Mybatis-Plus--必备插件
1 分页插件
已知的分页查询解决方案
- 使用数据库limit实现
- 使用PageHelper分页插件(mybatis)
- Mybatis-Plus内置了分页插件
1.1 配置MybatisPlus分页插件
<!-- 配置SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
......
<!-- 添加插件配置 -->
<property name="plugins" ref="plusInterceptor"></property>
</bean>
<!--MybatisPlus插件-->
<bean id="plusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<!--分页插件-->
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"/>
</list>
</property>
</bean>
1.2 分页插件测试
根据 entity 条件,查询全部记录(并分页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
@Test
public void test18(){
//参数1 :当前页 参数2:每页条数
Page page = new Page(2,3);
//参数1:当前页 参数2:条件
userMapper.selectPage(page,null);
System.out.println(page.getTotal()); //总条数
System.out.println(page.getPages()); //总页数
System.out.println(page.getCurrent()); //当前页
System.out.println(page.getSize()); //每一页条数
System.out.println(page.getRecords()); //每一页数据
}
//测试分页查询
@Test
public void testPage(){
Page<User> page = new Page<>(1,3);
userMapper.selectPage(page, null);
//page中包含了分页的相关信息
System.out.println(page);
List<User> userList = page.getRecords();
userList.forEach(System.out::println);
}
2 乐观锁插件
2.1 悲观锁
当我们要对一个数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。
**但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;**另外,还会降低并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数据。
在数据库中演示
-- 会话1
set autocommit = 0 ;
select name,age,email from user where id = 1 for update;
commit;
-- 会话2
set autocommit = 0;
update user set name = 'lisi' where id = 1; -- 此时无法进行修改,必须要等到会话1提交事务
2.2 乐观锁
乐观锁( Optimistic Locking ) 是相对悲观锁而言的,乐观锁假设数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。
在数据库中演示
-- 会话1
select name,age,email,version from user where id = 1
update name='王五',age=30 where id = 1 and version = 1;
-- 更新完毕将version+1
-- 会话2
select name,age,email,version from user where id = 1
update name='赵六',age=30 where id = 1 and version = 1;-- 此时更新失败,version不一致
2.3 MP中实现乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前version
- 更新时,带上这个version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果version不对,就更新失败
2.3.1 配置插件
<!-- 配置SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
......
<!-- 添加插件配置 -->
<property name="plugins" ref="plusInterceptor"></property>
</bean>
<!--MybatisPlus插件-->
<bean id="plusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<!--乐观锁插件-->
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor"/>
</list>
</property>
</bean>
2.3.2 @Version
注解
@Version
private Integer version;
2.3.3 测试乐观锁插件
//乐观锁(更新成功(单线程演示))
@Test
public void testLock1(){
User user = userMapper.selectById(1L);
user.setName("zhangsan");
user.setAge(30);
userMapper.updateById(user);
}
//乐观锁(更新失败(多线程演示))
@Test
public void testLock2(){
//模拟线程1
User user = userMapper.selectById(1L);
user.setName("zhangsan");
user.setAge(30);
//线程1还未来得及更新,模拟线程2执行,此时线程2成功更新,并将version+1
User user1 = userMapper.selectById(1L);
user1.setName("李四");
user1.setAge(31);
userMapper.updateById(user1);
//线程1此时执行,但是无法更新成功,因为version版本与查询版本不一致
userMapper.updateById(user);
}
3 防止全表更新与删除插件
针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
3.1 配置全表更新与删除插件
<!-- 配置SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
......
<!-- 添加插件配置 -->
<property name="plugins" ref="plusInterceptor"></property>
</bean>
<!--MybatisPlus插件-->
<bean id="plusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
<property name="interceptors">
<list>
<!--防止全表更新和删除插件-->
<bean class="com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor"/>
</list>
</property>
</bean>
3.2 测试插件
@Test
public void test21(){
int count = userMapper.delete(null);
System.out.println(count);
}
注意:此时会报错:
Prohibition of table update operation
禁止全表更新操作,必须携带条件