MyBatis
关于MyBatis,大部分人都很熟悉。MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
不管是DDD(Domain Driven Design,领域驱动建模)还是分层架构的风格,都会涉及到对数据库持久层的操作,本文将会讲解Spring Boot集成MyBatis如何实现通用Mapper。
Spring Boot集成MyBatis
引入依赖
1 <dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter</artifactId>
4 </dependency>
5
6 <dependency>
7 <groupId>org.springframework.boot</groupId>
8 <artifactId>spring-boot-starter-web</artifactId>
9 </dependency>
10
11 <dependency>
12 <groupId>org.mybatis.spring.boot</groupId>
13 <artifactId>mybatis-spring-boot-starter</artifactId>
14 <version>1.3.1</version>
15 </dependency>
16
17 <dependency>
18 <groupId>mysql</groupId>
19 <artifactId>mysql-connector-java</artifactId>
20 </dependency>
21 <dependency>
22 <groupId>org.projectlombok</groupId>
23 <artifactId>lombok</artifactId>
24 </dependency>
25
26 <dependency>
27 <groupId>com.zaxxer</groupId>
28 <artifactId>HikariCP</artifactId>
29 </dependency>
复制
可以看到如上关于Mybatis引入了
mybatis-spring-boot-starter
,由Mybatis提供的starter。
数据库配置
在application.yml中增加如下配置:
1spring:
2 datasource:
3 hikari:
4 connection-test-query: SELECT 1
5 minimum-idle: 1
6 maximum-pool-size: 5
7 pool-name: dbcp1
8 driver-class-name: com.mysql.jdbc.Driver
9 url: jdbc:mysql://localhost:3306/test?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=utf-8
10 username: user
11 password: pwd
12 type: com.zaxxer.hikari.HikariDataSource
13 schema[0]: classpath:/init.sql
14 initialize: true
复制
可以看到,我们配置了hikari和数据库的基本信息。在应用服务启动时,会自动初始化classpath下的sql脚本。
1CREATE TABLE IF NOT EXISTS `test` (
2 `id` bigint(20) unsigned NOT NULL,
3 `local_name` varchar(128) NOT NULL ,
4 PRIMARY KEY (`id`)
5) ENGINE=InnoDB DEFAULT CHARSET=utf8;
复制
在sql脚本中,我们创建了一张
test
表。
到这里,后面我们一般需要配置Mybatis映射的xml文件和实体类的路径。根据mybatis generator 自动生成代码。包括
XXMapper.java
,
XXEntity.java
,
XXMapper.xml
。这里我们就不演示了,直接进入下一步的通用Mapper实现。
通用Mapper的使用
引入依赖
1 <dependency>
2 <groupId>tk.mybatis</groupId>
3 <artifactId>mapper</artifactId>
4 <version>3.4.0</version>
5 </dependency>
复制
通用Mapper的作者abel533,有兴趣可阅读源码。
配置通用Mapper
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3import tk.mybatis.spring.mapper.MapperScannerConfigurer;
4
5import java.util.Properties;
6
7@Configuration
8public class MyBatisMapperScannerConfig {
9 @Bean
10 public MapperScannerConfigurer mapperScannerConfigurer() {
11 MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
12 mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
13 mapperScannerConfigurer.setBasePackage("com.blueskykong.mybatis.dao");//扫描该路径下的dao
14 Properties properties = new Properties();
15 properties.setProperty("mappers", "com.blueskykong.mybatis.config.BaseDao");//通用dao
16 properties.setProperty("notEmpty", "false");
17 properties.setProperty("IDENTITY", "MYSQL");
18 mapperScannerConfigurer.setProperties(properties);
19 return mapperScannerConfigurer;
20 }
21}
复制
在配置中,设定了指定路径下的dao,并指定了通用dao。需要注意的是,
MapperScannerConfigurer
来自于
tk.mybatis.spring.mapper
包下。
BaseDao
1import tk.mybatis.mapper.common.Mapper;
2import tk.mybatis.mapper.common.MySqlMapper;
3
4public interface BaseDao<T> extends Mapper<T>,MySqlMapper<T>{
5
6}
复制
通用Mapper接口,其他接口继承该接口即可。
创建实体
我们需要添加
test
表对应的实体。
1@Data
2@Table(name = "test")
3@AllArgsConstructor
4@NoArgsConstructor
5public class TestModel {
6
7 @Id
8 @Column(name = "id")
9 @GeneratedValue(strategy = GenerationType.IDENTITY)
10 private Integer id;
11
12 private String localName;
13}
复制
其中,
@Table(name = "test")
注解指定了该实体对应的数据库表名。
配置文件
1mybatis:
2 configuration:
3 map-underscore-to-camel-case: true
复制
为了更好地映射Java实体和数据库字段,我们指定下划线驼峰法的映射配置。
TestDao编写
1public interface TestDao extends BaseDao<TestModel> {
2
3
4 @Insert("insert into test(id, local_name) values(#{id}, #{localName})")
5 Integer insertTestModel(TestModel testModel);
6}
复制
TestDao
继承自
BaseDao
,并指定了泛型为对应的
TestModel
。
TestDao
包含继承的方法,如:
1 int deleteByPrimaryKey(Integer userId);
2
3 int insert(User record);
4
5 int insertSelective(User record);
6
7 User selectByPrimaryKey(Integer userId);
8
9 int updateByPrimaryKeySelective(User record);
10
11 int updateByPrimaryKey(User record);
复制
还可以自定义一些方法,我们在上面自定义了一个
insertTestModel
方法。
Service层和控制层
本文略过这两层,比较简单,读者可以参见本文对应的源码地址。
结果验证
我们在插入一条数据之后,查询对应的实体。对应执行的结果也都是成功,可以看到控制台的如下日志信息:
1c.b.mybatis.dao.TestDao.insertTestModel : ==> Preparing: insert into test(id, local_name) values(?, ?)
2c.b.mybatis.dao.TestDao.insertTestModel : ==> Parameters: 5953(Integer), testName(String)
3c.b.mybatis.dao.TestDao.insertTestModel : <== Updates: 1
4c.b.m.dao.TestDao.selectByPrimaryKey : ==> Preparing: SELECT id,local_name FROM test WHERE id = ?
5c.b.m.dao.TestDao.selectByPrimaryKey : ==> Parameters: 5953(Integer)
6c.b.m.dao.TestDao.selectByPrimaryKey : <== Total: 1
复制
Spring Boot集成MyBatis实现通用Mapper到此就大功告成。
小结
MyBatis是持久层非常常用的组件,Spring Boot倡导约定优于配置,特别是很多xml的配置。当然还有很多同学使用Spring Data。相比而言,我觉得MyBatis的SQL比Spring Data更加灵活,至于具体特性的比较不在此讨论。
本文对应的源码地址: https://github.com/keets2012/Spring-Boot-Samples/tree/master/mybatis-demo
参考
- abel533/Mapper,https://github.com/abel533/Mapper
-
配置Spring Boot集成MyBatis、通用Mapper、Quartz、PageHelper
https://www.jianshu.com/p/cf43176067d8