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
| @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 { 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.setSex(SexEnum.FEMALE); userDao.updateUser(user); System.out.println(userDao.getUserById(1L)); } }
|
Mybatis 配置多数据源
有时候系统的数据库不止有一个,需要配置多个数据源,配置多个数据源关键在于要自己定义 SqlSessionFactory 以及 SqlSessionTemplate。然后用 @MapperScan 注解指定 SqlSessionFactory 以及 SqlSessionTemplate。
之后在使用的过程中用到哪个数据源就使用哪个 SqlSessionTemplate。