mybatis-Plus入门
入门
简介
- MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只 做增强不做改变,为简化开发、提高效率而生。
- 愿景:我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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、SQLServer2005、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快 速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规 则,预防误操作
框架结构
快速开始
- 环境要求 jdk8+
- mybatis plus 3.2.0
- springboot2+ maven3+
数据库
DDL
1
2
3
4
5
6
7
8
9
10
11CREATE DATABASE db_mp;
USE db_mp;
DROP TABLE IF EXISTS 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 )
);DML
1
2
3
4
5
6
7DELETE FROM user;
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');
初始化工程
创建springboot项目,加入 mybatisplus 、 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<parent>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.11.RELEASE</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<mybatis-plus.vesrion>3.2.0</mybatis-plus.vesrion>
</properties>
<dependencies>
<!-- MySQL驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatisPlus驱动包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.vesrion}</version>
</dependency>
<!-- Lombok 驱动包 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
application.properties
mysql驱动版本,高版本驱动路径为com.mysql.cj.jdbc.Driver
注意修改数据库信息(数据库名称、账号、密码)
1 | spring: |
启动器
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
1
2
3
4
5
6
7
8
9
10
//扫描加载mapper接口
public class MybatisplusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisplusApplication.class, args);
}
}
实体类
创建实体类,建议属性名与数据库表中的列名一致
1
2
3
4
5
6
7
8
9
10import lombok.Data;
public class User {
private Integer id;//用户编号
private String name;//用户名
private Integer age;//年龄
private String email;//邮箱
}
mapper接口
若想使用mp实现快速的CRUD操作,mapper接口集成BaseMapper接口即可
1
2
3
4
5
6
7
8
9
10
11
12
13import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import pers.fulsun.mybatisplusstudy.entity.User;
/**
* 自定义Mapper接口集成BaseMapper<T>接口,即可使用MP
*
* @author fulsun
* @date 8/10/2021
*/
public interface IUserMapper extends BaseMapper<User> {
}
测试类
springboot项目自带test测试类,在test包下可以找到测试类
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
26package pers.fulsun.mybatisplusstudy;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import pers.fulsun.mybatisplusstudy.dao.IUserMapper;
import pers.fulsun.mybatisplusstudy.entity.User;
class MybatisplusApplicationTest {
//注入userMapper接口
private IUserMapper userMapper;
void test1() {
//调用mp底层查询方法
List<User> users = userMapper.selectList(null);
for (User user : users) {
System.out.println(user);
}
}selectList()方法参数可以为null,可查看源码学习,源码如下:
1
2
3
4
5
6/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(; Wrapper<T> queryWrapper)
通用CRUD的使用
假设我们已存在一张 t_employee 表, 且已有对应的实体类 Employee , 实现 t_employee 表的 CRUD 操作,我们需要做什么呢?
实现方式
- 基于Mybatis: 需要编写EmployeeMapper 接口,并手动编写CRUD 方法 提供EmployeeMapper.xml 映射文件,并手动编写每个方法对应的SQL 语句.
- 基于MP: 只需要创建 EmployeeMapper 接口, 并继承 BaseMapper 接口即可 若需要完成所有操作,不需要创建SQL
数据库文件
创建t_employee表,对应实体类为Employee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15-- 创建表
CREATE TABLE t_employee (
id INT ( 11 ) PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR ( 50 ),
email VARCHAR ( 50 ),
gender CHAR ( 1 ),
age INT
);
INSERT INTO t_employee ( user_name, email, gender, age )
VALUES
( 'Tom', 'tom@qq.com', 1, 22 ),
( 'Jerry', 'jerry@qq.com', 0, 25 ),
( 'Black', 'black@qq.com', 1, 30 ),
( 'White', 'white@qq.com', 0, 35 );
实体类
遵循JavaBean规范编写实体类,提供get\set方法及toString()方法
表名与实体类名不一致,列名与属性名不一致是否可以成功运行?
- 注意:表名与实体类名称不一致时,需要使用@TableName注解指定表名
1
2
3
4
5
6
7
8
public class Employee {
private Integer id;//编号
private String userName;//用户名
private String email;//邮箱
private Integer gender;//性别
private Integer age;//年龄
}
Mapper接口
在dao包下创建EmployeeMapper接口,继承BaseMapper接口,无需编写xml映射 文件
1
2
3
4
5
6
7
8public interface IEmployeeMapper extends BaseMapper<Employee> {
/**
* 插入一条记录
*
* @param entity 实体对象
*/
int insert(T entity);
}
测试新增
在test包下创建新的测试类IEmployeeMapperTest
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
29package pers.fulsun.mybatisplusstudy.dao;
import javax.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import pers.fulsun.mybatisplusstudy.entity.Employee;
class IEmployeeMapperTest {
private IEmployeeMapper employeeMapper;
void testInsert() {
Employee employee = new Employee();
employee.setAge(20);
employee.setEmail("1325698667@qq.com");
employee.setGender(1);
employee.setUserName("lucy");
//新增
int count = employeeMapper.insert(employee);
if (count > 0) {
System.out.println("新增成功,主键id为:" + employee.getId());
} else {
System.out.println("新增失败");
}
}
}
错误1-没有设置主键
错误信息
- org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException:
Could not set property 'id' of 'class pers.fulsun.mybatisplusstudy.entity.Employee' with value '1424966924487487490'
Cause: java.lang.IllegalArgumentException: argument type mismatch
- org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException:
解决办法
在实体类中的主键属性加入注解 @TableId
1
2
3
4
5
6
7
8
9
10
11
public class Employee {
//主键生成策略,value属性可选,当属性名与表中的列名不一致,必填
//type:配置主键生成策略,IdType.AUTO表示自增
private Integer id;//编号
private String userName;//用户名
private String email;//邮箱
private Integer gender;//性别
private Integer age;//年龄
}
错误2-表名与实体类名不一致
错误信息
1
2### Cause: java.sql.SQLSyntaxErrorException: Table 'db_mp.employee' doesn't exist
; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: Table 'db_mp.employee' doesn't exist解决办法
在实体类名称上加入注解 @TableName
1
2
3
4//名称一致时,此注解可以省略
public class Employee {
}
列名与属性名不一致
如果useName写成usename后,会出现如下错误信息
1
2org.springframework.jdbc.BadSqlGrammarException:
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'usename' in 'field list'解决办法
在实体类的属性上加入@TableField注解
注意:当表中的列名与实体类中的属性值不一致时,属性名遵循驼峰命名法,可以自动 映射,无需加入@TableField注解,
如:列名为user_name,属性名为 userName【该情况下不需要加注解】
1
2
private String usename;//用户名
MP注解的使用
- 介绍 MybatisPlus 注解包相关类详解(更多详细描述可点击查看源码注释)
- 注解类包:mybatis-plus-annotation
@TableName
- 描述:表名注解
属性 | 类 型 | 必 须 指 定 | 默 认 值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 表名 |
resultMap | String | 否 | “” | xml 中 resultMap 的 id |
schema | String | 否 | “” | schema(@since 3.1.1) |
keepGlobalPrefix | String | 否 | false | 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)(@since 3.1.1) |
@TableId
- 描述:主键注解
属性 | 类 型 | 必 须 指 定 | 默 认 值 | 描述 |
---|---|---|---|---|
value | String | 否 | “” | 主键字段名 |
type | Enum | 否 | IdType.NONE | 主键类型 |
@IdType
值 | 描述 |
---|---|
AUTO | 数据库自增 |
INPUT | 自行输入 |
ID_WORKER | 分布式全局唯一ID |
UUID | 32位UUID字符串 |
NONE | 无状态 |
ID_WORKER_STR | 分布式全局唯一ID |
@TableField
描述:字段注解(非主键)
具体参考官方文档https://mp.baomidou.com/guide/annotation.html#tablefield
属性 类 型 必 须 指 定 默 认 值 描述 value String 否 “” 字段名 exist boolean 否 true 是否为数据库表字段 fill Enum 否 FieldFill.DEFAULT 字段自动填充策略
@TableLogin
描述: 表字段逻辑处理注解(逻辑删除)
属性 类型 必须制定 默认值 描述 value String 否 “” 逻辑未删除值 delval String 否 “” 逻辑删除值
排除非表中字段
测试非表中字段属性操作,在 Enployee的实体类中加入remark属性,提供get、set方法
1
2//备注信息(数据库表中并无此列)
private String remark;测试中添加备注
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void testInsert() {
Employee employee = new Employee();
employee.setAge(20);
employee.setEmail("1325698667@qq.com");
employee.setGender(1);
employee.setUsename("lucy");
//设置备注
employee.setRemark("xxx");
//新增
int count = employeeMapper.insert(employee);
if (count > 0) {
System.out.println("新增成功,主键id为:" + employee.getId());
} else {
System.out.println("新增失败");
}
}错误信息
1
2
3org.springframework.jdbc.BadSqlGrammarException:
### Error updating database. Cause: java.sql.SQLSyntaxErrorException: Unknown column 'remark' in 'field list'
方法1-transient关键字
在实体类属性上加入 transient 关键字
1
private transient String remark;
方法2-@TableField
在实体类属性上加入 @TableField 注解,设置 exist 属性为 false
1
2
3//备注信息(数据库表中并无此列)
private String remark;
条件构造器
构造器简介
- Mybatis-Plus 通过 QueryWrapper(简称 QW,MP 封装的一个查询条件构造器) 来让用户自由的构建查询条件,简单便捷,没有额外的负担, 能够有效提高开发效率
- 实体包装器,主要用于处理 sql 拼接,排序,实体参数查询等
- 注意: 使用的是 数据库表字段 ,不是 Java 属性!
条件参数
体条件参数详细用法可参考MP官方文档
查询方式 说明 setSqlSelect 设置select 查询字段 where where语句,拼接+ where 条件
and AND 语句,拼接+ AND 字段=值
andNew AND 语句,拼接+ AND (字段=值)
or OR 语句,拼接+ OR 字段=值
orNew OR 语句,拼接+ OR (字段=值)
eq 等于= allEq 基于map 内容等于= ne 不等于<> gt 大于 > ge 大于等于 >= lt 小于 < le 小于等于 <= like 模糊查询 LIKE notLike 模糊查询 NOT LIKE in IN查询 notIn NOT IN 查询 isNull NULL查询 isNotNull IS NOT Null groupBy 分组 Group BY having having关键词 orderBy 排序 ORDER BY orderAsc ASC 排序 ORDER BY orderDesc DESC 排序 ORDER BY exists EXISTS 条件语句 notExists NOT EXISTS 条件语句 between between条件语句 notBetween NOT BETWEEN条件语句 addFilter 自由拼接SQL last 拼接在最后,例如 last("LIMIT 1")
delete删除操作
MP删除的方法
具体参考BaseMapper接口源码
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
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(; Map<String, Object> columnMap)
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(; Wrapper<T> wrapper)
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(; Collection<? extends Serializable> idList)
MP删除的使用
deleteById()
根据id主键删除数据
1
2
3
4
5
6
7
8
9
10
public void testDeleteById() {
//删除
int count = employeeMapper.deleteById(8);
if (count > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
deleteByMap()
根据 columnMap 条件,删除记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void testDeleteByMap() {
//指定条件列,key为数据库表中的列名
Map<String, Object> map = new LinkedHashMap<String, Object>();
map.put("user_name", "lucy");
map.put("gender", 1);
//删除
int count = employeeMapper.deleteByMap(map);
if (count > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
delete()
根据 entity 条件,删除记录
1
2
3
4
5
6
7
8
9
10
11
12
13
public void testDelete() {
//创建条件构造器对象
//指定条件,key为数据库表中的列名
QueryWrapper<Employee> wrapper = new QueryWrapper<Employee>();
wrapper.eq("id", 5); //删除
int count = employeeMapper.delete(wrapper);
if (count > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
deleteBatchIds()
删除(根据ID 批量删除)
1
2
3
4
5
6
7
8
9
10
public void testDeleteBatchIds() {
//删除
int count = employeeMapper.deleteBatchIds(Arrays.asList(1, 2, 3));
if (count > 0) {
System.out.println("删除成功");
} else {
System.out.println("删除失败");
}
}
update更新操作
MP更新的方法
具体方法参考源码BaseMapper接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(; T entity)
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(; T entity, Wrapper<T> updateWrapper)
MP更新方法的使用
updateById()
根据 ID 修改
1
2
3
4
5
6
7
8
9
10
11
12
13
public void testUpdateById() {
Employee employee = new Employee();
employee.setUserName("王明");
employee.setId(6);
//修改
int count = employeeMapper.updateById(employee);
if (count > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
}
update()
根据 whereEntity 条件,更新记录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void testUpdate() {
UpdateWrapper<Employee> wrapper = new UpdateWrapper<Employee>();
wrapper.eq("id", 6);
//指定修改条件, 修改员工数据
Employee employee = new Employee();
employee.setUserName("jason");
//修改
int count = employeeMapper.update(employee, wrapper);
if (count > 0) {
System.out.println("修改成功");
} else {
System.out.println("修改失败");
}
}
select查询
MP查询的方法
列举MyBatisPlus常用的查询方法,具体可参考BaseMapper接口源码
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
63
64
65
66
67
68
69
70
71
72
73
74
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(; Collection<? extends Serializable> idList)
/**
* 查询(根据 columnMap 条件)
*
* @param columnMap 表字段 map 对象
*/
List<T> selectByMap(; Map<String, Object> columnMap)
/**
* 根据 entity 条件,查询一条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(; Wrapper<T> queryWrapper)
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(; Wrapper<T> queryWrapper)
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(; Wrapper<T> queryWrapper)
/**
* 根据 Wrapper 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Map<String, Object>> selectMaps(; Wrapper<T> queryWrapper)
/**
* 根据 Wrapper 条件,查询全部记录
* <p>注意: 只返回第一个字段的值</p>
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<Object> selectObjs(; Wrapper<T> queryWrapper)
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage<T> selectPage(IPage<T> page, ; Wrapper<T> queryWrapper)
/**
* 根据 Wrapper 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件
* @param queryWrapper 实体对象封装操作类
*/
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, ; Wrapper<T> queryWrapper)
MP查询方法的使用
selectById()
根据 ID 查询
1
2
3
4
5
public void testSelectById() {
Employee employee = this.employeeMapper.selectById(1);
System.out.println(employee);
}
selectBatchIds()
查询(根据ID 批量查询)
1
2
3
4
5
6
7
8
9
10
public void testSelectBatchIds() {
//创建集合保存员工id
List<Integer> idList = Arrays.asList(1, 2, 3);
//批量查询(使用in()查询)
List<Employee> list = this.employeeMapper.selectBatchIds(idList);
for (Employee employee : list) {
System.out.println(employee);
}
}
selectByMap()
查询(根据 columnMap 条件)
1
2
3
4
5
6
7
8
9
public void testSelectByMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", 1);
List<Employee> list = this.employeeMapper.selectByMap(map);
for (Employee employee : list) {
System.out.println(employee);
}
}
selectOne()
根据 entity 条件,查询一条记录
注意:最多只能返回1条记录
1
2
3
4
5
6
7
8
9
10
public void testSelectOne() {
//创建条件构造器
QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>();
//指定条件,key为表字段
queryWrapper.eq("id", 1);
//返回的结果最多1条,返回多条记录会报错
Employee employee = this.employeeMapper.selectOne(queryWrapper);
System.out.println(employee);
}
selectCount()
根据 Wrapper 条件,查询总记录数
1
2
3
4
5
6
7
8
9
10
public void testSelectCount() {
//创建条件构造器
QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>();
// 指定条件,key为表字段
queryWrapper.like("user_name", "t");
// 总数量
int count = this.employeeMapper.selectCount(queryWrapper);
System.out.println("总数量:" + count);
}
selectList()
根据 entity 条件,查询全部记录
1
2
3
4
5
6
7
8
9
10
11
12
public void testSelectList() {
//创建条件构造器
QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>();
// 指定条件,key为表字段
queryWrapper.like("user_name", "c");
queryWrapper.ge("age", 20);
List<Employee> list = this.employeeMapper.selectList(queryWrapper);
for (Employee employee : list) {
System.out.println(employee);
}
}
selectPage()
注意:在MyBatis Plus中实现分页,需要注入MyBatis Plus分页拦截器
在.config包下创建MyBatisPlusConfig类,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13//开启事务
public class MyBatisPlusConfig {
/**
* 分页插件
*/
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}测试类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* 分页查询
*/
public void testSelectPage() {
//创建分页信息(参数1:当前页码,参数2:每页显示的数量)
IPage<Employee> page = new Page<Employee>(1, 2);
//创建条件构造器对象
QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>();
queryWrapper.orderByDesc("id");
// 调用分页查询的方法
IPage<Employee> employeeIPage = employeeMapper.selectPage(page, queryWrapper);
System.out.println("当前页码:" + employeeIPage.getCurrent());
System.out.println("每页显示数量:" + employeeIPage.getSize());
System.out.println("数据总数量" + employeeIPage.getTotal());
System.out.println("总页数:" + employeeIPage.getPages());
//获取数据列表
List<Employee> employees = employeeIPage.getRecords();
for (Employee employee : employees) {
System.out.println(employee);
}
}
动态条件查询
定义扩展类EmployeeVo
注意:该类只做查询条件的参数,不做方法的返回值类型
1
2
3
4public class EmployeeVo extends Employee {
}测试
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/**
* 动态条件查询
*/
public void test() {
//参数
EmployeeVo employeeVo = new EmployeeVo();
employeeVo.setAge(15);
employeeVo.setUserName("t");
// 创建条件构造器
QueryWrapper<Employee> queryWrapper = new QueryWrapper<Employee>();
//参数1:是否加入该条件(true:加入)
// 参数2:数据库表的列名
// 参数3:查询的内容
// 姓名模糊查询
queryWrapper.like(!StringUtils.isEmpty(employeeVo.getUserName()), "user_name",
employeeVo.getUserName());
//年龄范围查询
queryWrapper.ge(!StringUtils.isEmpty(employeeVo.getAge()), "age", employeeVo.getAge());
//排序(排序的列名)
queryWrapper.orderByDesc("id");
//根据id降序
List<Employee> list = this.employeeMapper.selectList(queryWrapper);
for (Employee employee : list) {
System.out.println(employee);
}
}
自定义SQL查询及分页查询
- 自定义SQL查询:常用的方式有注解方式和xml方式,与MyBatis的用法一致
注解方式
mapper接口
1
2
3
4
5
6
7
8public interface EmployeeMapper extends BaseMapper<Employee> {
/**
* 查询员工数据
* @return
*/
List<Employee> findEmployeeList();
}测试
1
2
3
4
5
6
7
public void testFindEmpList() {
List<Employee> list = this.employeeMapper.findEmployeeList();
for (Employee employee : list) {
System.out.println(employee);
}
}
xml方式
mapper接口
1
2
3
4
5
6
7public interface EmployeeMapper extends BaseMapper<Employee> {
/**
* 查询员工数据
* @return
*/
List<Employee> findEmployeeList();
}mapper映射文件
如果在mapper接口相同目录下创建与接口同名的mapper映射文件,
application.properties配置文件则不用进行任何配置(idea开发工具中需要在 pom.xml文件中加入以下代码)
1
2
3
4
5
6
7
8
9
10
11
12
13<build>
<resources>
<resource>
<!-- 编译目录 -->
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>如果mapper映射文件是放在resource资源文件夹下的mapper目录, application.properties配置文件需要进行加载映射文件
1
2#加载映射文件
mybatis-plus.mapper-locations=classpath:mapper/*.xmlresource/mapper目录下的UserMapper映射文件:
1
2
3
4
5
6
7
<mapper namespace="pers.fulsun.mybatisplusstudy.dao.IEmployeeMapper">
<select id="findEmployeeList" resultType="pers.fulsun.mybatisplusstudy.entity.Employee">
select * from t_employee
</select>
</mapper>
分页查询
概述
- MyBatisPlus支持分页插件(非PageHelper分页插件)
- MyBatisPlus3+版本不支持PageHelper插件
- 使用MyBatisPlus分页插件需要编写配置类
分页插件配置类
在config包下创建分页插件配置类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15//开启事务
//扫描加载mapper接口
public class MyBatisPlusConfig {
/**
* 分页插件
*/
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
通用Service
概述
- 说明: 通用 Service CRUD 封装 IService 接口,进一步封装 CRUD
- 采用
get 查询单行
remove 删除
list 查询集合
page 分页
, 前缀命名方式区分 Mapper 层避免混淆 - 泛型 T 为任意实体对象 建议如果存在自定义通用 Service 方法的可能,请创建自己的
IBaseService
继承 Mybatis-Plus 提供的基类 - 对象 Wrapper 为 条件构造器 使用通用Service进行CRUD操作,业务层接口只需继承
IService<T>
接口即可,其中T为 泛型。
通用Service的使用
自定义Service接口
自定义Service接口,继承IService接口
1
2
3public interface IUserService extends IService<User> {
}实现类
1
2
3
4
5
6
public class UserServiceImpl extends ServiceImpl<IUserMapper, User> implements IUserService {
}
测试通用Service接口
添加测试类,注入自定义Service接口
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
63
64
65
66
67
68
69
70
71
class UserServiceImplTest {
//注入UserService
private IUserService userService;
/**
* 新增
*/
public void testSave() {
User user = new User();
user.setAge(20);
user.setEmail("test@163.com");
user.setName("test"); //调用新增方法
boolean flag = userService.save(user);
System.out.println(flag ? "新增成功" : "新增失败");
}
/**
* 批量新增
*/
public void testSaveBatch() {
User user1 = new User();
user1.setAge(22);
user1.setEmail("lucy@163.com");
user1.setName("露西");
User user2 = new User();
user2.setAge(20);
user2.setEmail("lulu@163.com");
user2.setName("露露");
//调用新增方法
boolean flag = userService.saveBatch(Arrays.asList(user1, user2));
System.out.println(flag ? "新增成功" : "新增失败");
}
/**
* 批量新增或修改
*/
public void testSaveOrUpdateBatch() {
User user1 = new User();
user1.setId(9);
user1.setAge(22);
user1.setEmail("ross@163.com");
user1.setName("肉丝");
User user2 = new User();
user2.setAge(20);
user2.setEmail("harry@163.com");
user2.setName("harry");
//调用新增方法
boolean flag = userService.saveOrUpdateBatch(Arrays.asList(user1, user2));
System.out.println(flag ? "成功" : "失败");
}
/**
* 查询唯一
*/
public void testGetOne() {
QueryWrapper<User> queryWrapper = new QueryWrapper<User>();
queryWrapper.eq("age", 20);
//会报错
// User user = userService.getOne(queryWrapper);
// 不会报错,但会发出警告
User user = userService.getOne(queryWrapper, false);
System.out.println(user);
}
}
代码生成器
概述
- MyBatisPlus提供了强大的代码生成器,可生成实体类、mapper接口、mapper映射 文件、service接口及实现类、Controller控制器等
- 使用MyBatisPlus提供的代码生成器步骤:
- 第一步:添加相关依赖
- 第二步:编写代码生成器类
代码生成器的使用
添加相关依赖
1 | <dependency> |
编写代码生成器类
1 | package pers.fulsun.mybatisplusstudy; |