MybatisPlus介绍
Mybatis-Plus是一个Mybatis的增强工具,在Myabtis的基础上只做增强不做改变,为简化开发,提高效率存在。
特性:

架构:

MybatisPlus快速入门
环境准备
Mybatis-plus3.0版本是基于JDK8,提供了lambda形式调用,要安装JDK8+,Maven。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.0</version>
</dependency>
在引入mybatisPlus之后不需要再引入mybatis和mybatis-spring,不如会出现依赖问题。
MyBatis 允许你在已映射语句执⾏过程中的某⼀点进⾏拦截调⽤。默认情况下,MyBatis 允许使⽤插件来拦截的⽅
法调⽤包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接⼝的部分⽅法,⽐如update,query,commit,rollback等⽅法,还有其他接⼝
的⼀些⽅法等。
总体概括为: - 拦截执⾏器的⽅法
- 拦截参数的处理
- 拦截结果集的处理
- 拦截Sql语法构建的处理
对于Mybatis整合MP有三个方法:Mybatis+MP,Spring+Mybatis+MP,SpringBoot+Mybatis+MP。
创建数据库表User
-- 创建测试表
DROP TABLE IF EXISTS tb_user;
CREATE TABLE user
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
age INT(11) NULL DEFAULT NULL COMMENT '年龄',
email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (id)
);
-- 插入测试数据
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
配置项目依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.guslegend</groupId>
<artifactId>MybatisPlusQuickStart</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>11</java.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.4.0</version>
</dependency>
<!--mysql驱动坐标-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.11</version>
</dependency>
<!--单元测试坐标-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--⽇志坐标-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<!--Lombok 坐标-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
</project>
Myabtis+MP
创建子Module
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.guslegend</groupId>
<artifactId>MybatisQucickStart</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>simple</artifactId>
</project>
配置日志文件log4j.properties
log4j.rootLogger=DEBUG,A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
原生Myabtis查询用户信息
实体类
@Data
@TableName("user")
public class UserDO {
private Long id;
private String name;
private Integer age;
private String email;
}
mapper
public interface UserMapper {
List<UserDO> findAll();
}
<?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>
<properties resource="jdbc.properties"></properties>
<typeAliases>
<typeAlias alias="UserDO" type="com.guslegend.model.UserDO"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
public class MPTest {
@Test
public void test1() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<UserDO> userDOList = userMapper.findAll();
for (UserDO userDO : userDOList){
System.out.println(userDO);
}
}
}
Mybatis+MP查询用户信息
我们首先要将UserMapper集成BaseMapper,使用BaseMapper里面的方法
public interface UserMapper extends BaseMapper<UserDO> {
}
@Test
public void test2() throws Exception{
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new
MybatisSqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<UserDO> userDOList = userMapper.selectList(null);
for (UserDO userDO : userDOList){
System.out.println(userDO);
}
}
注意:MybatisSqlSessionFactoryBuilder(),MP里面使用的是这个工厂。
SpringBoot+Mybatis+MP
配置maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- 降级到 3.2.x 版本(与 MyBatis-Plus 3.5.7 兼容性最优) -->
<version>3.2.10</version>
<relativePath/>
</parent>
<groupId>com.guslegend</groupId>
<artifactId>MybatisPlus</artifactId>
<version>1.0-SNAPSHOT</version>
<name>MybatisPlus</name>
<properties>
<java.version>17</java.version>
<lombok.version>1.18.38</lombok.version>
<mybatis-plus.version>3.5.7</mybatis-plus.version>
<mybatis-spring.version>3.0.3</mybatis-spring.version> <!-- 适配 Spring 6 的版本 -->
<mysql.version>8.0.33</mysql.version>
</properties>
<dependencies>
<!-- Spring Boot Web 核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<!-- MyBatis-Plus 核心依赖(适配 Spring Boot 3.x) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
<!-- 排除默认的低版本 mybatis-spring -->
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 手动引入适配 Spring 6 的 mybatis-spring 版本 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!-- MySQL 驱动(适配 Java 17 + Spring Boot 3.x) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<!-- 构建配置:确保编译时 Lombok 生效 -->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<!-- 阿里云镜像仓库,保证依赖下载稳定 -->
<repositories>
<repository>
<id>aliyunmaven</id>
<name>阿里云中央仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
启动类
@SpringBootApplication
@MapperScan("com.guslegend.mapper")
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
实体类
@Data
public class UserDO {
private Long id;
private String name;
private String email;
private Integer age;
}
mapper层
@Mapper
public interface UserMapper extends BaseMapper<UserDO> {
}

CRUD
增加

增加:
@Test
public void test2() {
UserDO userDO = new UserDO();
userDO.setName("guslegend");
userDO.setAge(18);
userMapper.insert(userDO);
System.out.println(userDO.getId());
userMapper.updateById(userDO);
}

我们发现写入数据库中的数据,id是不正确的,其并不是数据库自增长,实际是MP生成的id的值写入了数据库之中。

@TableName("user")
@Data
public class UserDO {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
@TableId(type = IdType.AUTO)即可为自增ID。
@TableFieid注解
可以解决对象中的属性名和字段名不一致的问题(非驼峰),对象中的属性字段在表中不存在的问题。
@TableName("user")
@Data
public class UserDO {
@TableField("id")
private Integer id;
@TableField("name")
private String name;
@TableField(value = "age",select = false) //不加入查询
private Integer age;
@TableField("email") // 字段名不一样
private String mail;
@TableField(exist = false) // 数据库不存在
private String address;
}

更新
根据ID更新
@Test
public void test3() {
UserDO userDO = new UserDO();
userDO.setName("guslegend2");
userDO.setId(1L);
userMapper.updateById(userDO);
}
根据条件更新
QueryWrapper:
@Test
public void test4() {
UserDO userDO = new UserDO();
userDO.setMail("guslegend");
QueryWrapper<UserDO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", 1);
userMapper.update(userDO, queryWrapper);
}
UpdateWrapper:
@Test
public void test5() {
int update = userMapper.update(null, new UpdateWrapper<UserDO>().eq("id", 1).set("name", "guslegend2"));
System.out.println(update);
}
删除操作
deleteById
@Test
public void test6() {
userMapper.deleteById(1995853989370589186L);
}
deleteByMap
@Test
public void test7() {
Map<String, Object> map = new HashMap<>();
// map中的删除条件要全部满足才可以删除
map.put("name", "guslegend");
map.put("age", 18);
userMapper.deleteByMap(map);
}
delete
@Test
public void test8() {
userMapper.delete(new QueryWrapper<UserDO>().eq("id", 1).eq("name", "guslegend"));
}
deleteByIds
@Test
public void test9() {
userMapper.deleteByIds(Arrays.asList(1L, 2L));
}
查询操作
selectById
@Test
public void test10() {
userMapper.selectById(1L);
}
selectBatchIds
@Test
public void test11() {
userMapper.selectBatchIds(Arrays.asList(1L, 2L));
}
selectOne
@Test
public void test12() {
// 查询单个,如果超过一个结果会抛出异常
userMapper.selectOne(new QueryWrapper<UserDO>().eq("id", 1));
}
selectList
@Test
public void test13() {
//gt 意思是 大于
userMapper.selectList(new QueryWrapper<UserDO>().gt("age", 18));
}
分页selectPage
首先我们需要设置分页插件
package com.guslegend.config;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.guslegend.mapper")
public class MybatisPlusConfig {
/**
* 分页设置
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor() {
return new PaginationInnerInterceptor();
}
}
然后编写测试代码
@Test
public void test14() {
Page<UserDO> page = new Page<>();
IPage<UserDO> iPage = userMapper.selectPage(page, new QueryWrapper<UserDO>().gt("age", 20));
System.out.println("数据总数"+iPage.getTotal());
System.out.println("总页数"+iPage.getPages());
List<UserDO> userDOList = iPage.getRecords();
for (UserDO userDO : userDOList) {
System.out.println(userDO);
}
}

Sql注入原理
MP启动后端BaseMapper通过一系列方法注册到mappedStatements中,我们接下来分析究竟是如何完成SQL注入的。
首先我们找到了ISqlInjector负责SQL注入,其是一个接口,有两个实现类。

找到其inspectInject()方法

实现方式的关键是,循环变量方法,进行依赖注入
methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));



这里以SelectById为例子,生成的SqlSource对象,再将SQL通过addSelectMappedStatementForTable注入sql

配置
官网网站:https://mybatis.plus/config/
基本配置
configLocation
Mybatis配置文件位置,如果有单独的Mybatis配置,请将其路径配置到configLocation中。
springBoot:
mybatis-plus.config-location = classpath:mybatis-config.xml
springMVC:
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
mapperLocations
如果在Mapper中有自定义方法(XML中自定义实现),需要进行配置,告诉mapper所对应的XML文件位置。
springBoot:
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
springMVC:
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
</bean>
测试用例
<?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.guslegend.mapper.UserMapper">
<select id="findByIds" resultType="com.guslegend.model.UserDO">
select * from user where id = #{id}
</select>
</mapper>
@Mapper
public interface UserMapper extends BaseMapper<UserDO> {
UserDO findByIds(Long id);
}
@SpringBootTest(classes = MybatisPlusApplication.class)
@RunWith(SpringRunner.class)
public class MPTest {
@Autowired
private UserMapper userMapper;
@Test
public void test1() {
UserDO userDO = userMapper.findByIds(1L);
System.out.println(userDO);
}
}
typeAliasesPackage
MyBaits 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML ⽂件中可以直接 使⽤类名,⽽不⽤使⽤全限定的类名(即 XML 中调⽤的时候不⽤包含包名)。
springBoot:
mybatis-plus.type-aliases-package = com.lagou.mp.pojo
springMVC:
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="typeAliasesPackage"
value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
</bean>
进阶配置
mapUnderscoreToCamelCase
是否开启自动驼峰命名规则,默认值为Ture
#关闭⾃动驼峰映射,该参数不能和mybatis-plus.config-location同时存在
mybatis-plus.configuration.map-underscore-to-camel-case=false
cacheEnabled
全局开启或者关闭配置文件中的所以映射器中的如何缓冲,默认为true。
mybatis-plus.configuration.cache-enabled=false
DB策略配置
idType
全局默认主键类型,设置后,可以省略实体类对象中的@TableIf(type = IdType.AUTO)配置。
springBoot:
mybatis-plus.global-config.db-config.id-type=auto
springMVC:
<!--这⾥使⽤MP提供的sqlSessionFactory,完成了Spring与MP的整合-->
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="globalConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean
class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<property name="idType" value="AUTO"/>
</bean>
</property>
</bean>
</property>
</bean>
tablePrefix
表名前缀,全局配置后可以省略@TableName()配置
springBoot:
mybatis-plus.global-config.db-config.table-prefix=tb_
springMVC:
<bean id="sqlSessionFactory"
class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="globalConfig">
<bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
<property name="dbConfig">
<bean
class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
<property name="idType" value="AUTO"/>
<property name="tablePrefix" value="tb_"/>
</bean>
</property>
</bean>
</property>
</bean>
条件构造器

基本操作
eq:等于
ne:不等于
gt:大于
ge:小于
lt:小于
le:小于等于
between:BETWEEN 值1 AND 值2
notBetween:NOT BETWEEN 值1 AND 值2
in:字段IN(value.get(0),value.get(1)......)
notIn:字段NOT IN(v0,v1)
模糊查询
like:LIKE'%值%',例:like("name","老王")
notLike:NOTLIKE'%值%',例:notLike("name","老王")
likeLeft:LIKELEFT'%值%',例:likeLeft("name","老王")
likeRight:LIKERIGHT'%值%',例:likeRight("name","老王")
排序
orderBy:排序 ORDER BY 字段
orderByAsc:排序 ORDER BY 字段,...ASC
orderByDesc:排序 ORDER BY 字段,...DESC
逻辑查询
or:或者
and:一起
Slelect
默认查询所以字段,也可以使用select查询指定字段
@Test
public void test2() {
UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().eq("id", 1).select("name"));
System.out.println(userDO);
}

插件
Mybatis的插件机制
MyBatis 允许你在已映射语句执⾏过程中的某⼀点进⾏拦截调⽤。默认情况下,MyBatis 允许使⽤插件来拦截的⽅
法调⽤包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接⼝的部分⽅法,⽐如update,query,commit,rollback等⽅法,还有其他接⼝
的⼀些⽅法等。
总体概括为: - 拦截执⾏器的⽅法
- 拦截参数的处理
- 拦截结果集的处理
- 拦截Sql语法构建的处理
拦截器示例:
package com.guslegend.interceptor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class}
)})
public class MyInterceptor implements Interceptor {
@Override
public Object plugin(Object target) {
//创建target对象的代理对象,⽬的是将当前拦截器加⼊到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
//属性设置
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 拦截方法,具体业务逻辑编写的位置
System.out.println("拦截方法");
return invocation.proceed();
}
}
注入到spring容器中
@Bean
public MyInterceptor myInterceptor() {
return new MyInterceptor();
}
执行分析插件
MP中提供了对SQL执行的分析的插件,可用于阻断全表更新,删除的操作,此插件仅仅适用于开发环境中。
@Bean
public SqlExplainInterceptor sqlExplainInterceptor(){
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List<ISqlParser> sqlParserList = new ArrayList<>();
// 攻击 SQL 阻断解析器、加⼊解析链
sqlParserList.add(new BlockAttackSqlParser());
sqlExplainInterceptor.setSqlParserList(sqlParserList);
return sqlExplainInterceptor;
}
性能分析插件
性能分析拦截器,用于输出每条SQL语句以及器执行时间,可以设置最大执行时间,超过会抛出异常。
@Bean
public PerformanceInterceptor performanceInterceptor(){
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
xml方式
<?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>
<plugins>
<!-- SQL 执⾏性能分析,开发环境使⽤,线上不推荐。 maxTime 指的是 sql 最⼤执⾏时⻓ -->
<plugin
interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
<property name="maxTime" value="100" />
<!--SQL是否格式化 默认false-->
<property name="format" value="true" />
</plugin>
</plugins>
</configuration>
乐观锁插件
我们想要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时,set version = newVersion where version = OldVersion
- 如果version不对,就会更新失败
xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
springBoot:
/**
* 乐观锁设置
*/
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() {
return new OptimisticLockerInnerInterceptor();
}
更改表结果添加version字段

实体类添加version,并添加@Version注解
@TableField("version")
@Version
private Integer version;
@Test
public void test3() {
int rows = userMapper.update(null,new UpdateWrapper<UserDO>().eq("id",1).eq("version",1).set("name","guslegend"));
System.out.println(rows);
}
特别说明
- ⽀持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅⽀持 updateById(id) 与 update(entity, wrapper) ⽅法
- 在 update(entity, wrapper) ⽅法下, wrapper 不能复⽤!!!
SQL注入器
通过上面的学习,我们知道MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到Mybatis容器中,这些方法才可以正常执行。那么我们需要扩充BaseMapper该怎么实现?
-
编写自己的MyMapper
public interface MyMapper<T> extends BaseMapper<T> {
List<T> findAll();}
-
将UserMapper集成自己的MyMapper
@Mapper
public interface UserMapper extends BaseMapper<UserDO>,MyMapper<UserDO> {UserDO findByIds(Long id); List<UserDO> findAll();}
-
编写MySqlInjector(如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法会失效,所以我们选择继承DefaultSqlInjector进行扩展)
public class MySqlInjector extends DefaultSqlInjector {
@Override public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) { System.out.println("MySqlInjector,自定义sql拦截器"); List<AbstractMethod> methodList = super.getMethodList(configuration, mapperClass, tableInfo); methodList.add(new FindAll(mapperClass.getName())); return methodList; }}
-
编写findAll
public class FindAll extends AbstractMethod {
/** * @param methodName 方法名 * @since 3.5.0 */ public FindAll(String methodName) { super(methodName); } @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sqlMethod = "findAll"; String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.addSelectMappedStatementForTable(mapperClass, sqlMethod, sqlSource, tableInfo); }}
-
注册到spring容器
@Bean public MySqlInjector mySqlInjector() { return new MySqlInjector(); }
测试代码
@Test
public void test4() {
List<UserDO> userDOList = userMapper.findAll() ;
for (UserDO userDO : userDOList){
System.out.println(userDO);
}
}
自动填充功能
在有些时候我们可能会有这样的需求,当我们插入或者更新数据时,希望有些字段可以自动填充数据,比如密码,version等,在MP中提供了这样的功能,可以实现自动填充。
@TableField注解
@TableField(fill = FieldFill.INSERT)
private Integer version;
为email添加自动填充功能,在新增数据时有效。

编写MyMetaObjectHandler
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject){
Object password = getFieldValByName("version",metaObject);
if(password==null){
setFieldValByName("version",1,metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}

逻辑删除
开发系统的时候,有时候实现删除功能时候,删除需要逻辑删除。在查询数据的时候要携带状态,确保被标记的数据不被查询到,这样做的目的就是被避免被真正的删除。
首先我们需要修改表结构如下:

然后修改UserDO实体类
@TableLogic
@TableField("del")
private Integer del;
添加配置文件
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
测试代码
@Test
public void test7() {
UserDO userDO = userMapper.selectOne(new QueryWrapper<UserDO>().eq("id", 4).eq("del",0));
System.out.println( userDO);
}
@Test
public void test6() {
int rows = userMapper.deleteById(4l);
System.out.println( rows);
}
代码生成器
首先我们需要添加一个maven依赖
<!-- 代码自动生成依赖 begin-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!-- velocity -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<!-- 代码自动生成依赖 end-->
package com.guslegend;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
public class MybatisPlusGenerator {
public static void main(String[] args) {
//1. 全局配置
GlobalConfig config = new GlobalConfig();
// 是否支持AR模式
config.setActiveRecord(true)
// 作者
.setAuthor("com/guslegend")
// 生成路径,最好使用绝对路径,window路径是不一样的
//TODO TODO TODO TODO
//相对路径
.setOutputDir("generation")
// 文件覆盖
.setFileOverride(true)
// 主键策略
.setIdType(IdType.AUTO)
.setDateType(DateType.ONLY_DATE)
// 设置生成的service接口的名字的首字母是否为I,默认Service是以I开头的
.setServiceName("%sService")
//实体类结尾名称
.setEntityName("%sDO")
//生成基本的resultMap
.setBaseResultMap(true)
//不使用AR模式
.setActiveRecord(false)
//生成基本的SQL片段
.setBaseColumnList(true);
//2. 数据源配置
DataSourceConfig dsConfig = new DataSourceConfig();
// 设置数据库类型
dsConfig.setDbType(DbType.MYSQL)
.setDriverName("com.mysql.cj.jdbc.Driver")
//TODO TODO TODO TODO
.setUrl("jdbc:mysql://127.0.0.1:3307/test1?useSSL=false")
.setUsername("root")
.setPassword("123456");
//3. 策略配置globalConfiguration中
StrategyConfig stConfig = new StrategyConfig();
//全局大写命名
stConfig.setCapitalMode(true)
// 数据库表映射到实体的命名策略
.setNaming(NamingStrategy.underline_to_camel)
//使用lombok
.setEntityLombokModel(true)
//使用restcontroller注解
.setRestControllerStyle(true)
// 生成的表,支持多表一起生成,以数组形式填写
//TODO TODO TODO TODO
.setInclude("product");
//4. 包名策略配置
PackageConfig pkConfig = new PackageConfig();
pkConfig.setParent("com.guslegend")
.setMapper("mapper")
.setService("service")
.setController("controller")
.setEntity("model")
.setXml("mapper");
//5. 整合配置
AutoGenerator ag = new AutoGenerator();
ag.setGlobalConfig(config)
.setDataSource(dsConfig)
.setStrategy(stConfig)
.setPackageInfo(pkConfig);
//6. 执行操作
ag.execute();
System.out.println("======= 相关代码生成完毕 =======");
}
}
MyabtisX快速开发插件

这个插件其功能:
- java与xml调回跳转
- Mapper方法自动生成Xml