书成

再这样堕落下去就给我去死啊你这混蛋!!!

0%

SpringBoot整合Mybatis

Spring Boot 整合 Mybatis

Spring Boot 对于 Mybatis的整合十分方便,基本可以做到开箱即用。

Mybatis 配置

Mybatis 是基于 SqlSessionFactory 构建的框架,SqlSessionFactory 的作用是生成 SqlSession 接口对象,通过 SqlSession 对象操作数据库。在 Spring Boot 中,自动配置了上述两个对象,因此只需要关注业务代码即可。

在 Spring Boot 中,可以在配置文件中配置 SqlSessionFactory 对象,可配置的主要内容如下:

配置 作用
settings 对应于 xml 配置中的 settings 子标签
typeAliases 配置类型别名
typeHandlers 配置自定义类型处理器
plugins 配置拦截器
mappers 配置mapper

简单示例

首先新建一个 Spring Boot 项目,添加 MyBatis 依赖与 Mysql 依赖:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>

新建在项目中新建 model 包,在包中新建实体类 User 与性别枚举类 SexEnum 如下:

1
2
3
4
5
6
7
public class User {

private Long id;
private String name;
private SexEnum sex;
// 省略其它代码...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public enum SexEnum {

MALE(1,"男"),
FEMALE(2,"女");

private int id;
private String name;

SexEnum(int id, String name) {
this.id = id;
this.name = name;
}

public static SexEnum getEnumById(int id){
for (SexEnum sex : SexEnum.values()) {
if(sex.getId() == id)
return sex;
}
return null;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

然后新建一个 mapper 包,在包中创建 UserMapper 接口与 UserMapper.xml 如下:

1
2
3
4
5
6
7
@Repository
public interface UserMapper {

public int insertUser(User user);
public int updateUser(User user);
public User getUserById(Long id);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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="top.liuzhenhui.mybatisdemo.mapper.UserMapper">
<resultMap id="BaseResultMap" type="user">
<id column="id" property="id"></id>
<result column="name" property="name"></result>
<result column="sex" property="sex"></result>
</resultMap>
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into user (name, sex) values (#{name},#{sex})
</insert>
<select id="getUserById" resultMap="BaseResultMap">
select *
from user
where id = #{id}
</select>
<update id="updateUser">
update user
<set>
<if test="name != null and name.length() > 0">
name = #{name},
</if>
<if test="sex != null">
sex = #{sex}
</if>
</set>
where id = #{id}
</update>
</mapper>

由于 mapper 接口与 mapper.xml 都在 java 目录下的包中,需要在 pom.xml 中加入如下代码让 xml 文件能够被扫描到:

1
2
3
4
5
6
7
8
9
10
11
12
13
<build>
<resources>
<resource>
<directory>src/main/java/</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>

创建一个 dao 包,新建 UserDao 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class UserDao {

@Autowired
UserMapper userMapper;

public int insertUser(User user){
return userMapper.insertUser(user);
}
public int updateUser(User user){
return userMapper.updateUser(user);
}
public User getUserById(Long id){
return userMapper.getUserById(id);
}
}

由于 User 类中的性别是枚举类,需要编写一个类型转换器,新建 typehandler 包之后新建 SexTypeHandler 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// java类型
@MappedTypes(SexEnum.class)
// 数据库中存的类型
@MappedJdbcTypes(JdbcType.INTEGER)
public class SexHandler implements TypeHandler<SexEnum> {
@Override
public void setParameter(PreparedStatement preparedStatement, int i, SexEnum sexEnum, JdbcType jdbcType) throws SQLException {
// 为语句设置值
preparedStatement.setInt(i, sexEnum.getId());
}

@Override
public SexEnum getResult(ResultSet resultSet, String s) throws SQLException {
// s 代表 columnName
int sexId = resultSet.getInt(s);
if(sexId != 1 && sexId != 2) return null;
return SexEnum.getEnumById(sexId);
}

@Override
public SexEnum getResult(ResultSet resultSet, int i) throws SQLException {
int sexId = resultSet.getInt(i);
if(sexId != 1 && sexId != 2) return null;
return SexEnum.getEnumById(sexId);
}

@Override
public SexEnum getResult(CallableStatement callableStatement, int i) throws SQLException {
// 存储过程的类型转换
int sexId = callableStatement.getInt(i);
if(sexId != 1 && sexId != 2) return null;
return SexEnum.getEnumById(sexId);
}
}

在配置文件中加入如下配置:

1
2
3
4
5
6
7
8
9
10
# 数据库基础配置
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql:///mybatisdemo?useUnicode=true&characterEncoding=UTF-8

# 配置别名
mybatis.type-aliases-package=top.liuzhenhui.mybatisdemo.model
# 配置类型转换器
mybatis.type-handlers-package=top.liuzhenhui.mybatisdemo.typehandler

在数据库中新建对应的数据库与表之后在启动文件中加入 @MapperScan(basePackages = "top.liuzhenhui.mybatisdemo.mapper") 注解,之后在单元测试中分别测试各个方法是否能正确运行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@SpringBootTest
class MybatisdemoApplicationTests {

@Autowired
UserDao userDao;
@Test
void contextLoads() {
User user = new User();
user.setName("test4");
user.setSex(SexEnum.MALE);
userDao.insertUser(user);
System.out.println(user);
}
@Test
void testGetUserById(){
System.out.println(userDao.getUserById(1L));
System.out.println(userDao.getUserById(2L));
System.out.println(userDao.getUserById(3L));
System.out.println(userDao.getUserById(4L));
}
@Test
void updateUser(){
User user = new User();
user.setId(1l);
//user.setName("update1");
user.setSex(SexEnum.FEMALE);
userDao.updateUser(user);
System.out.println(userDao.getUserById(1L));
}
}

Mybatis 配置多数据源

有时候系统的数据库不止有一个,需要配置多个数据源,配置多个数据源关键在于要自己定义 SqlSessionFactory 以及 SqlSessionTemplate。然后用 @MapperScan 注解指定 SqlSessionFactory 以及 SqlSessionTemplate。

之后在使用的过程中用到哪个数据源就使用哪个 SqlSessionTemplate。