尚融宝04-mybatis-plus插件和条件构造器
目录
一、分页插件
1、添加配置类
2、添加分页插件
3、测试分页
二、XML自定义分页
1、UserMapper中定义接口方法
2、定义XML
3、测试
三、乐观锁
1、场景
2、乐观锁方案
3、乐观锁实现流程
4、优化流程
四、wapper介绍
1、Wrapper家族
2、创建测试类
五、QueryWrapper
1、例1:组装查询条件
2、例2:组装排序条件
3、例3:组装删除条件
4、例4:条件的优先级
5、例5:组装select子句
6、例6:实现子查询
六、UpdateWrapper
例7:需求同例4
七、condition
例8:动态组装查询条件
八、LambdaXxxWrapper
1、例9:Query - 需求同例8
2、例10:Update - 需求同例4
尚融宝02-mybatisplus复习 |
尚融宝03-mybatisplus基本CRUD和注解 |
一、分页插件
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
1、添加配置类
创建config包,创建MybatisPlusConfig类
package com.atguigu.mybatisplus.config;@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper") //可以将主类中的注解移到此处
public class MybatisPlusConfig {}
2、添加分页插件
配置类中添加@Bean配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;
}
3、测试分页
创建类InterceptorTests
package com.atguigu.mybatisplus;@SpringBootTest
public class InterceptorTests {@Resourceprivate UserMapper userMapper;@Testpublic void testSelectPage(){//创建分页参数Page<User> pageParam = new Page<>(1,5);//执行分页查询userMapper.selectPage(pageParam, null);//查看分页参数的成员System.out.println(pageParam);}
}
二、XML自定义分页
1、UserMapper中定义接口方法
/*** 查询 : 根据年龄查询用户列表,分页显示** @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位* @param age 年龄* @return 分页对象*/
IPage<User> selectPageByPage(Page<?> page, Integer age);
2、定义XML
<select id="selectPageByPage" resultType="com.atguigu.mybatisplus.entity.User">SELECT <include refid="Base_Column_List"/> FROM user WHERE age > #{age}
</select>
3、测试
@Test
public void testSelectPageVo(){Page<User> pageParam = new Page<>(1,5);userMapper.selectPageByPage(pageParam, 18);List<User> users = pageParam.getRecords();users.forEach(System.out::println);
}
三、乐观锁
1、场景
一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。
此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。
现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1万多。
接下来将我们演示这一过程:
step1:数据库中增加商品表
CREATE TABLE product
(id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',price INT(11) DEFAULT 0 COMMENT '价格',version INT(11) DEFAULT 0 COMMENT '乐观锁版本号',PRIMARY KEY (id)
);INSERT INTO product (id, NAME, price) VALUES (1, '笔记本', 100);
step2:创建实体类
package com.atguigu.mybatisplus.entity;
@Data
public class Product {private Long id;private String name;private Integer price;private Integer version;
}
step3:创建Mapper
package com.atguigu.mybatisplus.mapper;public interface ProductMapper extends BaseMapper<Product> {}
step4:测试
@Resource
private ProductMapper productMapper;@Test
public void testConcurrentUpdate() {//1、小李Product p1 = productMapper.selectById(1L);//2、小王Product p2 = productMapper.selectById(1L);//3、小李将价格加了50元,存入了数据库 100+50=150p1.setPrice(p1.getPrice() + 50);int result1 = productMapper.updateById(p1);System.out.println("小李修改结果:" + result1);//4、小王将商品减了30元,存入了数据库 100-30=70覆盖了小李的150p2.setPrice(p2.getPrice() - 30);int result2 = productMapper.updateById(p2);System.out.println("小王修改结果:" + result2);//最后的结果Product p3 = productMapper.selectById(1L);System.out.println("最后的结果:" + p3.getPrice());
}
2、乐观锁方案
SELECT id,`name`,price,`version` FROM product WHERE id=1
- 更新时,version + 1,如果where语句中的version版本不对,则更新失败
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1
3、乐观锁实现流程
@Version
private Integer version;
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//乐观锁interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;
}
4、优化流程
失败后重试
if(result2 == 0){//更新失败,重试System.out.println("小王重试");//重新获取数据p2 = productMapper.selectById(1L);//更新p2.setPrice(p2.getPrice() - 30);productMapper.updateById(p2);
}
四、wapper介绍
1、Wrapper家族
在MP中我们可以使用通用Mapper(BaseMapper)实现基本查询,也可以使用自定义Mapper(自定义XML)来实现更高级的查询。当然你也可以结合条件构造器来方便的实现更多的高级查询。
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
2、创建测试类
@SpringBootTest
public class WrapperTests {@Resourceprivate UserMapper userMapper;
}
五、QueryWrapper
1、例1:组装查询条件
查询名字中包含n,年龄大于等于10且小于等于20,email不为空的用户
@Test
public void test1() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("name","n").between("age", 10, 20) // 大于等于10小于等于20.isNotNull("email");List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
2、例2:组装排序条件
按年龄降序查询用户,如果年龄相同则按id升序排列
@Test
public void test2() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("age").orderByAsc("id");List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
3、例3:组装删除条件
删除email为空的用户
@Test
public void test3() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.isNull("email");int result = userMapper.delete(queryWrapper); //条件构造器也可以构建删除语句的条件System.out.println("delete return count = " + result);
}
4、例4:条件的优先级
查询名字中包含n,且(年龄小于18或email为空的用户),并将这些用户的年龄设置为18,邮箱设置为 user@atguigu.com
@Test
public void test4() {//修改条件QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("name", "n").and(i -> i.lt("age", 18).or().isNull("email")); //lambda表达式内的逻辑优先运算User user = new User();user.setAge(18);user.setEmail("user@atguigu.com");int result = userMapper.update(user, queryWrapper);System.out.println(result);
}
5、例5:组装select子句
查询所有用户的用户名和年龄
@Test
public void test5() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.select("name", "age");//selectMaps()返回Map集合列表,通常配合select()使用,避免User对象中没有被查询到的列值为nullList<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表maps.forEach(System.out::println);
}
6、例6:实现子查询
@Test
public void test6() {QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.inSql("id", "select id from user where id <= 3");//selectObjs的使用场景:只返回一列List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表objects.forEach(System.out::println);
}
但上面的方式容易引发sql注入,即最后添加一个true使得条件永真
// 或插叙出所有用户id
queryWrapper.inSql("id", "select id from user where id <= 3 or true");
可是使用下面的查询方式替换
queryWrapper.in("id", 1, 2, 3 );
// 或
queryWrapper.le("id", 3 );
六、UpdateWrapper
例7:需求同例4
查询名字中包含n,且(年龄小于18或email为空的用户),并将这些用户的年龄设置为18,邮箱设置为 user@atguigu.com
@Test
public void test7() {//组装set子句UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.set("age", 18).set("email", "user@atguigu.com").like("name", "n").and(i -> i.lt("age", 18).or().isNull("email")); //lambda表达式内的逻辑优先运算//这里必须要创建User对象,否则无法应用自动填充。如果没有自动填充,可以设置为nullUser user = new User();int result = userMapper.update(user, updateWrapper);System.out.println(result);
}
updatewrapper有set方法
七、condition
例8:动态组装查询条件
查询名字中包含n,年龄大于10且小于20的用户,查询条件来源于用户输入,是可选的
@Test
public void test8() {//定义查询条件,有可能为null(用户未输入)String name = null;Integer ageBegin = 10;Integer ageEnd = 20;QueryWrapper<User> queryWrapper = new QueryWrapper<>();if(StringUtils.isNotBlank(name)){queryWrapper.like("name","n");}if(ageBegin != null){queryWrapper.ge("age", ageBegin);}if(ageEnd != null){queryWrapper.le("age", ageEnd);}List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
上面的实现方案没有问题,但是代码比较复杂,我们可以使用带condition参数的重载方法构建查询条件,简化代码的编写
@Test
public void test8Condition() {//定义查询条件,有可能为null(用户未输入)String name = null;Integer ageBegin = 10;Integer ageEnd = 20;QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like(StringUtils.isNotBlank(name), "name", "n").ge(ageBegin != null, "age", ageBegin).le(ageEnd != null, "age", ageEnd);List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
八、LambdaXxxWrapper
1、例9:Query - 需求同例8
@Test
public void test9() {//定义查询条件,有可能为null(用户未输入)String name = null;Integer ageBegin = 10;Integer ageEnd = 20;LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper//避免使用字符串表示字段,防止运行时错误.like(StringUtils.isNotBlank(name), User::getName, "n").ge(ageBegin != null, User::getAge, ageBegin).le(ageEnd != null, User::getAge, ageEnd);List<User> users = userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}
2、例10:Update - 需求同例4
@Test
public void test10() {//组装set子句LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.set(User::getAge, 18).set(User::getEmail, "user@atguigu.com").like(User::getName, "n").and(i -> i.lt(User::getAge, 18).or().isNull(User::getEmail)); //lambda表达式内的逻辑优先运算User user = new User();int result = userMapper.update(user, updateWrapper);System.out.println(result);
}
相关文章:
尚融宝04-mybatis-plus插件和条件构造器
目录 一、分页插件 1、添加配置类 2、添加分页插件 3、测试分页 二、XML自定义分页 1、UserMapper中定义接口方法 2、定义XML 3、测试 三、乐观锁 1、场景 2、乐观锁方案 3、乐观锁实现流程 4、优化流程 四、wapper介绍 1、Wrapper家族 2、创建测试类 五、Qu…...
面试重难点问题(C++)
持续更新!!!!! 网络部分 1.问,四次挥手的过程,和双方状态变化? 挥手这前,两边都是established状态,客户端发起断开请求,向服务器发送fin请求&…...
androidx.appcompat 升级到1.5.1 趟过的坑
APP 要上google play,Android SDK 版本要升级到32;接了一个第三方SDK,不巧的是这个SDK引用appcompat是1.5.1,顺手把appcompat 包升级到1.5.1,这草率的一升,带来的不止一地鸡毛,还有精神上被残忍…...
[C++]反向迭代器
目录 前言: 1 对反向迭代器的构造思想 2 实现反向迭代器 3 完整代码 前言: 本篇文章主要介绍了STL容器当中的反向迭代器,可能有朋友会说:“反向迭代器有什么好学的?不一样还是迭代器吗,我正向能写出来&…...
解析Python编程中的包结构
假设你想设计一个模块集(也就是一个“包”)来统一处理声音文件和声音数据。通常由它们的扩展有不同的声音格式,例如:WAV,AIFF,AU),所以你可能需要创建和维护一个不断增长的各种文件格…...
【前端】深入浅出缓存原理
缓存的基本原理 对于前端来说,缓存主要分为浏览器缓存(比如 localStorage、sessionStorage、cookie等等)以及http缓存,也是本文主要讲述的。 当然叫法也不一样,比如客户端缓存大概包括浏览器缓存和http缓存 所谓htt…...
单调栈图文详解(附Java模板)
🍏🍐🍊🍑🍒🍓🫐🥑🍋🍉🥝 啥是"单调栈",它能解决什么样的问题? 文章目录🦩单调栈的概念&a…...
彻底理解Session、Cookie、Token,入门及实战
文章目录Session Cookie的使用Token的使用Session Cookie的使用 1. Session存储数据 HttpSession session request.getSession(); //Servlet底层通过的SESSIONID,获取Session对象。 session.setAttribute("loginTime",new Date()); out.println(&q…...
为什么运营商大数据可以精准获客?
“获客难”,“获客成本高”,一直是困扰企业的大问题,身边的许多朋友在吐槽客户的意向度不高,总是无法成交,员工非常积极主动去跟踪客户了,但始终事倍功半,这就像是老人们常说的一句老话“热脸贴…...
【数据结构】栈的实现
💯💯💯 本篇主要利用数组来实现栈,对于栈的各种操作都作详细介绍,压栈,出栈以及获取栈中元素的操作都是学习栈的必备知识,快来学起来吧!!!©Ⅰ.栈的概念及…...
【链表OJ题(六)】链表分割
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯长路漫漫浩浩,万事皆有期待 文章目录链表OJ题(六)1. 链表…...
C++类中的三大函数(构造,析构,拷贝)
下面一段话与大家共勉:每个人的一生都会遇到很多边界,有些边界可以突破,有些则不能。那些无法突破的边界就是你的极限,而划分边界的标准就是“阈值”。每次突破阈值之后,人生轨迹就会发生剧烈变化,其间需要…...
【2024考研】计算机考研,4轮复习时间安排
文章目录🎨第1轮复习(暑假前&系统课)英语1/2数学1/2专业课408🎨第2轮复习(开学前&真题)英语1/2试卷数学1/2试卷专业课408试卷🎨第3轮复习(报名前&政治)政治试…...
(十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
系列文章: python网络爬虫专栏 目录 序言 本节学习目标 特别申明 4.7 使用BeautfulSoup解析h...
【经验】项目管理:瀑布式、Scrum
1、瀑布式开发 流程关键词关键人员输出立项简述、周期、预算领导立项申请表、立项评审表策划计划项目经理、QA、CM各种计划书(项目、配置、测试等),评审需求功能项目经理功能列表、需求规格书、需求开发计划等,评审设计UML开发设…...
Learning C++ No.17【STL No.7】双端队列
引言: 北京时间:2023/3/17/7:18,刚刚快乐的早锻炼回来(不对 ,应该说回来有一会了),因为此时我已经吃完早饭,洗过澡了;现在回想起上学期,就算是第二天需要晨跑…...
Snackbar
1.简介 位于底部的提示View 支持侧滑消失 同一时间只有一个 不支持跨Activity展示 国内使用率很低 2.基础使用 2.1 基本展示 Snackbar.make(view, "Content", Snackbar.LENGTH_LONG).show()2.2 设置点击事件 注意不设置点击事件回调,点击按钮的文字不…...
HummerRisk 使用教程:主机检测
1. 概述 HummerRisk 是开源的云原生安全平台,以非侵入的方式解决云原生环境的安全和治理问题。核心能力包括混合云的安全治理和容器云安全检测。 本文将介绍HummerRisk中的主机检测部分功能,包括如何管理主机、管理凭证,以及使用主机检测规…...
【Arduino无线气象站项目】
【Arduino无线气象站项目】 1. 概述2. Arduino无线气象站电路图3. 定制设计电路板4. Arduino无线气象站代码5. 总结1. 概述 使用DHT22传感器测量室外温度和湿度,并使用NRF24L01收发器模块将这些数据无线发送到室内机。在室内机,还有另一个用于测量室内温度和湿度的DHT22传感…...
HTTP详解
一,什么是HTTPHTTP(全称为“超文本传输协议”),是一种应用非常广泛的应用层协议,之前在《初识网络原理》的博客(初识网络原理_徐憨憨!的博客-CSDN博客)中,有详细讲解过TCP/IP五层模型,其中应用层描述了数据…...
cpufreq--处理器功耗控制
cpu 功耗控制 参考框架: cpufreq 框架。 cpufreq 框架提供 cpu 功耗管理接口,以及功耗管理方案。 用户可以通过功耗管理接口(以文件形式提供)来选择管理方案,并设置相关参数。 管理方案的实现则由具体的驱动来完成。…...
做技术,最忌讳东张西望
又好长时间没更新,研二了,忙着做实验、写论文、发论文,再加上给我导做一些事情(都习惯了,以前很不爽的事情,现在居然能这么平静的说出来)。 但这不是我今天说的重点,而是另外一件事…...
Oracle 常见报错问题汇总
Oracle 常见报错问题汇总 报错:ORA-01017: invalid username/password; logon denied报错:ORA-01031: insufficient privileges报错:"ORA-01034: ORACLE not available" 和 "ORA-27101: shared memory realm does not exist"报错:“ORA-00119: invalid…...
单片机连接有人云上传数据
首先采用有人物联网的模块 ,连接有人云平台服务器 看云平台相关配置配置连接设备在线后 添加设备添加设备完成后 添加变量模板 变量模板的添加方式如下 :本次采用的是标准的MODbus 协议添加一个温度变量温度变量如下显示云平台 下发数据 采集01 03 00 00…...
系统集成项目管理工程师:第18章项目风险管理学习笔记
第18章项目风险管理 一、目录 18.1 风险概述 18.1.1 风险的定义 18.1.2 风险的分类 18.1.3 风险的性质 18.2 项目风险管理 18.3 规划风险管理 18.3.1 规划风险管理的输入 18.3.2 规划风险管理的工具与技术 18.3.3 规划风险管理的输出 18.4 识别风险...
【笔试强训选择题】Day3.习题(错题)解析
文章目录 前言一、Day3习题(错题)解析二、Day3习题(原题)练习总结前言 今天我们将进入到第三天的练习,希望能一直坚持下去,不断反思总结错误,得到进步; 一、Day3习题(错…...
基于GPT-4的免费代码生成工具
大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...
Android开发的这一年里,Jetpack的Room源码是怎么狠狠奖励我的?
简述 Android Jetpack的出现统一了Android开发生态,各种三方库逐渐被官方组件所取代。Room也同样如此,逐渐取代竞品成为最主流的数据库ORM框架。这当然不仅仅因为其官方身份,更是因为其良好的开发体验,大大降低了SQLite的使用门槛…...
推荐一款卸载软件的小工具-《UninstallToo》
目录 UninstallToo介绍 UninstallToo下载 UninstallToo使用 总结 UninstallToo介绍 Uninstall Tool 是一款可以用来替代“添加/删除程序”的工具。它允许您显示隐藏的安装程序,按名称过滤已安装程序的列表,强行写在程序,浏览注册表项目&a…...
线程池——JUC随记8
线程池使用方式 1、一池N线程(Executors.newFixedThreadPool(n)) import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class ExecutorDemo {public static void main(String[] args) {ExecutorService execu…...
表白视频制作网站/长沙百度快速排名优化
简介 这节课NeHe课程主要向我们展示了将物理运动规律引入到三维场景中,模拟真实物体的位置变化过程。这节课分别模拟了如下几种运动方式: (1)在重力作用下的抛物线运动; (2)匀速运动 ÿ…...
wordpress默认页面设置/网页制作工具
2013年,天文学家发现了一个小型椭圆星系,然而这个椭圆星系一直是个谜。该星系没有任何特征、没有其他星系的螺旋结构,看起来像是一个被孤立的星系,仿佛与宇宙中所有的外层恒星没有任何关联。为解开离群星系之谜,天文学…...
网站建设招聘要求/seo培训
1、Python中的列表和元组有什么区别? 列表是动态数组,它们不可变且可以重设长度(改变其内部元素的个数)。 元组是静态数组,它们不可变,且其内部数据一旦创建便无法改变。 元组缓存于Python运行时环境&…...
一个公司能备案多个网站吗/搜索引擎实训心得体会
int main(int argc , char *argv[])//测试调用函数 {const char *env_init[] {"USERunkown","PATHmypath",NULL};pid_t pid;if( (pid fork()) < 0 )err_sys("fork error");else if(pid 0)//这个很牛逼的样子哦,还可以这样玩,在子函数里面调…...
wordpress图片加载快/实训百度搜索引擎的总结
题目要求:根据《福建省电网销售电价表》,居民生活用电按3个梯度收费:月用电量150千瓦时及以下部分,每千瓦时0.4463元,151—400千瓦时部分为0.4663元,401千瓦时以上部分为0.5663元,请编写程序&am…...
qq营销/东莞网络优化公司
一大早,U-Mail客服张小姐就被电话催得迅速进入工作状态,原来一位客户心急火燎的说邮件往外界投递失败,但不知什么原因?张小姐迅速联系到客户专享技术工程师刘工,迅速对客户进行远程诊断,即刻排除了故障&…...