此文章假定您对Spring Boot和REST API比较了解。它将帮助您将MyBatis集成到Spring-Boot项目中,并开发一些与MySQL数据库进行交互的示例。在本教程的最后,您将拥有创建与关系数据库的基本交互(包括事务和池大小限制)以及与 MySQL 数据库的交互进行单元测试所需的全部功能。
对于本教程,我们将先创建一个Spring Boot 的基本实例
快速创建实例
前往 https://start.spring.io/ 如下所示
点击GENERATE
生产一个zip解压导入IDEA工具即可
当然我们还需要创建 MySQL 数据库用来运行到你的 MacOS/Linux/win 等系统
初始化我们的数据库
resources/init.sql
脚本将为您初始化数据库结构与数据:
CREATE DATABASE IF NOT EXISTS `spring_boot` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `spring_boot`;
DROP TABLE IF EXISTS `mybatis_test`;
CREATE TABLE `mybatis_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(255) NOT NULL,
`en_name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `mybatis_test` VALUES (1,'郭耶斯','Yes.Guo'),(2,'郭莫拉','Mola.Guo');
创建mybatis_test实体
@Data
public class MybatisTest implements Serializable {
private static final long serialVersionUID = 8897018268303812871L;
private Long id;
private String firstName;
private String enName;
}
集成MyBatis并配置Spring数据源
首先,我们添加一些需要的依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- Database -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.14</version>
</dependency>
lombok依赖帮你省去了额外的getter或者equals方法。
mybatis-spring-boot-starter依赖将MyBatis添加到您的项目中。
mysql-connector-java依赖提供了与MySQL 数据库通信所需的驱动程序。
如果使用其他数据库,则需要其他依赖。
接下来,我们需要配置我们的数据源(在application.properties中),这将使我们能够以最少的配置轻松配置事务管理,池大小和连接超时以及许多其他内容:
spring.datasource.url=jdbc:mysql://alibaba.com:3306/spring_boot?useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.hikari.maximum-pool-size=10
代码中的服务器地址自行更换本地的。
这是我们在运行时连接到数据库所需的全部信息,现在让我们学习如何创建 MyBatis Mappers。
创建 Mappers
Mappers 是允许我们将SQL查询映射到Java方法的接口。映射有两种类型:
- 注解驱动(最简单)
- XML(对于复杂和/或动态查询更好)
我们会在本文中学到两者,但让我们从更简单的注解驱动映射开始。
注解驱动的映射器
创建以下 TestMapper.java 接口,该接口定义了两个查询映射和一个插入映射:
@Mapper
public interface TestMapper {
@Select("SELECT id, first_name as firstName, en_name as enName FROM mybatis_test WHERE id = #{id}")
MybatisTest selectOne(long id);
@Select("SELECT id, first_name as firstName, en_name as enName FROM mybatis_test")
List<MybatisTest> findAll();
@Insert("INSERT INTO mybatis_test (id, first_name, en_name) VALUES (#{id}, #{firstName}, #{enName})")
// 将对象ID设置为数据库中生成的ID
@Options(useGeneratedKeys = true, keyColumn = "id", keyProperty = "id")
void insertMybatisTest(MybatisTest mybatisTest);
}
类上方的 @Mapper 注释告诉MyBatis该接口是一个映射器。
方法签名上方的 @Select 和 @Insert 批注指示我们正在映射的查询类型。根据查询的类型,MyBatis提供不同的选项(insertMybatisTest()上方的@Options批注中所示),但是@Select和@Insert之间的最大区别是@Select返回一个或多个记录,而@Insert仅返回受影响的行数。
每个方法的结构都非常简单,对于熟悉Hibernate的人来说看起来会很熟悉:批注中的查询绑定到Java方法。现在,您可以将映射器自动连接到另一个类,以调用查询数据库。下面我们来尝试一下。
创建业务接口以及其实现类
TestService.java
public interface TestService {
MybatisTest getMybatisTestById(Long id);
void createMybatisTest(final MybatisTest mybatisTest);
List<MybatisTest> getMybatisTests();
}
TestServiceImpl.java
@Service
public class TestServiceImpl implements TestService {
private TestMapper testMapper;
@Autowired
public void setTestMapper(TestMapper testMapper) {
this.testMapper = testMapper;
}
@Override
public MybatisTest getMybatisTestById(Long id) {
return testMapper.selectOne(id);
}
@Override
public List<MybatisTest> getMybatisTests() {
return testMapper.findAll();
}
@Override
public void createMybatisTest(final MybatisTest mybatisTest) {
testMapper.insertMybatisTest(mybatisTest);
}
}
控制层用来调用业务接口
tips:编写控制层的Controller需要引入spring-boot-starter-web依赖到pom.xml中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
TestController.java
@RequestMapping("/test")
@RestController
public class TestController {
private TestService testService;
@Autowired
public void setTestService(TestService testService) {
this.testService = testService;
}
@GetMapping("getById/{id}")
public MybatisTest getClient(@PathVariable("id") final Long id) {
return testService.getMybatisTestById(id);
}
@PostMapping("add")
public ResponseBean createClient(@RequestBody MybatisTest mybatisTest) {
testService.createMybatisTest(mybatisTest);
return ResponseBean.ok();
}
}
附上sponseBean.java
@Data
public class ResponseBean {
private Integer status;
private String msg;
private Object data;
public static ResponseBean build() {
return new ResponseBean();
}
public static ResponseBean ok() {
return new ResponseBean(200, "success", null);
}
public static ResponseBean ok(String msg) {
return new ResponseBean(200, msg, null);
}
public static ResponseBean ok(String msg, Object obj) {
return new ResponseBean(200, msg, obj);
}
public static ResponseBean error(String msg) {
return new ResponseBean(500, msg, null);
}
public static ResponseBean error(String msg, Object obj) {
return new ResponseBean(500, msg, obj);
}
private ResponseBean() {
}
private ResponseBean(Integer status, String msg, Object obj) {
this.status = status;
this.msg = msg;
this.data = obj;
}
}
现在我们可以启动项目并测试了
测试接口
postman是一个很好地测试工具,现在我们访问http://localhost:8080/test/getById/1 ,您应该看到以下结果:
{
"id": 1,
"firstName": "郭耶斯",
"enName": "Yes.Guo"
}
让我们测试一下create方法。使用以下JSON向http://localhost:8080/test/add 发出POST请求:
{
"id": 3,
"firstName": "狗兔子",
"enName": "Rabbit.Dog"
}
您应该获得HTTP 200响应。要检查数据是否已正确创建,请再次尝试GET访问http://localhost:8080/test/getById/3 ,您会看到以下的访问结果证明数据已经添加:
XML 映射器
既然我们已经介绍了注释驱动的映射器,我们将使用XML实现一个更复杂的映射器。这使得使我们能够根据用户名进行查询数据。
文件路径应为 resources/mapper/TestMapper.xml 如下所示:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.github.demo.mapper.TestMapper">
<select id="findByFirstName" resultType="MybatisTest" parameterType="java.lang.String">
SELECT
id,
first_name as firstName,
en_name as enName
FROM mybatis_test
WHERE first_name = #{value}
</select>
</mapper>
要注意的事情:
在第3行,我们告诉MyBatis哪个映射器接口将开放此查询。
在select标记中,resultType属性告诉MyBatis将返回结果定为 MybatisTest 实体对象,而parameterType告诉它入参为字符串。
现在我们必须告诉MyBatis在哪里可以找到XML映射器,因此将其添加到application.properties中:
mybatis.mapper-locations= classpath*:/mybatis/*.xml # 告诉mybatis查找 resources/mybatis 用于XML映射器
mybatis.type-aliases-package= com.github.demo.model # 告诉mybatis在正确的包中寻找我们的实体类
下一步是返回 XXXMapper 界面,并创建与我们的XML映射器中的查询一致的方法名。
将以下内容添加到 TestMapper.java 中:
List<MybatisTest> findByFirstName(String value);
方法的名称应对应于我们在XML映射器中编写的查询的id属性。同样,它应该使用String参数,并且由于许多firstName可能具有相同的名字(即,数据库中的first_name列不是UNIQUE),因此我们应使其返回一个List。
现在,您可以像其他任何方法一样通过调用findByFirstName执行此查询。
我将其添加到业务层以及控制层,以便您可以通过HTTP POST进行测试
事务配置
Spring已经具有出色的事务管理,我们可以在MyBatis上花费最少的精力来利用它。只需将以下注解添加到您的Application类:
@EnableTransactionManagement
现在就这样。当然,像所有Spring功能一样,用于事务管理的配置选项有很多,但是我们在本文开头编写的数据源配置足以为Spring提供在方法级别创建事务的方法。
在我们想要使用他们的地方,要使方法具有事务性,只需向其添加 @Transactional 批注。
如今,Spring的默认数据源实现是Hikari。您可以从他们的Github中找到有关该项目的更多信息,您可以在其中找到许多自定义选项。