雄安投资建设集团有限公司网站,平面设计师必看的网站,seo百度点击软件,行政事业单位网站建设建议前言 在前面的文章中#xff0c;荔枝梳理了一个MyBatis-Plus的基本使用、配置和通用Service接口#xff0c;我们发现在MyBatis-Plus的辅助增强下我们不再需要通过配置xml文件中的sql语句来实现基本的sql操作了#xff0c;不愧是最佳搭档#xff01;在这篇文章中#xff0c…前言 在前面的文章中荔枝梳理了一个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(){QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.like(user_name,crj).between(age,20,30).isNotNull(email);ListUser list userMapper.selectList(queryWrapper);list.forEach(System.out::println);}
1.2 组装排序条件
//组装排序条件Testpublic void test1(){//查询用户信息按照年龄的降序排序若年龄相同则按照id升序排序QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.orderByDesc(age).orderByAsc(uid);ListUser list userMapper.selectList(queryWrapper);list.forEach(System.out::println);}
1.3 组装删除条件
//组装删除条件Testpublic void test2(){QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.isNull(email);int result userMapper.delete(queryWrapper);System.out.println(受影响函数result);}
1.4 使用QueryWrapper实现修改功能
//实现修改功能Testpublic void test3(){QueryWrapperUser 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(123456123.com);int result userMapper.update(user,queryWrapper);System.out.println(result);}
1.5 条件优先级
在and()和or()中通过Lambda表达式实现优先级操作其中Lambda表达式中的条件优先执行。 //条件优先级Testpublic void test4(){//将用户名中含有crj并且年龄大于20或邮箱为null的用户信息修改//lambda中的条件优先执行QueryWrapperUser 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(123456123.com);int result userMapper.update(user,queryWrapper);System.out.println(result);}
1.6 子查询
//子查询Testpublic void test5(){//查询id小于等于100的用户信息QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.inSql(uid,select uid from t_user where uid100);ListUser list userMapper.selectList(queryWrapper);}
1.7 使用UpdateWrapper实现修改功能
//使用UpdateWrapper实现修改功能
//将用户名中含有crj并且年龄大于20或邮箱为null的用户信息修改Testpublic void test6(){UpdateWrapperUser 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;LambdaQueryWrapperUser queryWrapper new LambdaQueryWrapper();queryWrapper.like(StringUtils.isNotBlank(username),User::getName,username).ge(ageBegin!null,User::getAge,ageBegin).le(ageEnd!null,User::getAge,ageEnd);ListUser list userMapper.selectList(queryWrapper);list.forEach(System.out::println);}
1.10 LambdaUpdateWrapper Testpublic void test9(){LambdaUpdateWrapperUser 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(){PageUser 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 BaseMapperUser {/*** 根据年龄查询用户信息并分页* param page mybatis-plus提供的分页对象必须放在第一个参数中* param age* return*/PageUser selectPageVo(Param(page) PageUser page,Param(age) Integer age);
}UserMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapperPUBLIC -//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.crj.mybatisplus_test.mapper.UserMapper!-- PageUser selectPageVo(Param(page) PageUser page,Param(age) Integer age);--select idselectPageVo resultTypeUserselect uid,name,age from t_user where age #{age}/select
/mapper
测试类 Testpublic void testPageVo(){PageUser page new Page(1,3);userMapper.selectPageVo(page,20);} 三、乐观锁插件
3.1 乐观锁和悲观锁 说到乐观锁和悲观锁我们经常通过一个场景来理解我们需要对一个值为100的数进行10操作再进行-30操作这两步使用多线程执行。A和B线程同时取一个值为100的数CA对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 BaseMapperProduct {}测试类
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(result0){//失败重试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的相关基础知识收尾同时尝试整合到学习的项目中跟荔枝一起期待一波吧哈哈哈哈哈~~~ 今朝已然成为过去明日依然向往未来我是小荔枝在技术成长的路上与你相伴码文不易麻烦举起小爪爪点个赞吧哈哈哈~~~ 比心心♥~~~