在这里插入图片描述

1. 简介

1.1 MybatisPlus

MyBatis-Plus(简称MP)是一款非常强大的MyBatis增强工具包,只做增强不做改变。在不用编写任何SQL语句的情况下即可以极其方便的实现单一、批量、分页等操作。

1.2 代码及文档发布地址

官方地址:http://mp.baomidou.com
代码发布地址:
Github: https://github.com/baomidou/mybatis-plus
Gitee: https://gitee.com/baomidou/mybatis-plus
文档发布地址:http://mp.baomidou.com/#/?id=%E7%AE%80%E4%BB%8B

2. 集成MP

2.1 依赖配置

1)在 pom.xml 中加入对 MP依赖

1
2
3
4
5
6
<!-- mp 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.3</version>
</dependency>

* Mybatis-Plus依赖已经集成了Mybatis和Mybatis-Spring的依赖,所有不需要导入这两个依赖
2)其他文件,包括Mybatis的主配置文件和spring整合Mybatis的配置文件与使用Mybatis时没有太大区别。想要集成Mybatis-Plus非常简单,对于 Spring,仅仅需要把 Mybatis 自带的MybatisSqlSessionFactoryBean 替换为 MP 自带的即可。
在这里插入图片描述

2.2 依赖与配置

1) 在pom.xml中加入对MP、Spring、连接池、Junit、Mysql 驱动等依赖

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
38
39
40
41
<!-- mp 依赖 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>2.3</version>
</dependency>
<!--junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.37</version>
</dependency>
<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.10.RELEASE</version>
</dependency>

2) 加入 MyBatis 的全局配置文件

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

</configuration>

3) 加入log4j.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/>
</layout>
</appender>
<logger name="java.sql">
<level value="debug"/>
</logger>
<logger name="org.apache.ibatis">
<level value="info"/>
</logger>
<root>
<level value="debug"/>
<appender-ref ref="STDOUT"/>
</root>
</log4j:configuration>

4) 加入db.properties连接信息配置

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mp
jdbc.username=root
jdbc.password=1234

5) 加入spring的配置文件 applicationContext.xml

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">

<!-- 数据源 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

<!-- 事务管理器 -->
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 基于注解的事务管理 -->
<!-- <tx:annotation-drivern transaction-manager="dataSourceTransactionManager"/>-->
<tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>

<!-- 配置SqlSessionFactoryBea -->
<!-- <bean id="sqlSessionFactoryBean"-->
<!-- class="org.mybatis.spring.SqlSessionFactoryBean">-->
<bean id="sqlSessionFactoryBean"
class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" value="com.mp.domain"></property>
<!-- 注入全局策略配置 -->
<property name="globalConfig" ref="globalConfiguration"></property>
</bean>

<!-- 定义MybatisPlus的全局策略配置 -->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
</bean>

<!-- 配置mybatis 扫描mapper接口的路径 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.mp.mapper"></property>
</bean>
</beans>

3. 通用CRUD

3.1 Mybatis与Mybatis-Plus实现方式比较

1)基于 Mybatis
需要编写 xxxMapper 接口,并手动编写 CRUD 方法
提供xxxMapper.xml 映射文件,并手动编写每个方法对应的 SQL 语句
2)基于 MP
只需要创建 xxxMapper 接口, 并继承 BaseMapper 接口
这就是使用 MP需要完成的所有操作,甚至不需要创建 SQL 映射文件

3.2 操作示例

创建一个Mapper接口并继承BaseMapper,即可实现大部分单CRUD操作。
BaseMapper 提供了多达 17 个方法给大家使用, 可以极其方便的实现单一、批量、分页等操作。
多表操作或者其他CRUD操作可以通过创建xxxMapper.xml配置文件自行增加。
在这里插入图片描述
* MP在启动时会挨个分析xxxMapper中的方法,并且将对应的SQL语句处理后,保存到configuration对象中的mapperStatements中,所有只要继承BaseMapper就可以无须编写SQL语句直接使用方法。

4. 条件构造器 EntityWrapper

4.1 EntityWrapper简介

1) Mybatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担,能够有效提高开发效率
2) 实体包装器,主要用于处理 sql 拼接,排序,实体参数查询等
3) 注意: 使用的是数据库字段,不是 Java 属性!
4) 条件参数说明:
在这里插入图片描述

4.2 操作示例

1)EntityWrapper方式

1
2
3
4
5
6
7
8
9
@Test
public void testEntityWrapperSelect(){
//EntityWrapper 分页查询数据库中年龄在10~22之间,性别为女,姓名为周慧敏的数据
List<Employee> employees = employeeMapper.selectPage(new Page<Integer>(1, 5),
new EntityWrapper<Employee>().between("age", 10, 22)
.eq("gender", 0)
.eq("last_name", "周慧敏")
);
}

2)Condition方法

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testConditionSelect(){
//Condition 分页查询数据库中年龄在10~22之间,性别为女,姓名为周慧敏的数据
List<Employee> emps = employeeMapper.selectPage(
new Page<Integer>(1, 2),
Condition.create()
.between("age", 10, 22)
.eq("gender", 0)
.eq("last_name", "周慧敏")
);
}

5. ActiveRecord(活动记录)

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
ActiveRecord 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于 ActiveRecord 往往只能感叹其优雅,所以 MP 也在 AR 道路上进行了一定的探索

5.1 AR模式的使用

仅仅需要让实体类继承 Model 类且实现主键指定方法,即可开启 AR 之旅

1
2
3
4
5
6
7
8
9
10
@TableName("tbl_employee")
public class Employee extends Model<Employee>{
// .. fields
// .. getter and setter

@Override
protected Serializable pkVal() {
return this.id;
}
}

实体类继承Model类后,重写pkVal()方法,返回实体类的主键。既可以直接使用Model类中的方法进行CRUD操作

1
2
3
4
5
6
7
8
9
10
11
@Test
public void testARInsert(){
Employee employee = new Employee();
employee.setLastName("周慧敏");
employee.setEmail("zhm@li.cm");
employee.setGender(0);
employee.setAge(18);

boolean result = employee.insert();
System.out.println(result);
}

5.2 AR基本CRUD

1) 插入操作
public boolean insert()
2) 修改操作
public boolean updateById()
3) 查询操作
public T selectById()
public T selectById(Serializable id)
public List selectAll()
public List selectList(Wrapper wrapper)
public int selectCount(Wrapper wrapper)
4) 删除操作
public boolean deleteById()
public boolean deleteById(Serializable id)
public boolean delete(Wrapper wrapper)
5) 分页复杂操作
public Page selectPage(Page page, Wrapper wrapper)

5.3 AR 小结

AR 模式提供了一种更加便捷的方式实现 CRUD 操作,其本质还是调用的 Mybatis 对
应的方法,类似于语法糖(语法糖是指计算机语言中添加的某种语法,这种语法对原本语言的功能并没有影响.
可以更方便开发者使用,可以避免出错的机会,让程序可读性更好)

6. 代码生成器

1) MP 提供了大量的自定义设置,生成的代码完全能够满足各类型的需求
2) MP 的代码生成器和Mybatis MBG代码生成器: MP的代码生成器都是基于java代码来生成。MBG 基于xml文件进行代码生成
MyBatis的代码生成器可生成: 实体类、Mapper 接口、Mapper 映射文件
MP的代码生成器可生成: 实体类(可以选择是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 层、Controller 层
3) 表及字段命名策略选择
在MP中,我们建议数据库表名 和 表字段名采用驼峰命名方式,如果采用下划线命名方式 请开启全局下划线开关,如果表名字段名命名方式不一致请注解指定,最好保持一致。这么做的原因是为了避免在对应实体类时产生的性能损耗,这样字段不用做映射就能直接和实体类对应。当然如果项目里不用考虑这点性能损耗,那么采用下滑线也是没问题的,只需要在生成代码时配置 dbColumnUnderline 属性就可以

6.1 代码生成器依赖

1) 模板引擎
MP的代码生成器默认使用的是Apache的Velocity模板,当然也可以更换为别的模板技术,例如freemarker。此处不做过多的介绍。
需要加入 Apache Velocity 的依赖

1
2
3
4
5
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>

2) 加入 slf4j,查看日志输出信息

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>

6.2 示例代码

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
38
39
40
41
42
43
44
45
46
public class TestConfig {

@Test
public void testGenerator(){
//1.全局配置
GlobalConfig config = new GlobalConfig();
config.setActiveRecord(true) //是否支持AR模式
.setAuthor("Shadow") //作者
.setOutputDir("D:\\Program Files\\JetBrains\\mp03\\src\\main\\java") //生成路径
.setFileOverride(true) //文件覆盖
.setIdType(IdType.AUTO) //主键策略
.setServiceName("%sService") //设置生成的service接口的名字的首字母是否为I
.setBaseResultMap(true) //生成ResultMap
.setBaseColumnList(true); //生成sql片段
//2.数据源配置
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL) //设置数据库类型
.setDriverName("com.mysql.cj.jdbc.Driver")
.setUrl("jdbc:mysql://localhost:3306/mp?serverTimezone=UTC")
.setUsername("root")
.setPassword("123456");
//3.策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setCapitalMode(true) //全局大写命名
.setDbColumnUnderline(true) //指定表名 字段名是否使用下划线
.setNaming(NamingStrategy.underline_to_camel) //数据库表映射到实体的命名策略
.setTablePrefix("tbl_") //表的前缀
.setInclude("tbl_employee"); //生成的表
//4.包名策略配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("com.mp")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("domain")
.setXml("mapper");
//5.整合配置
AutoGenerator autoGenerator = new AutoGenerator();
autoGenerator.setGlobalConfig(config)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(packageConfig);
//6.执行
autoGenerator.execute();
}
}

6.3 ServiceImpl说明

代码生成器生成的xxxServiceImpl会继承ServiceImpl类,mybatis-plus通过这种方式为我们注入了xxxMapper,这样可以使用service层默认为我们提供的很多方法,也可以调用我们自己在 dao层编写的操作数据库的方法

7. 插件扩展

7.1 Mybatis 插件机制简介

1) 插件机制:Mybatis通过插件(Interceptor)可以做到拦截四大对象相关方法的执行,根据需求,完成相关数据的动态改变。
Executor
StatementHandler
ParameterHandler
ResultSetHandler
2) 插件原理
四大对象的每个对象在创建时,都会执行 interceptorChain.pluginAll(),会经过每个插件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理

7.2 插件注册

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
<!-- 配置SqlSessionFactoryBea -->
<bean id="sqlSessionFactoryBean"
class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" value="com.mp.domain"></property>

<!-- 注入全局策略配置 -->
<property name="globalConfig" ref="globalConfiguration"></property>
<!-- 注册插件 -->
<property name="plugins">
<list>
<!-- 注册分页插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
<!-- 注册执行分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property>
</bean>
<!-- 注册性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<property name="format" value="true"></property>
<!--<property name="maxTime" value="5"></property>-->
</bean>
<!-- 注册乐观锁插件 -->
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor"></bean>
</list>
</property>
</bean>

8. 自定义全局操作

根据MybatisPlus的AutoSqlInjector可以自定义各种你想要的SQL,注入到全局中,相当于自定义Mybatisplus自动注入的方法。
之前需要在xml中进行配置的SQL语句,现在通过扩展AutoSqlInjector在加载Mybatis环境时就注入。

8.1 AutoSqlInjector

1) 在Mapper接口中定义相关的CRUD方法
2) 扩展AutoSqlInjector inject方法,实现Mapper接口中方法要注入的SQL
3) 在MP全局策略中,配置自定义注入器

8.2 自定义注入器的应用之逻辑删除

假删除、逻辑删除:并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态
tbl_user logic_flag = 1 → -1

1) com.baomidou.mybatisplus.mapper.LogicSqlInjector
2) logicDeleteValue逻辑删除全局值
3) logicNotDeleteValue逻辑未删除全局值
4) 在POJO的逻辑删除字段添加@TableLogic注解
5) 会在mp自带查询和更新方法的sql 后面,追加『逻辑删除字段』=『LogicNotDeleteValue默认值』 删除方法:deleteById()和其他delete方法,底层SQL调用的是update tbl_xxx set 『逻辑删除字段』=『logicDeleteValue 默认值』

9. 公共字段自动填充

9.1 元数据处理器接口

com.baomidou.mybatisplus.mapper.MetaObjectHandler
insertFill(MetaObject metaObject)
updateFill(MetaObject metaObject)
metaobject:元对象是Mybatis提供的一个用于更加方便,更加优雅的访问对象的属性,给对象的属性设置值 的一个对象. 还会用于包装对象,支持对 Object 、Map、Collection等对象进行包装。本质上metaObject获取对象的属性值或者是给对象的属性设置值,最终是要通过 Reflector获取到属性的对应方法的Invoker,最终 invoke.

9.2 开发步骤

1) 注解填充字段 @TableFile(fill = FieldFill.INSERT) 查看 FieldFill
2) 自定义公共字段填充处理器
3) MP全局注入自定义公共字段填充处理器

10. Oracle主键 Sequence

MySQL:支持主键自增(IdType.Auto)
Oracle:序列(Sequence)

1) 实体类配置主键 Sequence @KeySequence(value=”序列名”,clazz=xxx.class 主键属性类型)
2) 全局MP主键生成策略为 IdType.INPUT
3) 全局MP中配置 Oracle 主键Sequence
com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
4) 可以将@keySequence 定义在父类中,可实现多个子类对应的多个表公用一个Sequence