网上的有关Spring Boot整合Mybatis的案例有很多,很少有发现解释详细的整合过程,下面是我自己整合的一个小案例,以备参考。
基于配置
以最少的配置整合Mybatis是我一直追求的,对于Mybatis来说,整合无非包括三个方面,xml配置和对应的mapper接口以及事物的配置。因此,我们所需要配置的是mapper.xml文件的路径配置以及mapper接口的所需扫描的包以及对事物的配置。
因为Spring Boot没有默认的配置Mybatis的依赖,我们要使用Mybatis必须需要它的相关的jar包,需要我们在pom文件中添加Mybatis的依赖,作者进行研究的时候,Mybatis在中央仓库的最高版本为3.5.1,在可配置如下:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
配置了以后,发现在application.properties文件中找不到mybatis的属性,我想既然是spring项目,自然要和spring进行整合,单纯的mybatis的jar可能不够,可能是缺少依赖导致的,由此,我查询了一下,mybatis与spring整合的过程可能需要mybatis-spring的jar包,因此我添加了mybatis-spring的jar包依赖。
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
再次尝试,依然不行,我思索了一下整合jpa的配置,它是直接和Sping Boot进行整合的,只需要配置相应的依赖即可,然后我想到Spring Boot是一个单独的项目,mybatis-spring只是和spring有关,但和spring boot是没有关联的,于是我思考着能不能让mybatis直接与Spring Boot进行整合,经过度娘一下,发现果然有这样的配置,可参考如下:
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
这样配置以后,果然在配置文件中有了mybatis的属性,我查看了一下mybatis-spring-boot-starter的pom文件,发现了它拥有着mybatis与mybatis-spring的依赖,根据maven的依赖传递性,我删除了mybatis与mybatis-spring的依赖配置,仅仅配置如上,查看依赖的jar,果然会自动依赖这两个jar,因此,在pom文件中仅需配置mybatis-spring-boot-starter的依赖即可。
配置xml
配置mapper.xml,在application.properties配置文件中添加如下配置
mybatis.mapper-locations=classpath:mapping/*.xml
配置Mapper
在Mapper接口上添加@Mapper注解即可。
如果mapper接口过多,嫌弃@Mapper麻烦的话,可以在执行的main方法的类上添加注解@MapperScan进行配置。
代码示例
DemoUser.java是由之前的JPA配置时使用,没有进行更改,如下所示,读者参考的时候可以将下面的注解全部去掉。
package com.example.demo.entity;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "DEMO_USER")
public class DemoUser {
@Id
@Column(name = "ID", length = 10, nullable = false)
private Integer id;
@Column(name = "NAME", length = 40, nullable = false)
private String name;
@Column(name = "SEX", length = 1, nullable = true)
private String sex;
@Column(name = "CREATEDATE", nullable = false)
private Date createDate;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getCreateDate() {
return createDate;
}
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
@Override
public String toString() {
return "DemoUser [id=" + id + ", name=" + name + ", sex=" + sex + ", createDate=" + createDate + "]";
}
}
DemoUserMapper.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.example.demo.dao.DemoUserMapper">
<select id="selectDemoUser"
resultType="com.example.demo.entity.DemoUser">
SELECT ID AS "id",
NAME AS "name",
SEX AS "sex",
CREATEDATE AS"createDate"
FROM DEMO_USER
</select>
</mapper>
DemoUserMapper.java如下:
package com.example.demo.dao;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.example.demo.entity.DemoUser;
@Mapper
public interface DemoUserMapper {
List<DemoUser> selectDemoUser();
}
在不配置事物的情况下,我做了查询测试,和之前所测的整合jpa基本一致。
启动服务,在浏览器输入以下地址,进入Controller,
http://localhost:8080/testMybatis
结果如下:
DemoUser [id=2, name=李四, sex=0, createDate=Thu Apr 25 11:57:22 CST 2019]
DemoUser [id=1, name=张三, sex=1, createDate=Thu Apr 25 12:01:51 CST 2019]
DemoUser [id=3, name=王五, sex=0, createDate=Thu Apr 25 12:03:00 CST 2019]
如上则为最简单的Spring Boot整合Mybatis完毕。
下面为不在mapper接口上加@Mapper注解,在执行类上加上扫描包配置注解@MapperScan进行配置,如下:
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan(basePackages= {"com.example.demo.dao"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
执行结果一致,因此,可以二者选其一即可。
事物
默认
由于不太清楚Spring Boot是否默认会进行事物提交,于是我写了一个插表的操作进行了测试,发现在默认情况下,Mapper接口中的操作是可以提交的。由于我们经常需要对许多张表进行操作,需要保持这几张表的一致性,根据事物中的一致性的特性,我们可以使用事物进行配置。于是,我尝试在一个Controller里同时调用两个Mapper,第一个使正常通过,第二个让其报错回滚,进行测试后发现,第一个事物正常提交,第二个事物回滚,与预期不符。那么,如何保证这两个事物的一致性呢?
配置事物
我们之前使用spring的时候,常常使用@Transactional注解,于是,抱着试试的态度,看看是否能使用该注解,结果不出所料,果然依赖了spring-tx的jar包中有着事物注解的类org.springframework.transaction.annotation.Transactional。
那么该依赖是怎么来的呢?因为pom文件中,我们是没有进行配置的,那么肯定是某个依赖给引进过来的。刚开始的时候,我发现pom文件总共就依赖了四个,分别是spring-boot-starter,spring-boot-starter-web,spring-boot-devtools,mybatis-spring-boot-starter。于是我尝试着一个个点进去查找,发现这个工作量可不是看起来那么easy,每一个都包络万象,我放弃了,因为我尝试着点了五六个之后,并没有发现什么。利用著名的二分法,我逆向干掉了后两个依赖,其实,当我只干掉最后一个的时候,就已经找到了答案,spring-tx的jar是由mybatis-spring-boot-starter依赖引入的。至于具体的是其依赖下的哪个依赖引入的,有兴趣的可以去找一找,我尝试过,后来放弃了,因为太恶心了。
由此可以发现,mybatis-spring-boot-starter自动装配了事物,不过值得注意的是在类的public方法中@Transactional注解起作用,但是在其他如private、protected和default作用域不起作用,那么如何在这些作用域中配置事物呢?
作者自己度娘了一下spring boot事物的配置,发现有好多示例除了@Transactional注解之外,另外在启动类上新加了@EnableTransactionManagement事物管理的注解,我尝试了一下,重新启动了项目,执行后发现,对私有方法,@Transactional注解依旧不起作用。
本人是在Spring Boot与Mybatis整合的Controller里进行测试的,由此得出结论可能与各位研究的不同,就本次测试而言可以得出以下结论:简单的事物配置仅需在被public修饰的类或方法上添加@Transactional注解即可。具体的事物属性设置不在此次研究之列,如对事物有兴趣研究,可参见其他文章。