目录
-
- 第一章 MyBatis-Plus3概述
-
- 1.1、简介
- 1.2、特性
- 1.3、框架结构
- 1.4、项目地址
- 1.5、版本介绍
- 1.6、快速安装
- 1.7、开发环境
- 第二章 MyBatis-Plus3增删改查
-
- 2.1、项目搭建
- 2.2、项目配置(1)
- 2.3、项目配置(2)
- 2.4、数据导入
- 2.5、创建实体
- 2.6、创建接口
- 2.7、测试准备
- 2.8、增删改查
-
- 2.8.1、insert
- 2.8.2、updateById
- 2.8.3、selectById
- 2.8.4、selectByMap
- 2.8.5、selectBatchIds
- 2.8.6、deleteById
- 2.8.7、deleteByMap
- 2.8.8、deleteBatchIds
- 第三章 MyBatis-Plus3注解介绍
-
- 3.1、@TableName
- 3.2、@TableId
- 3.3、@TableField
- 3.4、@Version
- 3.5、@EnumValue
- 3.6、@TableLogic
- 3.7、@SqlParser
- 3.8、@KeySequence
- 第四章 MyBatis-Plus3条件构造器
-
- 4.1、数据导入
- 4.2、构造器简介
- 4.3、构造器使用(1)
-
- 4.3.1、带条件的查询
- 4.3.2、带条件的修改
- 4.3.3、带条件的删除
- 4.4、构造器使用(2)
-
- 4.4.1、allEq
- 4.4.2、eq
- 4.4.3、ne
- 4.4.4、gt
- 4.4.5、ge
- 4.4.6、lt
- 4.4.7、le
- 4.4.8、between
- 4.4.9、notBetween
- 4.4.10、like
- 4.4.11、notLike
- 4.4.12、likeLeft
- 4.4.13、likeRight
- 4.4.14、isNull
- 4.4.15、isNotNull
- 4.4.16、in
- 4.4.17、notIn
- 4.4.18、inSql
- 4.4.19、notInSql
- 4.4.20、groupBy
- 4.4.21、orderByAsc
- 4.4.22、orderByDesc
- 4.4.23、orderBy
- 4.4.24、having
- 4.4.25、func
- 4.4.26、or
- 4.4.27、and
- 4.4.28、nested
- 4.4.29、apply
- 4.4.30、last
- 4.4.31、exists
- 4.4.32、notExists
- 第五章 MyBatis-Plus3代码生成器
-
- 5.1、数据导入
- 5.2、代码生成器简介
- 5.3、代码生成器使用
-
- 5.3.1、添加依赖
- 5.3.2、添加配置
- 5.3.3、启动配置
- 5.3.4、代码生成
- 5.3.5、工程结构
- 5.3.6、添加代码
- 5.3.7、启动运行
- 5.3.8、测试方法
- 5.3.9、温馨提示
- 5.4、代码生成器方法
-
- 5.4.1、save
- 5.4.2、saveOrUpdate
- 5.4.3、remove
- 5.4.4、update
- 5.4.5、get
- 5.4.6、list
- 5.4.7、page
- 5.4.8、count
- 5.4.9、chain
- 第六章 MyBatis-Plus3配置详解
-
- 6.1、配置概述
- 6.2、配置方式
- 6.3、配置选项
-
- 6.3.1、mapperLocations
- 6.3.2、typeAliasesPackage
- 6.3.3、typeHandlersPackage
- 6.3.4、typeEnumsPackage
- 6.3.5、checkConfigLocation
- 6.3.6、executorType
- 6.3.7、configurationProperties
- 6.3.8、configuration
-
- 6.3.8.1、mapUnderscoreToCamelCase
- 6.3.8.2、defaultEnumTypeHandler
- 6.3.8.3、aggressiveLazyLoading
- 6.3.8.4、autoMappingBehavior
- 6.3.8.5、autoMappingUnknownColumnBehavior
- 6.3.8.6、localCacheScope
- 6.3.8.7、cacheEnabled
- 6.3.8.8、callSettersOnNulls
- 6.3.8.9、configurationFactory
- 6.3.8.10、MyBatis3的配置属性
- 6.3.9、globalConfig
-
- 6.3.9.1、banner
- 6.3.9.2、enableSqlRunner
- 6.3.9.3、superMapperClass
- 6.3.9.4、dbConfig
-
- 6.3.9.4.1、idType
- 6.3.9.4.2、tablePrefix
- 6.3.9.4.3、schema
- 6.3.9.4.4、columnFormat
- 6.3.9.4.5、propertyFormat
- 6.3.9.4.6、tableUnderline
- 6.3.9.4.7、capitalMode
- 6.3.9.4.8、logicDeleteField
- 6.3.9.4.9、logicDeleteValue
- 6.3.9.4.10、logicNotDeleteValue
- 6.3.9.4.11、insertStrategy
- 6.3.9.4.12、updateStrategy
- 6.3.9.4.13、selectStrategy
- 6.4、配置小结
- 第七章 MyBatis-Plus3插件扩展
-
- 7.1、分页插件
- 7.2、执行分析插件
- 7.3、性能分析插件
- 7.4、乐观锁插件
- 7.5、快速开发插件
- 第八章 MyBatis-Plus3其它功能
-
- 8.1、Sql 注入器
- 8.2、逻辑删除
- 8.3、通用枚举
-
- 8.3.1、保存枚举值
- 8.3.2、保存枚举名称
- 8.4、自动填充功能
- 8.5、字段类型处理器
- 8.6、自定义ID生成器
- 8.7、Sequence主键
配套资料,免费下载
链接:https://pan.baidu.com/s/1yQS9hGP3r_zZbkuo-jlijA
提取码:4v88
复制这段内容后打开百度网盘手机App,操作更方便哦
第一章 MyBatis-Plus3概述
1.1、简介
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
我们的愿景是成为 MyBatis 最好的搭档,就像魂斗罗中的1P、2P,基友搭配,效率翻倍。
1.2、特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
1.3、框架结构
1.4、项目地址
官网地址:点击打开
源码地址:点击打开
文档地址:点击打开
配置地址:点击打开
1.5、版本介绍
全新的 MyBatis-Plus
3.0 版本基于 JDK8,提供了 lambda
形式的调用,所以安装集成 MP3.0 要求如下:
- JDK 8+
- Maven or Gradle
1.6、快速安装
-
Spring Boot
-
Maven:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency>
-
Gradle:
compile group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.4.0'
-
-
Spring MVC
-
Maven:
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.4.0</version> </dependency>
-
Gradle:
compile group: 'com.baomidou', name: 'mybatis-plus', version: '3.4.0'
-
警告:引入
MyBatis-Plus
之后请不要再次引入MyBatis
以及MyBatis-Spring
,以避免因版本差异导致的问题。
1.7、开发环境
- Jdk:jdk1.8.0_261
- Idea:IntelliJ IDEA 2020.1.2 x64
- Maven:apache-maven-3.3.9
- MySQL:mysql-5.5.61-win64
第二章 MyBatis-Plus3增删改查
2.1、项目搭建
新建完成以后,打开pom.xml后添加以下依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
在src/mian/java目录中,创建以下包文件
- com.caochenlei.mpdemo.pojo
- com.caochenlei.mpdemo.mapper
2.2、项目配置(1)
MyBatis-Plus 的配置异常的简单,我们仅需要一些简单的配置即可使用 MyBatis-Plus 的强大功能!
-
Spring Boot 工程:
-
配置 MapperScan 注解
@SpringBootApplication @MapperScan("com.caochenlei.mpdemo.mapper") public class MpDemoApplication { public static void main(String[] args) { SpringApplication.run(MpDemoApplication.class, args); } }
-
-
Spring MVC 工程:
-
配置 MapperScan 对象
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.caochenlei.mpdemo.mapper"/> </bean>
-
调整 SqlSessionFactory 为 MyBatis-Plus 的 SqlSessionFactory
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> </bean>
-
2.3、项目配置(2)
application.properties
#mysql
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
#mybatis-plus
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2.4、数据导入
## 创建库
CREATE DATABASE mp;
## 使用库
USE mp;
## 创建表
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1),
age INT
);
## 导入数据
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom','tom@qq.com',1,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Jerry','jerry@qq.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Black','black@qq.com',1,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('White','white@qq.com',0,35);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tiger','tiger@qq.com',1,28);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Bobby','bobby@qq.com',0,16);
## 查询数据
SELECT * FROM tbl_employee;
2.5、创建实体
com.caochenlei.mpdemo.pojo.Employee
@TableName("tbl_employee")
public class Employee {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(value = "last_name")
private String lastName;
@TableField(value = "email")
private String email;
@TableField(value = "gender")
private Integer gender;
@TableField(value = "age")
private Integer age;
public Employee() { }
public Employee(Integer id, String lastName, String email, Integer gender, Integer age) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Integer getGender() {
return gender;
}
public void setGender(Integer gender) {
this.gender = gender;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", gender=" + gender +
", age=" + age +
'}';
}
}
2.6、创建接口
com.caochenlei.mpdemo.mapper.EmployeeMapper
@Repository
public interface EmployeeMapper extends BaseMapper<Employee> {
}
2.7、测试准备
com.caochenlei.mpdemo.MpDemoApplicationTests
@SpringBootTest
class MpDemoApplicationTests {
@Autowired
private EmployeeMapper employeeMapper;
@Test
void contextLoads() {
List<Employee> employees = employeeMapper.selectList(null);
employees.forEach(System.out::println);
}
}
2.8、增删改查
2.8.1、insert
需求描述:插入一个员工,员工姓名为“张三”、邮箱为"zhangsan@qq.com"、男性、25岁
@Test
void testInsert() {
int result = employeeMapper.insert(new Employee(null, "zhangsan", "zhangsan@qq.com", 0, 25));
System.out.println("result:" + result);
}
2.8.2、updateById
需求信息:将id为1的员工的姓名更改为"Jennie"
@Test
void testUpdateById() {
// 先查询
Employee employee = employeeMapper.selectById(1);
employee.setLastName("Jennie");
// 再修改
int result = employeeMapper.updateById(employee);
System.out.println(result);
}
2.8.3、selectById
需求描述:查询id为1的员工信息
@Test
void testSelectById() {
Employee employee = employeeMapper.selectById(1);
System.out.println(employee);
}
2.8.4、selectByMap
需求描述:查询性别为男性(0)且年龄在25岁的员工信息
@Test
void testSelectByMap() {
Map<String, Object> map = new HashMap<>();
map.put("gender",0);
map.put("age",25);
List<Employee> employees = employeeMapper.selectByMap(map);
employees.forEach(System.out::println);
}
2.8.5、selectBatchIds
需求描述:查询id分别为1、2、3的员工的信息
@Test
void testSelectBatchIds() {
List<Employee> employees = employeeMapper.selectBatchIds(Arrays.asList(1, 2, 3));
employees.forEach(System.out::println);
}
2.8.6、deleteById
需求信息:删除id为1的员工信息
@Test
void testDeleteById() {
int result = employeeMapper.deleteById(1);
System.out.println(result);
}
2.8.7、deleteByMap
需求描述:删除性别为男性(0)且年龄在25岁的员工信息
@Test
void testDeleteByMap() {
Map<String, Object> map = new HashMap<>();
map.put("gender", 0);
map.put("age", 25);
int result = employeeMapper.deleteByMap(map);
System.out.println(result);
}
2.8.8、deleteBatchIds
需求描述:删除id分别为4、5、6的员工的信息
@Test
void testDeleteBatchIds() {
int result = employeeMapper.deleteBatchIds(Arrays.asList(4, 5, 6));
System.out.println(result);
}
第三章 MyBatis-Plus3注解介绍
3.1、@TableName
描述:表名注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 表名 |
schema | String | 否 | “” | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值) |
resultMap | String | 否 | “” | xml 中 resultMap 的 id |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入) |
3.2、@TableId
描述:主键注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
IdType
值 | 描述 |
---|---|
AUTO | 数据库ID自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert前自行set主键值 |
ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认default方法) |
3.3、@TableField
描述:字段注解(非主键)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 数据库字段名 |
el | String | 否 | “” | 映射为原生 #{ ... } 逻辑,相当于写在 xml 里的 #{ ... } 部分 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | “” | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s} |
update | String | 否 | “” | 字段 update set 部分注入, 例如:update="%s+1":表示更新时会set version=version+1(该属性优先级高于 el 属性) |
insertStrategy | Enum | N | DEFAULT | 举例:NOT_NULL: insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | N | DEFAULT | 举例:IGNORED: update table_a set column=#{columnProperty} |
whereStrategy | Enum | N | DEFAULT | 举例:NOT_EMPTY: where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | “” | 指定小数点后保留的 |
FieldStrategy
值 | 描述 |
---|---|
IGNORED | 忽略判断 |
NOT_NULL | 非NULL判断 |
NOT_EMPTY | 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断) |
DEFAULT | 追随全局配置 |
FieldFill
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
3.4、@Version
描述:乐观锁注解、标记 @Verison
在字段上
3.5、@EnumValue
描述:通枚举类注解(注解在枚举字段上)
3.6、@TableLogic
描述:表字段逻辑处理注解(逻辑删除)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 逻辑未删除值 |
delval | String | 否 | “” | 逻辑删除值 |
3.7、@SqlParser
描述:租户注解,支持method上以及mapper接口上
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
filter | boolean | 否 | false | true: 表示过滤SQL解析,即不会进入ISqlParser解析链,否则会进解析链并追加例如tenant_id等条件 |
3.8、@KeySequence
描述:序列主键策略 oracle
属性:value、resultMap
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 序列名 |
clazz | Class | 否 | Long.class | id的类型, 可以指定String.class,这样返回的Sequence值是字符串"1" |
第四章 MyBatis-Plus3条件构造器
4.1、数据导入
## 使用库
USE mp;
## 清空表
TRUNCATE TABLE tbl_employee;
## 导入数据
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan0','123@qq.com',0,21);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan1','123@qq.com',0,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan2','123@qq.com',0,23);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan3','123@qq.com',0,24);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan4','123@qq.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan5','123@qq.com',0,26);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan6','123@qq.com',0,27);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan7','123@qq.com',0,28);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan8','123@qq.com',0,29);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Allan9','123@qq.com',0,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby0','123@qq.com',1,21);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby1','123@qq.com',0,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby2','123@qq.com',1,23);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby3','123@qq.com',0,24);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby4','123@qq.com',1,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby5','123@qq.com',0,26);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby6','123@qq.com',1,27);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby7','123@qq.com',0,28);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby8','123@qq.com',1,29);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Baby9','123@qq.com',0,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom0','123@qq.com',1,21);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom1','123@qq.com',0,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom2','123@qq.com',1,23);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom3','123@qq.com',0,24);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom4','123@qq.com',1,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom5','123@qq.com',0,26);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom6','123@qq.com',1,27);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom7','123@qq.com',0,28);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom8','123@qq.com',1,29);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom9','123@qq.com',0,30);
## 查询数据
SELECT * FROM tbl_employee;
4.2、构造器简介
MyBatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者 Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担, 能够有效提高开发效率,它主要用于处理 sql 拼接,排序,实体参数查询等。
注意:使用的是数据库字段,不是 Java 属性!
警告:MyBatis-Plus不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输,Wrapper 很重,传输 Wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场),正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作。
4.3、构造器使用(1)
4.3.1、带条件的查询
需求描述:查询所有姓名的包含B、且姓名为女(1)、且年龄大于24岁的员工信息
@Test
void testSelectList1() {
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper
.like("last_name","B")
.eq("gender",1)
.gt("age",24);
List<Employee> employees = employeeMapper.selectList(queryWrapper);
employees.forEach(System.out::println);
}
需求描述:查询所有员工信息
@Test
void testSelectList2() {
List<Employee> employees = employeeMapper.selectList(null);
employees.forEach(System.out::println);
}
需求描述:查询所有女生的数量(1)
@Test
void testSelectList3() {
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("gender", 1);
Integer count = employeeMapper.selectCount(queryWrapper);
System.out.println(count);
}
4.3.2、带条件的修改
需求信息:将年龄大于25岁的女生(1)的性别修改为男生(0)
@Test
void testUpdate() {
UpdateWrapper<Employee> updateWrapper = new UpdateWrapper<>();
updateWrapper
.eq("gender", 1)
.gt("age", 25)
;
Employee employee = new Employee();
employee.setGender(0);
employeeMapper.update(employee, updateWrapper);
}
4.3.3、带条件的删除
需求信息:将姓名带有“Tom”的员工信息删除
@Test
void testDelete() {
QueryWrapper<Employee> queryWrapper = new QueryWrapper<>();
queryWrapper.like("last_name", "Tom");
int result = employeeMapper.delete(queryWrapper);
System.out.println(result);
}
4.4、构造器使用(2)
参数说明:
- 以下出现的第一个入参
boolean condition
表示该条件是否加入最后生成的sql中 - 以下代码块内的多个方法均为从上往下补全个别
boolean
类型的入参,默认为true
- 以下出现的泛型
Param
均为Wrapper
的子类实例(均具有AbstractWrapper
的所有方法) - 以下方法在入参中出现的
R
为泛型,在普通wrapper中是String
,在LambdaWrapper中是函数(例:Entity::getId
,Entity
为实体类,getId
为字段id
的getMethod) - 以下方法入参中的
R column
均表示数据库字段,当R
具体类型为String
时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹)!而不是实体类数据字段名,另当R
具体类型为SFunction
时项目runtime不支持eclipse自家的编译器 - 以下举例均为使用普通wrapper,入参为
Map
和List
的均以json
形式表现 - 使用中如果入参的
Map
或者List
为空,则不会加入最后生成的sql中
AbstractWrapper:
说明:AbstractWrapper 是 QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类用于生成 sql 的 where 条件,entity 属性也用于生成 sql 的 where 条件,注意 entity 生成的 where 条件与使用各个 api 生成的 where 条件没有任何关联行为
4.4.1、allEq
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
- 全部
eq
(或个别isNull
)
个别参数说明:
params
:key
为数据库字段名,value
为字段值
null2IsNull
:为true
则在map
的value
为null
时调用 isNull
方法,为false
时则忽略value
为null
的
- 例1:
allEq({id:1,name:"老王",age:null})
—>id = 1 and name = '老王' and age is null
- 例2:
allEq({id:1,name:"老王",age:null}, false)
—>id = 1 and name = '老王'
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
个别参数说明:
filter
: 过滤函数,是否允许字段传入比对条件中
params
与 null2IsNull
: 同上
- 例1:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})
—>name = '老王' and age is null
- 例2:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)
—>name = '老王'
4.4.2、eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)
- 等于 =
- 例:
eq("name", "老王")
—>name = '老王'
4.4.3、ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)
- 不等于 <>
- 例:
ne("name", "老王")
—>name <> '老王'
4.4.4、gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)
- 大于 >
- 例:
gt("age", 18)
—>age > 18
4.4.5、ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)
- 大于等于 >=
- 例:
ge("age", 18)
—>age >= 18
4.4.6、lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)
- 小于 <
- 例:
lt("age", 18)
—>age < 18
4.4.7、le
le(R column, Object val)
le(boolean condition, R column, Object val)
- 小于等于 <=
- 例:
le("age", 18)
—>age <= 18
4.4.8、between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)
—>age between 18 and 30
4.4.9、notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)
—>age not between 18 and 30
4.4.10、like
like(R column, Object val)
like(boolean condition, R column, Object val)
- LIKE ‘%值%’
- 例:
like("name", "王")
—>name like '%王%'
4.4.11、notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
- NOT LIKE ‘%值%’
- 例:
notLike("name", "王")
—>name not like '%王%'
4.4.12、likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
- LIKE ‘%值’
- 例:
likeLeft("name", "王")
—>name like '%王'
4.4.13、likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
- LIKE ‘值%’
- 例:
likeRight("name", "王")
—>name like '王%'
4.4.14、isNull
isNull(R column)
isNull(boolean condition, R column)
- 字段 IS NULL
- 例:
isNull("name")
—>name is null
4.4.15、isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
- 字段 IS NOT NULL
- 例:
isNotNull("name")
—>name is not null
4.4.16、in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
- 字段 IN (value.get(0), value.get(1), …)
- 例:
in("age",{1,2,3})
—>age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
- 字段 IN (v0, v1, …)
- 例:
in("age", 1, 2, 3)
—>age in (1,2,3)
4.4.17、notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
- 字段 NOT IN (value.get(0), value.get(1), …)
- 例:
notIn("age",{1,2,3})
—>age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
- 字段 NOT IN (v0, v1, …)
- 例:
notIn("age", 1, 2, 3)
—>age not in (1,2,3)
4.4.18、inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
- 字段 IN ( sql语句 )
- 例:
inSql("age", "1,2,3,4,5,6")
—>age in (1,2,3,4,5,6)
- 例:
inSql("id", "select id from table where id < 3")
—>id in (select id from table where id < 3)
4.4.19、notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
- 字段 NOT IN ( sql语句 )
- 例:
notInSql("age", "1,2,3,4,5,6")
—>age not in (1,2,3,4,5,6)
- 例:
notInSql("id", "select id from table where id < 3")
—>id not in (select id from table where id < 3)
4.4.20、groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
- 分组:GROUP BY 字段, …
- 例:
groupBy("id", "name")
—>group by id,name
4.4.21、orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … ASC
- 例:
orderByAsc("id", "name")
—>order by id ASC,name ASC
4.4.22、orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … DESC
- 例:
orderByDesc("id", "name")
—>order by id DESC,name DESC
4.4.23、orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
- 排序:ORDER BY 字段, …
- 例:
orderBy(true, true, "id", "name")
—>order by id ASC,name ASC
4.4.24、having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
- HAVINg ( sql语句 )
- 例:
having("sum(age) > 10")
—>having sum(age) > 10
- 例:
having("sum(age) > {0}", 11)
—>having sum(age) > 11
4.4.25、func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
- func 方法(主要方便在出现if…else下调用不同方法能不断链)
- 例:
func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
4.4.26、or
or()
or(boolean condition)
- 拼接 OR
注意事项:
主动调用or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接)
- 例:
eq("id",1).or().eq("name","老王")
—>id = 1 or name = '老王'
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))
—>or (name = '李白' and status <> '活着')
4.4.27、and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))
—>and (name = '李白' and status <> '活着')
4.4.28、nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))
—>(name = '李白' and status <> '活着')
4.4.29、apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
- 拼接 sql
注意事项:
该方法可用于数据库函数动态入参的params
对应前面applySql
内部的{index}
部分,这样是不会有sql注入风险的,反之会有!
- 例:
apply("id = 1")
—>id = 1
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
—>date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
—>date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
4.4.30、last
last(String lastSql)
last(boolean condition, String lastSql)
- 无视优化规则直接拼接到 sql 的最后
注意事项:
只能调用一次,多次调用以最后一次为准,有sql注入的风险,请谨慎使用
- 例:
last("limit 1")
4.4.31、exists
exists(String existsSql)
exists(boolean condition, String existsSql)
- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")
—>exists (select id from table where age = 1)
4.4.32、notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")
—>not exists (select id from table where age = 1)
第五章 MyBatis-Plus3代码生成器
5.1、数据导入
## 删除表
DROP TABLE IF EXISTS `tbl_user`;
## 创建表
CREATE TABLE `tbl_user` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`name` VARCHAR(30) DEFAULT NULL COMMENT '姓名',
`age` INT(11) DEFAULT NULL COMMENT '年龄',
`email` VARCHAR(30) DEFAULT NULL COMMENT '邮箱',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='用户';
## 导入数据
INSERT INTO `tbl_user`(`id`,`name`,`age`,`email`) VALUES (1,'Jone',18,'test1@baomidou.com');
INSERT INTO `tbl_user`(`id`,`name`,`age`,`email`) VALUES (2,'Jack',20,'test2@baomidou.com');
INSERT INTO `tbl_user`(`id`,`name`,`age`,`email`) VALUES (3,'Tom',28,'test3@baomidou.com');
INSERT INTO `tbl_user`(`id`,`name`,`age`,`email`) VALUES (4,'Sandy',21,'test4@baomidou.com');
INSERT INTO `tbl_user`(`id`,`name`,`age`,`email`) VALUES (5,'Billie',24,'test5@baomidou.com');
5.2、代码生成器简介
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
5.3、代码生成器使用
5.3.1、添加依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<!-- 插件管理 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
</plugin>
</plugins>
<!-- 资源管理 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>***.xml</include>
<include>***.properties</include>
<include>***.conf</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
5.3.2、添加配置
application.properties
#server server.port=8080 #mysql spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mp?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=123456 #mybatis-plus mybatis-plus.mapper-locations=classpath*:**/mapper/xmlmapper/xml*.xml"]
MyBatis Mapper 所对应的 XML 文件位置,如果您在 Mapper 中有自定义方法(XML 中有自定义实现),需要进行该配置,告诉 Mapper 所对应的 XML 文件位置,Maven 多模块项目的扫描路径需以
classpath*:
开头 (即加载多个 jar 包下的 XML 文件)。mybatis-plus.mapper-locations=classpath*:**/mapper/xmlmapper/xml private AgeEnum age;
测试方法:
@Test void testAgeEnum() { Student student = new Student(); student.setName("李四"); student.setAge(AgeEnum.THREE); int result = studentMapper.insert(student); System.out.println(result); }
控制台截图:
数据库截图:
8.3.2、保存枚举名称
添加配置:application.properties,如果有以下配置,请忽略此步骤
mybatis-plus.type-enums-package=com.caochenlei.mpdemo.myenum mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler
创建枚举类:com.caochenlei.mpdemo.myenum.GradeEnum
public enum GradeEnum { PRIMARY(1, "小学"), SECONDORY(2, "中学"), HIGH(3, "高中"); private int code; @EnumValue//描述作为枚举值保存到数据库 private String desc; GradeEnum(int code, String desc) { this.code = code; this.desc = desc; } public int getCode() { return code; } public void setCode(int code) { this.code = code; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } }
修改实体类:com.caochenlei.mpdemo.pojo.Student
private GradeEnum grade;
测试方法:
@Test void testGradeEnum() { Student student = new Student(); student.setName("王五"); student.setGrade(GradeEnum.HIGH); int result = studentMapper.insert(student); System.out.println(result); }
控制台截图:
数据库截图:
8.4、自动填充功能
我们现在有一个需求,每当插入一个学生的时候,自动的给学生状态设置为”插入“,每当修改的时候,如果状态标志位为null,就把标志字段设置为”修改“,这时候就需要自动填充功能了。
metaobject:元对象,是 Mybatis 提供的一个用于更加方便,更加优雅的访问对象的属性,给对象的属性设置值的一个对象,还会用于包装对象,支持对 Object 、Map、Collection等对象进行包装,本质上 metaObject 获取对象的属性值或者是给对象的属性设置值,最终是要通过 Reflector 获取到属性的对应方法的 Invoker,最终 invoke。
添加注解:
@TableField(fill = FieldFill.INSERT_UPDATE) private String status;
创建包:com.caochenlei.mpdemo.metaObjectHandler
创建自动填充功能处理器:com.caochenlei.mpdemo.metaObjectHandler.MyMetaObjectHandler
public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { System.out.println("start insert fill ...."); this.strictInsertFill(metaObject, "status",String.class,"插入"); } @Override public void updateFill(MetaObject metaObject) { System.out.println("start update fill ...."); this.strictUpdateFill(metaObject, "status",String.class,"更新"); } }
注册自动填充功能处理器:MybatisPlusConfig
@Bean public MyMetaObjectHandler myMetaObjectHandler(){ return new MyMetaObjectHandler(); }
测试方法:依次执行两个方法
@Test void testInsertFill(){ Student student = new Student(); student.setName("小六"); int result = studentMapper.insert(student); System.out.println(result); } @Test void testUpdateFill(){ Student student = studentMapper.selectById(4); student.setName("李四-修改"); student.setStatus(null); int result = studentMapper.updateById(student); System.out.println(result); }
控制台截图:
testInsertFill之后
testUpdateFill之后
数据库截图:
testInsertFill之后
testUpdateFill之后
8.5、字段类型处理器
字段类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值,本文讲解 mybaits-plus 内置常用类型处理器如何通过TableField注解快速注入到 mybatis 容器中。
@Data @Accessors(chain = true) @TableName(autoResultMap = true) public class User { private Long id; ... @TableField(typeHandler = JacksonTypeHandler.class) // @TableField(typeHandler = FastjsonTypeHandler.class) private OtherInfo otherInfo; }
8.6、自定义ID生成器
导入数据:
## 删除表 DROP TABLE IF EXISTS `tbl_product`; ## 新建表 CREATE TABLE `tbl_product` ( `pid` int(11) NOT NULL COMMENT '商品主键', `pname` varchar(255) DEFAULT NULL COMMENT '商品名称', PRIMARY KEY (`pid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品';
生成代码:运行CodeGenerator
温馨提示:自3.3.0开始,默认使用雪花算法+UUID(不含中划线)
重写方法:
方法 | 主键生成策略 | 主键类型 | 说明 |
---|---|---|---|
nextId | ASSIGN_ID | Long,Integer,String | 支持自动转换为String类型,但数值类型不支持自动转换,需精准匹配,例如返回Long,实体主键就不支持定义为Integer |
nextUUID | ASSIGN_UUID,UUID | String | 默认不含中划线的UUID生成 |
创建包:com.caochenlei.mpdemo.incrementer
创建类:com.caochenlei.mpdemo.incrementer.CustomIdGenerator
public class CustomIdGenerator implements IdentifierGenerator {
private final AtomicLong al = new AtomicLong(1);
@Override
public Long nextId(Object entity) {
//可以将当前传入的class全类名来作为bizKey或者提取参数来生成bizKey进行分布式Id调用生成
String bizKey = entity.getClass().getName();
System.out.println("bizKey:" + bizKey);
MetaObject metaObject = SystemMetaObject.forObject(entity);
String name = (String) metaObject.getValue("pname");
final long id = al.getAndAdd(1);
System.out.println("为" + name + "生成主键值->:" + id);
return id;
}
}
注册类:MybatisPlusConfig
@Bean
public IdentifierGenerator customIdGenerator(){
return new CustomIdGenerator();
}
修改主键策略
@TableId(value = "pid", type = IdType.ASSIGN_ID)
private Long pid;
测试方法:
@Autowired
private ProductMapper productMapper;
@Test
void testCustomIdGenerator() {
Product product = new Product();
product.setPname("手机");
int result = productMapper.insert(product);
System.out.println(result);
}
控制台截图:
数据库截图:
8.7、Sequence主键
在实际开发中,我们经常会使用到MySQL和Oracle数据库,但是这两种数据库对于主键有不同的策略,如下:
- MySQL:支持主键自增,type = IdType.Auto
- Oracle:支持序列自增,type = IdType.INPUT
那我们Oracle又要如何使用主键策略,在这里,我们就不进行一步一步介绍了,我们只提出解决方法
-
在实体类对象上添加注解@KeySequence(value=”序列名”, clazz=主键属性类型.class)
-
在实体类对象的主键字段上添加注解@TableId(value = “主键名称”, type = IdType.INPUT)
@KeySequence(value = "SEQ_ORACLE_INTEGER_KEY", clazz = Integer.class) public class YourEntity { @TableId(value = "ID", type = IdType.INPUT) private Integer id; }
-
在全局配置中注册com.baomidou.mybatisplus.incrementer.OracleKeyGenerator
@Bean public IKeyGenerator keyGenerator() { return new oracleKeyGenerator(); }
除了Oracle,MyBatis-Plus还内置支持以下数据库序列:
- DB2KeyGenerator
- H2KeyGenerator
- KingbaseKeyGenerator
- OracleKeyGenerator
- PostgreKeyGenerator
如果内置支持不满足你的需求,可实现IKeyGenerator接口来进行扩展。