mybatis plus官方文档:https://mp.baomidou.com/
悲观锁与乐观锁
乐观锁: 顾名思义就是非常乐观,它总是认为不会出现问题 , 无论干什么都不去上锁,如果出现了问题,再次更新值测试
悲观锁: 顾名思义十分悲观,它总是认为会出现问题,无论干什么都会上锁,再去操作
乐观锁实现方式:
1.取出记录时,获取当前的version
2.更新时,带上这个version
3.执行更新时,set version=new version where versio = oldVersion
4.如果version不对,就更新失败
1.给数据库添加version字段
2.实体类添加对应的字段
@Version//乐观锁注解version
private Integer version;
3.注册组件(OptimisticLockerInterceptor 乐观锁接收器)
//mybatisPlus配置类
@EnableTransactionManagement//自动管理事务
@Configuration
@MapperScan("com.chen.Mapper")
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor(){
return new OptimisticLockerInterceptor();
}
}
测试一下:
//测试乐观锁成功的
@Test
public void testOptimisticLockerInterceptor(){
//查询用户信息
User user = usermapper.selectById(1L);
//修改用户信息
user.setName("kuangshen").setEmail("2240559679@qq.com");
//执行更新操作
//updateById里面需要的是一个对象
usermapper.updateById(user);
}
结果看到先查询出来,然后执行更新操作的时候sql语句会自动加上where version=?
接下来模拟线程插队情况下失败的案例
//测试乐观锁失败的
@Test
public void testOptimisticLockerInterceptor2(){
//查询用户信息
User user = usermapper.selectById(1L);
//修改用户信息
user.setName("kuangshen111").setEmail("2240559679@qq.com");
//模拟另外一个线程执行了插队操作
User user1 = usermapper.selectById(1L);
user1.setName("kuangshen222").setEmail("2240559679@qq.com");
usermapper.updateById(user1);
//执行更新操作
//updateById里面需要的是一个对象
usermapper.updateById(user);//如果没有乐观锁就会覆盖插队线程的值
}
查询操作
批量查询用户selectBatchIds
查询id为1,2,3的用户
@Test
public void selectBatchIds(){
List<User> user = usermapper.selectBatchIds(Arrays.asList(1 ,2 ,3 ));
user.forEach(System.out::println);
}
复杂的查询操作,使用map
@Test
public void testBatchIds(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","陈述智");
usermapper.selectByMap(map);
}
分页查询
1.原始的limit进行分页
2.第三方插件pageHelper
3.mybatis plus内置分页插件
使用
1.注册分页插件
//注册分页插件
@Bean
public PaginationInterceptor paginationInterceptor(){
return new PaginationInterceptor();
}
测试
@Test
public void pagination(){
//参数一:当前页
//参数二:页面大小
Page<User> page = new Page<>(1,5);
IPage<User> userIPage = usermapper.selectPage(page, null);
page.getRecords().forEach(System.out::println);
}
逻辑删除
物理删除:从数据库中直接移除
逻辑删除: 在数据库中没有被移除,而是通过一个变量来让他失效! delete=0 =>delete=1
管理员可以查看被删除的记录,防止数据丢失,类似于回收站;
实现步骤
1.数据库中添加delete字段
2.实体类中添加对应的字段
@TableLogic //意思是表逻辑的意思,这里就是逻辑删除的注解
private Integer delete;
3.添加逻辑删除组件
//逻辑删除组件
@Bean
public ISqlInjector iSqlInjector(){
return new LogicSqlInjector();
}
4.application.yml配置逻辑删除配置,逻辑删除的字段值为1,没有删除的为0
#mybatis plus配置日志
mybatis-plus:
configuration:
#控制台输出日志 这里也可以使用log4j
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#配置逻辑删除
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
测试:
//测试删除
@Test
public void testDelete(){
usermapper.deleteById(1L);
}
这里看到数据并不会直接删除,而是更新操作,把字段的deleteField的值变为1
接下来我们再去查询一次啊刚刚执行了逻辑删除操作的数据
可以看到为null
性能分析插件
我们平时开发中,会遇到慢sql.
mybatis plus中也提供了性能分析插件,如果超过这个时间就会停止运行
1.导入插件
//导入性能分析插件的组件,
@Bean
@Profile({"dev", "test"})//这里是设置dev 还有test环境开启性能分析插件
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(1); //设置sql执行的最大时间,如果超过则不执行 默认为毫秒
performanceInterceptor.setFormat(true);//sql格式化
return performanceInterceptor;
}
2.测试使用
根据id查询一个用户可以看到如下结果
可以看到已经查到了,但是为什么会报错呢 .只要超过了规定时间就会抛出异常 看看这里
这个sql的执行时间太长了!这是因为我们设置了sql执行时间为一毫秒!!!更改则执行没问题.
记住要在springboot中配置环境为dev或者test环境
条件构造器
十分重要,我们写一些复杂的sql可以使用它来代替:wrapper
测试一:查询name不为空并且email不为空,还有age大于十二岁的用户
@Test
void contextLoads() {
//查询name不为空并且邮件不为空且年龄大于十二岁的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",12);
usermapper.selectList(wrapper).forEach(System.out::println);
}
测试二:根据名字查找用户
//根据名字查询一个用户
@Test
void test2() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.eq("name","chen");
User user = usermapper.selectOne(wrapper);
System.out.println(user);
}
测试三:查找年龄为二十岁到三十岁之间的用户
//查询年龄在二十岁到三十岁的用户
@Test
void test3() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.between("age",20,30);
Integer count = usermapper.selectCount(wrapper);
System.out.println(count);
}
测试四:模糊查询
@Test
public void test4(){
//likeRight : 就是%写在右边 例如 t%
//likeLeft : 就是%写在左边 例如 %t
//notLike : 不包含
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.notLike("name","c")
.likeRight("email","1");
List<Map<String, Object>> maps = usermapper.selectMaps(wrapper);
}
测试五:连接查询
@Test
public void test5(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//id是在子查询中查出来的
wrapper
.inSql("id","select id from user where id < 3");
List<Object> list = usermapper.selectObjs(wrapper);
list.forEach(System.out::println);
}
测试六:排序
//测试排序
@Test
public void test6() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByAsc("id");
List<User> users = usermapper.selectList(wrapper);
users.forEach(System.out::println);
}
代码自动生成器
dao、pojo、service、controller都给我自己去编写完成!
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、
Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
测试: