SpringBoot整合mybatis-plus进阶详细教程
作者:qq_44737094 发布时间:2023-11-27 05:13:12
前言
关于mybatis-plus的简介以及基本使用,我在《SpringBoot整合mybatis-plus–入门超详细》一文中已做介绍,此处不再赘述。本文主要对mybatis-plus的条件构造器、AR模式、插件、逆向工程、自定义全局操作、公共字段自动填充等知识点进行讲解。
wapper介绍 :
Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
QueryWrapper : Entity 对象封装操作类,不是用lambda语法
UpdateWrapper : Update 条件封装,用于Entity对象更新操作
条件构造器 AbstractWrapper
上一节我们完成了基于mybatis-plus的CRUD操作,这一节我们来学习一下使用mybatis-plus中的条件构造器——AbstractWrapper。
一、什么是AbstractWrapper
QueryWrapper(LambdaQueryWrapper)
和UpdateWrapper(LambdaUpdateWrapper)
的父类用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
首先我们来介绍一下AbstractWrapper,下图是AbstractWrapper的一个继承结构:
二、QueryWrapper(LambdaQueryWrapper)
由于其中方法太多就不一一赘述,想看全部方法用法可以看官网介绍或者看我的实例代码
1、QueryWrapper用法示例
查询id在1 - 30且性别为男、姓名带有test的用户:
@SpringBootTest
@SuppressWarnings("unchecked")
public class UserWrapperTest {
@Autowired
UserMapper userMapper;
@Test
public void TestQueryWrapper(){
QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
userQueryWrapper.like("name","test");
userQueryWrapper.eq("sex","男");
userQueryWrapper.between("id",1,30);
userMapper.selectList(userQueryWrapper).forEach(System.out::println);
}
}
注:eq是equals的简写,该方法两个参数,column和value,表示column的值和value要相等。
此处like方法就是查询name中包含“test”字样的记录;between方法三个参数,分别是column、value1、value2,该方法表示column的值要在value1和value2之间。
注意column是数据表对应的字段,而非实体类属性字段。
运行日志
2、LambdaQueryWrapper用法示例
LambdaQueryWrapper是mybatis plus中的一个条件构造器对象,只是是需要使用Lambda 语法使用 Wrapper
@Test
public void TestLambdaQueryWrapper() {
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.like(User::getName,"test");
lambdaWrapper.eq(User::getSex,"男");
lambdaWrapper.between(User::getId,1,30);
userMapper.selectList(lambdaWrapper).forEach(System.out::println);
}
运行日志
三、UpdateWrapper(LambdaUpdateWrapper)
我们再进行更新或者删除的时候,有时候where条件复杂的话,可以使用UpdateWrapper来构造条件
他们有部分方法是和上面的QueryWrapper(LambdaQueryWrapper)
相同的。这里演示不同之处
1、UpdateWrapper用法示例
将名字包含test1的用户名改为test1.1 :
@Test
public void TestUpdateWrapper() {
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
//继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
//及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!
User user = User.builder().build();
//修改语句
updateWrapper.set("name", "test1.1");
//条件
updateWrapper.like("name", "test1");
userMapper.update(user, updateWrapper);
}
运行日志
2、LambdaUpdateWrapper用法示例
@Test
public void TestLambdaUpdateWrapper() {
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
//LambdaUpdateWrapper<User> updateWrapper = new UpdateWrapper<User>().lambda();
User user = User.builder().build();
//修改语句
updateWrapper.set(User::getName, "test1.1");
//条件
updateWrapper.like(User::getName, "test1");
userMapper.update(user, updateWrapper);
}
mybatis-plus的插件
mybatis-plus提供了很多好用的插件,而且配置简单,使用方便。接下来一起看看MP的插件如何使用。
一、分页插件
BaseMapper的selectPage方法和AR提供的selectPage方法都不是物理分页,需要配置分页插件后才是物理分页,那么现在就来看看如何配置这个插件。分页查询
1、配置分页插件
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @program: springboot
* @description:
* @author: King
* @create: 2021-09-08 13:18
*/
@Configuration
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题
* 3.4.3不用设置
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
这个配置摘抄自官方示例
2、测试代码
@Autowired
UserMapper userMapper;
@Test
public void Test2() {
//配置了分页插件后,使用selectpage方法,
//但是现在就是真正的物理分页了,sql语句中有limit了
Page<User> page = new Page<>(1, 10);
IPage<User> selectPage = userMapper.selectPage(page, null);
System.out.println(selectPage);
System.out.println("================= 相关的分页信息 ==================");
System.out.println("总条数:" + selectPage.getTotal());
System.out.println("当前页码:" + selectPage.getCurrent());
System.out.println("总页数:" + selectPage.getPages());
System.out.println("每页显示条数:" + selectPage.getSize());
System.out.println("是否有上一页:" + page.hasPrevious());
System.out.println("是否有下一页:" + page.hasNext());
System.out.println("查询结果:");
List<User> list = selectPage.getRecords();
list.forEach(o -> System.out.println(o));
// page.getRecords().forEach(o -> System.out.println(o));
//还可以将查询到的结果set进page对象中
page.setRecords(list);
//也可以通过page调用相关方法获取到相关的分页信息,而且还可以把查询到的结果set回page对象中,方便前端使用。
}
运行结果
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17aa8a11] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1963906615 wrapping com.mysql.cj.jdbc.ConnectionImpl@5190010f] will not be managed by Spring
==> Preparing: SELECT COUNT(*) FROM User
==> Parameters:
<== Columns: COUNT(*)
<== Row: 31
<== Total: 1
==> Preparing: SELECT id,name,sex,pwd,email FROM User LIMIT ?
==> Parameters: 10(Long)
<== Columns: id, name, sex, pwd, email
<== Row: 2, test1.1, 女, aaaa, 1231@qq.com
<== Row: 3, test2, 男, aaaa, 1232@qq.com
<== Row: 4, test3, 女, aaaa, 1233@qq.com
<== Row: 5, test4, 男, aaaa, 1234@qq.com
<== Row: 6, test5, 女, aaaa, 1235@qq.com
<== Row: 7, test6, 男, aaaa, 1236@qq.com
<== Row: 8, test7, 女, aaaa, update@qq.com
<== Row: 9, test8, 男, aaaaaa, 1238@qq.com
<== Row: 42, test, 男, aaa, a@qq.com
<== Row: 43, test, 男, aaa, a@qq.com
<== Total: 10
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17aa8a11]
com.baomidou.mybatisplus.extension.plugins.pagination.Page@44286963
================= 相关的分页信息 ==================
总条数:31
当前页码:1
总页数:4
每页显示条数:10
是否有上一页:false
是否有下一页:true
查询结果:
User(id=2, name=test1.1, sex=女, pwd=aaaa, email=1231@qq.com)
User(id=3, name=test2, sex=男, pwd=aaaa, email=1232@qq.com)
User(id=4, name=test3, sex=女, pwd=aaaa, email=1233@qq.com)
User(id=5, name=test4, sex=男, pwd=aaaa, email=1234@qq.com)
User(id=6, name=test5, sex=女, pwd=aaaa, email=1235@qq.com)
User(id=7, name=test6, sex=男, pwd=aaaa, email=1236@qq.com)
User(id=8, name=test7, sex=女, pwd=aaaa, email=update@qq.com)
User(id=9, name=test8, sex=男, pwd=aaaaaa, email=1238@qq.com)
User(id=42, name=test, sex=男, pwd=aaa, email=a@qq.com)
User(id=43, name=test, sex=男, pwd=aaa, email=a@qq.com)
可以看到通过分页插件 sql语句中已经有了limit,是物理分页了。并且是否有上一页下一页也有展示非常好用
3、自定义分页条件
示例:
只需要在你的 UserMapper.java 中加入你自定义的分页方法,也可以按你自定义方法实现分页。UserMapper可以继承或者不继承BaseMapper
@Mapper
//表明这是一个Mapper,也可以在启动类上加上包扫描
//Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
public interface UserMapper extends BaseMapper<User> {
/**
* 查询 : 根据性别查询用户列表,分页显示
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @param sex 性别
* @return 分页对象
*/
@Select("SELECT * FROM user WHERE sex = #{sex}")
IPage<User> selectPageBySex(Page<?> page, String sex);
}
测试代码
@Test
public void Test3() {
Page<User> page = new Page<>(2, 10);
IPage<User> selectPage = userMapper.selectPageBySex(page, "男");
System.out.println("================= 相关的分页信息 ==================");
System.out.println("总条数:" + selectPage.getTotal());
System.out.println("当前页码:" + selectPage.getCurrent());
System.out.println("总页数:" + selectPage.getPages());
System.out.println("每页显示条数:" + selectPage.getSize());
System.out.println("是否有上一页:" + page.hasPrevious());
System.out.println("是否有下一页:" + page.hasNext());
System.out.println("分页结果");
selectPage.getRecords().forEach(System.out::println);
}
运行结果
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a0f2853] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1312762120 wrapping com.mysql.cj.jdbc.ConnectionImpl@7e87ef9e] will not be managed by Spring
==> Preparing: SELECT COUNT(*) FROM user WHERE sex = ?
==> Parameters: 男(String)
<== Columns: COUNT(*)
<== Row: 17
<== Total: 1
==> Preparing: SELECT * FROM user WHERE sex = ? LIMIT ? OFFSET ?
==> Parameters: 男(String), 10(Long), 10(Long)
<== Columns: id, name, sex, pwd, email
<== Row: 52, test28, 男, aaaa, a28@qq.com
<== Row: 54, test30, 男, aaaa, a30@qq.com
<== Row: 56, test32, 男, aaaa, a32@qq.com
<== Row: 58, test34, 男, aaaa, a34@qq.com
<== Row: 60, test36, 男, aaaa, a36@qq.com
<== Row: 62, test38, 男, aaaa, a38@qq.com
<== Row: 64, Test, 男, aaaaa, 1234@qq.com
<== Total: 7
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6a0f2853]
================= 相关的分页信息 ==================
总条数:17
当前页码:2
总页数:2
每页显示条数:10
是否有上一页:true
是否有下一页:false
分页结果
User(id=52, name=test28, sex=男, pwd=aaaa, email=a28@qq.com)
User(id=54, name=test30, sex=男, pwd=aaaa, email=a30@qq.com)
User(id=56, name=test32, sex=男, pwd=aaaa, email=a32@qq.com)
User(id=58, name=test34, sex=男, pwd=aaaa, email=a34@qq.com)
User(id=60, name=test36, sex=男, pwd=aaaa, email=a36@qq.com)
User(id=62, name=test38, sex=男, pwd=aaaa, email=a38@qq.com)
User(id=64, name=Test, sex=男, pwd=aaaaa, email=1234@qq.com)
二、性能分析插件
这个插件PerformanceInterceptor
在3.2.0被移除了,如果想进行性能分析,用第三方的,官方这样写的“该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行 SQL 分析打印 功能
”
三、执行分析插件
–防止全表更新与删除
1、配置插件
和上面的分页插件类似
//BlockAttackInnerInterceptor
//针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor3() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 执行分析插件
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
return interceptor;
}
2、测试代码
@Test
public void Test4(){
//条件为null,就是删除全表,执行分析插件会终止该操作
userMapper.delete(null);
}
3、执行结果
运行该junit测试,可以看到报如下错误,说明该插件生效了。
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e9f2c32] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@480645280 wrapping com.mysql.cj.jdbc.ConnectionImpl@49433c98] will not be managed by Spring
original SQL: DELETE FROM User
SQL to parse, SQL: DELETE FROM User
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7e9f2c32]org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error updating database. Cause: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of full table deletion
### The error may exist in com/king/mybatis_plus/mapper/UserMapper.java (best guess)
### The error may involve com.king.mybatis_plus.mapper.UserMapper.delete
### The error occurred while executing an update
### Cause: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of full table deletion
未完待续。。。
来源:https://blog.csdn.net/qq_44737094/article/details/120004420
猜你喜欢
- 0x00:前言参考之前的《MyBatis 中 SqlMapConfig 配置文件详解》记了一下 MyBatis 中的核心配置文件各个标签的作
- 一、新建BeanUtil类import lombok.extern.slf4j.Slf4j;import org.springframewo
- 介绍:上篇给大家介绍了ssm多模块项目的搭建,在搭建过程中spring整合springmvc和mybatis时会有很多的东西需要我们进行配置
- 前言我们知道在Java中除了基础的数据类型以外,其它的都为引用类型。而Java根据其生命周期的长短将引用类型又分为强引用、软引用、弱引用、幻
- Java8 HashMap键与Comparable接口最容易使 HashMap 发生哈希冲突的方法是什么呢?我们可以创建一个类,让它的哈希函
- 题目要求思路一:暴力模拟由于数据范围不算离谱,所以直接遍历解决可行。Javaclass Solution { pu
- 一、IO流的分类字符流ReaderInputStreamReader(节点流)BufferedReader(处理流)WriterOutput
- Springboot获取上下文ApplicationContext在项目中遇到了一个场景,就是通过获得上下文然后获取特定的bean。在此遇到
- 目录一,功能二,工具三、效果图:四、数据库设计五、JAVA层次分析六、主要Java代码分析一,功能管理员登录图书借阅信息管理图书信息管理管理
- Allatori混淆技术介绍Allatori是一个Java 混淆器,它属于第二代混淆器,因此它能够全方位地保护你的知识产权。 Allator
- 概述 wsimport是jdk自带的命令,可以根据wsdl文档生成客户端中间代码,基于生成的代码编写客户端,可以省很多麻烦。先看两张截图:使
- 单选题:(每道题目2分)1. 下列哪个声明是错误的?(B) A. int i=10;B. float f=1.1;&
- 前言之前我们提到了 CustomPaint er 的 Paint 可以使用渐变(GradientShader)来填充绘制的图形,本篇我们来介
- 本文实例为大家分享了Java手写线程池的实现代码,供大家参考,具体内容如下1.线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在
- HttpServletResponse.sendRedirect与RequestDispatcher.forward方法都可以实
- 目录1. 结论先出JSR 380Valid VS Validated 不同点?Validator2. @Valid和@Validated 注
- 由于 Spring 拥有对象的管理权,所以我们也需要拥有较为高效的对象存储和取出的手段,下面我们来分别总结一下:存对象配置文件在存储对象之前
- 重新认识 Java 的 System.in以前也写过不少命令行的程序,处理文件时总需要通过参数指定路径,直到今天看资料时发现了一种我自己从来
- 井字棋游戏要求在3乘3棋盘上,每行都相同或者每列都相同再或者对角线相同,则胜出.因此我们可以使用一个二维数组来表示棋盘,判断胜负只需要判断数
- 为什么要重复造轮子你可能会问,Spring已经自带了全局异常拦截,为什么还要重复造轮子呢?这是个好问题,我觉得有以下几个原因装逼Spring