前言
很多人在做ORM框架选型的时候,都在犹豫:Mybatis、Mybatis plus、Spring data JPA 如何选?尤其是Mybatis系列和Spring data JPA如何选。经过笔者在实际项目中使用,极力推荐Mybatis plus。理由如下:
- Spring data JPA 提供标准化API,如MySQL、Oracle、Elasticsearch都支持。一些简单的CURD撸起代码来还是很爽。但复杂的查询,比起Mybatis Plus、Nutz等ORM框架,复杂很多,没那么容易上手。另外,自定义SQL方面,复杂一点的SQL,在注解里面来表达,很不美观,也不易于维护。
- Spring data JPA 底层是使用 Hibernate 的 JPA 技术实现,服务启动真的是巨慢无比,尤其是在表很多的时候。但应该有解决办法,当时没有时间研究。
- 如果选择了Mybatis、那何必不选择Mybatis plus呢?Mybatis plus只做增强不做改变,真的是润物细如声。很多简单的CURD直接条件构造器完成,省去了很多xml代码。如果又想写复杂的SQL秀一秀,可以去xml定义SQL,就跟Mybatis一样!
如何集成
Step1: 引入相关jar依赖
<!-- Spring Boot Mybatis plus 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- Spring Boot Dynamic Datasource 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>2.5.6</version>
</dependency>
<!-- MySQL 连接驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<!-- Druid 连接池管理依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.18</version>
</dependency>
Step2:数据源配置。我这里举例:db1-master、db1-slave、db2-slave这种在实际项目中遇到的场景:写主库、读从库,甚至还依赖别的库。
spring:
application:
name: spring-demo
# DB 配置
datasource:
dynamic:
primary: db1-master
p6spy: true
druid:
initial-size: 5
min-idle: 5
max-active: 20
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
validation-query-timeout: 2
filters: stat,wall,slf4j
datasource:
# db1-主库数据源
db1-master:
url: jdbc:mysql://localhost:3306/user?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true
username: root
password: 123456
# db1-从数据源
db1-slave:
url: jdbc:mysql://localhost:3306/user2?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&rewriteBatchedStatements=true
username: root
password: 123456
# db2-从数据源
db2-slave:
url: jdbc:mysql://localhost:3006/user3?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username: root
password: 123456
Step3:@MapperScan 声明。我这里放到了 MybatisPlusConfig 类里,如果你高兴,@MapperScan 也可以定义到启动的Main方法类里。
package com.yb.demo.config.db;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author daoshenzzg@163.com
* @date 2019-09-05 09:41
*/
@Configuration
@MapperScan({"com.yb.demo.dao.mapper"})
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
paginationInterceptor.setLimit(100);
return paginationInterceptor;
}
}
Step4:定义Model实体。@TableName 对应的就是表名,字段对应表的字段,表字段是下划线隔开,实体类直接是驼峰了,具体见配置文件:capital-mode: true。
package com.yb.demo.pojo.model.db1;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* @author daoshenzzg@163.com
* @date 2019-08-05 17:58
*/
@Data
@TableName("student")
public class Student1DO {
private Long id;
private String studName;
private Integer studAge;
private String studSex;
@TableField(fill = FieldFill.INSERT)
private Integer createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Integer updateTime;
}
Step5:自动填充。上面的 @TableField(fill = FieldFill.INSERT)、@TableField(fill = FieldFill.INSERT_UPDATE) 估计有同学就在好奇,这是干什么用的。这其实是Mybatis plus的自动填充注解标记。配置 MetaObjectHandler 使用,可以做到自动填充字段的效果。
package com.yb.demo.config.db;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
/**
* @author daoshenzzg@163.com
* @date 2019-09-04 17:08
*/
@Component
public class DefaultMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime", (int) System.currentTimeMillis() / 1000, metaObject);
this.setFieldValByName("updateTime", (int) System.currentTimeMillis() / 1000, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", (int) System.currentTimeMillis() / 1000, metaObject);
}
}
Step6:定义Mapper。其中@DS注解可以明确指定使用哪个数据源,用以实现动态数据源配置。如果是同一数据源,实体类都一样,只是有主从之分,如何切换呢?其实也简单:只需要在调用该mapper的service方法上加上 @DS("db1-master") 或 @DS("db1-slave") 就可以完成主从切换了。
package com.yb.demo.dao.mapper.db1;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yb.demo.pojo.model.db1.Student1DO;
import org.springframework.stereotype.Repository;
/**
* @author daoshenzzg@163.com
* @date 2019-08-05 17:56
*/
@DS("db1-master")
@Repository
public interface Student1Mapper extends BaseMapper<Student1DO> {
}
Step7:XML配置,如果你愿意,几乎不需要写任何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.yb.demo.dao.mapper.db1.Student1Mapper">
</mapper>
Step8:如何做到的呢?Mybatis plus 支持条件构造器。
@Slf4j
@Service
public class StudentService extends ServiceImpl<Student1Mapper, Student1DO> {
/**
* 学生列表
*
* @return
*/
public List<Student1DO> listStudent(String studName) {
QueryWrapper<Student1DO> queryWrapper = new QueryWrapper<>();
queryWrapper.like("student_name", studName);
return super.list(queryWrapper);
}
}
Step9:分页也不需要写任何xml代码!!
@Slf4j
@Service
public class StudentService extends ServiceImpl<Student1Mapper, Student1DO> {
/**
* 学生列表
*
* @return
*/
public IPage<Student1DO> listStudentByPage(String studName, int pageNum, int pageSize) {
Page<Student1DO> page = new Page<>(pageNum, pageSize);
QueryWrapper<Student1DO> queryWrapper = new QueryWrapper<>();
queryWrapper.like("student_name", studName);
return super.page(page, queryWrapper);
}
}
Step10:很关键的一步。@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
package com.yb.demo;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author daoshenzzg@163.com
* @date 2019-08-05 16:19
*/
@EnableTransactionManagement
@SpringBootApplication(exclude = DruidDataSourceAutoConfigure.class)
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
结束语
实际开发过程中,使用Mybatis plus基础的CURD方法及条件构造器,可以提升许多开发效率。