MyBatis-Plus深入 —— 条件构造器与插件管理

前言

        在前面的文章中,荔枝梳理了一个MyBatis-Plus的基本使用、配置和通用Service接口,我们发现在MyBatis-Plus的辅助增强下我们不再需要通过配置xml文件中的sql语句来实现基本的sql操作了,不愧是最佳搭档!在这篇文章中,荔枝会着重梳理有关MyBatis-Plus的两个知识点:条件构造器、分页插件和乐观锁插件,希望对有需要的小伙伴有帮助~~~


文章目录

前言

一、条件构造器

1.1 组装查询条件

1.2 组装排序条件

1.3 组装删除条件

1.4 使用QueryWrapper实现修改功能 

1.5 条件优先级

1.6 子查询

1.7 使用UpdateWrapper实现修改功能

1.8 使用Condition组装条件

1.9 LambdaQueryWrapper

1.10 LambdaUpdateWrapper 

二、分页插件

2.1 基本使用 

2.2 自定义分页插件 

三、乐观锁插件

3.1 乐观锁和悲观锁

3.2 乐观锁插件

总结


一、条件构造器

        条件构造器,顾名思义就是用来封装当前我们用来查询的条件的,条件构造器的最顶层的接口是Mapper,被AbstractWrapper继承,其下由三个子类分别是:AbstractLambdaWrapper、UpdateWrapper和QueryWrapper。

1.1 组装查询条件

//条件构造器组装查询条件@Testpublic void testWrapper(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("user_name","crj").between("age",20,30).isNotNull("email");List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

1.2 组装排序条件

//组装排序条件@Testpublic void test1(){//查询用户信息按照年龄的降序排序,若年龄相同则按照id升序排序QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("age").orderByAsc("uid");List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

1.3 组装删除条件

//组装删除条件@Testpublic void test2(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.isNull("email");int result = userMapper.delete(queryWrapper);System.out.println("受影响函数"+result);}

1.4 使用QueryWrapper实现修改功能 

//实现修改功能@Testpublic void  test3(){QueryWrapper<User> queryWrapper = new QueryWrapper<>();//把年龄大于20且姓名为crj或者是邮箱为null的用户信息进行修改queryWrapper.gt("age",20).like("user_name","crj").or().isNull("email");User user = new User();user.setName("CRJ");user.setEmail("123456@123.com");int result = userMapper.update(user,queryWrapper);System.out.println(result);}

1.5 条件优先级

在and()和or()中通过Lambda表达式实现优先级操作,其中Lambda表达式中的条件优先执行。

 //条件优先级@Testpublic  void test4(){//将用户名中含有crj并且(年龄大于20或邮箱为null)的用户信息修改//lambda中的条件优先执行QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.like("user_name","crj").and(i->i.gt("age",20).or().isNull("email"));User user = new User();user.setName("CRJ");user.setEmail("123456@123.com");int result = userMapper.update(user,queryWrapper);System.out.println(result);}

1.6 子查询

//子查询@Testpublic void test5(){//查询id小于等于100的用户信息QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.inSql("uid","select uid from t_user where uid<=100");List<User> list = userMapper.selectList(queryWrapper);}

1.7 使用UpdateWrapper实现修改功能

//使用UpdateWrapper实现修改功能
//将用户名中含有crj并且(年龄大于20或邮箱为null)的用户信息修改@Testpublic  void  test6(){UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();updateWrapper.like("user_name","crj").and(i->i.gt("age",20).or().isNull("email"));updateWrapper.set("user_name","CRJ");userMapper.update(null,updateWrapper);}

1.8 使用Condition组装条件

1.9 LambdaQueryWrapper

    @Testpublic void test8(){String username = "a";Integer ageBegin = null;Integer ageEnd = 30;LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username).ge(ageBegin!=null,User::getAge,ageBegin).le(ageEnd!=null,User::getAge,ageEnd);List<User> list = userMapper.selectList(queryWrapper);list.forEach(System.out::println);}

1.10 LambdaUpdateWrapper 

    @Testpublic  void  test9(){LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();updateWrapper.like(User::getName,"crj").and(i->i.gt(User::getAge,20).or().isNull(User::getEmail));updateWrapper.set(User::getName,"CRJ");userMapper.update(null,updateWrapper);}

二、分页插件

2.1 基本使用 

 分页插件的配置类

package com.crj.mybatisplus_test.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
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;//配置类,配置MyBatisPlus的插件功能
@Configuration
@MapperScan("com.crj.mybatisplus_test.mapper")
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

测试类

package com.crj.mybatisplus_test;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crj.mybatisplus_test.mapper.UserMapper;
import com.crj.mybatisplus_test.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MyBatisPlusPluginsTest {@Autowiredprivate UserMapper userMapper;@Testpublic void test1(){Page<User> page = new Page<>(1,3);userMapper.selectPage(page,null);System.out.println(page);}
}

page对象的几个方法:

  • page.getRecords(): 获取当前页数据
  • page.getCurrent():获取当前页的页码
  • page.getSize():获取每页显示的条数
  • page.getPages(): 获取总页数
  • page.getTotal(): 获取总记录数
  • page.hasNext(): 查看有没有下一页
  • page.hasPrevious():查看有没有上一页

配置类型别名:

mybatis-plus:

        type-aliases-package:全路径 

2.2 自定义分页插件 

        之前借助条件构造器来实现分页的操作,通过查看源码知晓,selectPage要求两个参数,返回值和第一个参数都是IPage类型的,而IPage类型的接口是被Page类对象实现的,因此第一个参数一定是page对象。我们需要在userMapper接口中手写一个方法替代原来的selectPage,同时分页插件的配置文件保持不变,配置好MyBatisPlus的插件功能

UserMapper.java 

package com.crj.mybatisplus_test.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crj.mybatisplus_test.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;@Repository
//继承MyBatis-Plus的BaseMapper接口
public interface UserMapper extends BaseMapper<User> {/*** 根据年龄查询用户信息并分页* @param page mybatis-plus提供的分页对象,必须放在第一个参数中* @param age* @return*/Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);
}

UserMapper.xml 

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.crj.mybatisplus_test.mapper.UserMapper"><!--    Page<User> selectPageVo(@Param("page") Page<User> page,@Param("age") Integer age);--><select id="selectPageVo" resultType="User">select uid,name,age from t_user where age > #{age}</select>
</mapper>

测试类

    @Testpublic void testPageVo(){Page<User> page = new Page<>(1,3);userMapper.selectPageVo(page,20);}

三、乐观锁插件

3.1 乐观锁和悲观锁

        说到乐观锁和悲观锁,我们经常通过一个场景来理解:我们需要对一个值为100的数进行+10操作再进行-30操作,这两步使用多线程执行。A和B线程同时取一个值为100的数C,A对C进行+10操作,B对取出来的值进行-30的操作,如果没有加锁控制,那么A处理的值D不能被B拿到且会被B覆盖。对于加锁这里简单归纳两种:乐观锁和悲观锁,悲观锁会格外注重线程安全,只有等A操作完后才能由B取值;而乐观锁则是通过版本控制的方式来检测是否C被修改了。

未加锁的场景模拟

实体类

package com.crj.mybatisplus_test.pojo;import lombok.Data;@Data
public class Product {private Long id;private String name;private Integer price;private Integer version;}

mapper接口

package com.crj.mybatisplus_test.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.crj.mybatisplus_test.pojo.Product;
import org.springframework.stereotype.Service;@Service
public interface ProductMapper extends BaseMapper<Product> {}

测试类

package com.crj.mybatisplus_test;import com.crj.mybatisplus_test.mapper.ProductMapper;
import com.crj.mybatisplus_test.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;//乐观锁插件使用
@SpringBootTest
public class MyBatisLockTest {@Autowiredprivate ProductMapper productMapper;//模拟线程场景@Testpublic void test1(){Product productA = productMapper.selectById(1);System.out.println("A查询的商品价格"+productA.getPrice());Product productB = productMapper.selectById(1);System.out.println("B查询的商品价格"+productB.getPrice());productA.setPrice(productA.getPrice()+10);productMapper.updateById(productA);productB.setPrice(productB.getPrice()-30);productMapper.updateById(productB);//最后结果Product productC = productMapper.selectById(1);System.out.println("A查询的商品价格"+productC.getPrice());}
}

3.2 乐观锁插件

前面知道乐观锁实现需要加上版本号来控制,因此实体类需要进行通过@Version来设置版本号。

实体类

package com.crj.mybatisplus_test.pojo;import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;@Data
public class Product {private Long id;private String name;private Integer price;@Version //标识乐观锁版本号字段private Integer version;}

MyBatis-Plus插件配置类

需要在配置类中配置好乐观锁插件方法OptimisticLockerInnerInterceptor()

package com.crj.mybatisplus_test.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
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;//配置类,配置MyBatisPlus的插件功能
@Configuration
@MapperScan("com.crj.mybatisplus_test.mapper")
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//配置分页插件interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));//配置乐观锁插件interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

测试类

需要注意的是B修改数据失败后需要重试即可完成任务需求。 

package com.crj.mybatisplus_test;import com.crj.mybatisplus_test.mapper.ProductMapper;
import com.crj.mybatisplus_test.pojo.Product;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;//乐观锁插件使用
@SpringBootTest
public class MyBatisLockTest {@Autowiredprivate ProductMapper productMapper;//模拟线程场景@Testpublic void test1(){Product productA = productMapper.selectById(1);System.out.println("A查询的商品价格"+productA.getPrice());Product productB = productMapper.selectById(1);System.out.println("B查询的商品价格"+productB.getPrice());productA.setPrice(productA.getPrice()+10);productMapper.updateById(productA);productB.setPrice(productB.getPrice()-30);int result = productMapper.updateById(productB);//由于加入了版本号控制,因此需要对修改失败的操作进行重试if(result==0){//失败重试Product productNew = productMapper.selectById(1);productNew.setPrice(productNew.getPrice()-30);productMapper.updateById(productNew);}//最后结果Product productC = productMapper.selectById(1);System.out.println("A查询的商品价格"+productC.getPrice());}
}

总结

        通过条件构造器的几种基本用法使用示例,荔枝对wrapper类的使用有了一个比较直观的理解,同时荔枝觉得更需要注意的是两种插件的使用。接下来的文章中荔枝会对MyBatis-Plus的相关基础知识收尾,同时尝试整合到学习的项目中,跟荔枝一起期待一波吧哈哈哈哈哈~~~

今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/98931.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于使用RT-Thread系统读取stm32的adc无法连续转换的问题解决

关于使用RT-Thread系统读取stm32的adc无法连续转换的问题解决 今天发现rt系统的adc有一个缺陷&#xff08;也可能是我移植的方法有问题&#xff0c;这就不得而知了&#xff01;&#xff09;&#xff0c;就是只能单次转换&#xff0c;事情是这样的&#xff1a; 我在stm32的RT-T…

开源照片管理服务LibrePhotos

本文是为了解决网友 赵云遇到的问题&#xff0c;顺便折腾的。虽然软件跑起来了&#xff0c;但是他遇到的问题&#xff0c;超出了老苏的认知。当然最终问题还是得到了解决&#xff0c;不过与 LibrePhotos 无关&#xff1b; 什么是 LibrePhotos ? LibrePhotos 是一个自托管的开源…

CentOS7安装时直接跳过了安装信息摘要页面的解决方法

最近在配置Hadoop虚拟机的时候&#xff0c;创建的centos7虚拟机在安装信息摘要时直接自动跳过&#xff0c;直接跳到设置用户名和密码&#xff0c;在重复多次的重新删除安装后发现了问题所在&#xff1a; 在进行到选择操作系统来源时&#xff0c;注意是否出现“该操作系统将使用…

数据结构零基础入门篇(C语言实现)

前言&#xff1a;数据结构属于C学习中较难的一部分&#xff0c;对应学习者的要求较高&#xff0c;如基础不扎实&#xff0c;建议着重学习C语言中的指针和结构体&#xff0c;万丈高楼平地起。 一&#xff0c;链表 1&#xff09;单链表的大致结构实现 用C语言实现链表一般是使…

树莓 LUMA-OLED.EXAMPLE使用

详细介绍在文件目录下的README.rst中 第一步 $ sudo usermod -a -G i2c,spi,gpio pi //好像没什么用 $ sudo apt install python3-dev python3-pip python3-numpy libfreetype6-dev libjpeg-dev build-essential //安装依赖包&#xff0c;树莓派中好像已经有了 $ sudo a…

【C++ 二叉搜索树】

目录 1.什么是二叉搜索树2.构建二叉搜索树2.1首先搭建树的框架2.2搭建搜索树的框架 3.二叉搜索树的插入3.1非递归式插入3.2递归式插入 4.二叉搜索树的查找4.1非递归查找4.2递归查找 5.二叉搜索树的删除5.1非递归删除5.2递归删除 6.整个代码实现 1.什么是二叉搜索树 简单来讲就…

STM32CUBEMX_创建时间片轮询架构的软件框架

STM32CUBEMX_创建时间片轮询架构的软件框架 说明&#xff1a; 1、这种架构避免在更新STM32CUBEMX配置后把用户代码清除掉 2、利用这种时间片的架构可以使得代码架构清晰易于维护 创建步骤&#xff1a; 1、使用STM32CUBEMX创建基础工程 2、新建用户代码目录 3、构建基础的代码框…

机器视觉工程,如何快速摸清即将面试公司的基本情况

1.公司背景调查 企业查&#xff0c;天眼查&#xff0c;对一家公司的股东信息&#xff0c;知识产权&#xff0c;经营范围&#xff0c;是否有诉讼&#xff0c;经营范围等等信息&#xff0c;以及网上对其的整体评价&#xff0c;薪资整体水平等等。 2.公司官方网站 有些公司的网…

MySQL表的增删查改以及基本查询样例

文章目录 表的增删查改创建表插入单行全列数据插入多行指定列数据插入失败则更新替换 select全列查询指定列查询查询字段为表达式为查询结果指定别名查询结果去重 where数学小于60的英语在70到100之间的名字为王开头的总分在 200 分以下的语文成绩 > 80 并且不姓王的 结果排…

软件UI工程师工作的岗位职责(合集)

软件UI工程师工作的岗位职责1 职责&#xff1a; 1.负责产品的UI视觉设计(手机软件界面 网站界面 图标设计产品广告及 企业文化的创意设计等); 2.负责公司各种客户端软件客户端的UE/UI界面及相关图标制作; 3.设定产品界面的整体视觉风格; 4.参与产品规划构思和创意过程&…

Matlab信号处理1:模拟去除信号噪声

由于工作内容涉及信号系统、信号处理相关知识&#xff0c;本人本硕均为计算机相关专业&#xff0c;专业、研究方向均未涉及信号相关知识&#xff0c;因此需进行系统地学习。之前已将《信号与系统》快速过了一遍&#xff0c;但感觉较抽象且理解较浅显。在此系统地学习如何使用Ma…

食品化妆品核辐射检测

GB 14883.3-2016 GB 14883.3-2016 这次核污水时间&#xff0c;对我们的生活影响是比较大&#xff0c;尤其是未来几十年几百年的伤害最深&#xff0c;因为这是不可磨灭的伤害&#xff0c;无法去除&#xff01; 所以我要抵制日本任何的食物&#xff0c;尤其是海鲜食品&#xff…