分页插件
MP中自带了分页插件的功能,只需要在配置类中进行简单的配置即可使用分页的相关功能。分页插件常常与前端的分页显示功能相关,为了在前端美观的显示查询到的数据,通常会使用分页插件,将所有的数据分成许多页一页一页的进行显示,不同页的切换使用按钮来完成
MP的插件配置类
@Configuration public class MybatisPlusConfiguration { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { // 创建一个MybatisPlus的插件拦截器 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建分页的插件对象并设置数据库类型 PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false paginationInnerInterceptor.setOverflow(true); // 设置分页的单页最多条数,默认 500 条,-1 不受限制 paginationInnerInterceptor.setMaxLimit(500L); // 将这个分页插件添加到拦截器中并返回 interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } }
自定义方法并调用分页
mapper定义方法
@Mapper @Repository public interface UserMapper extends BaseMapper<User> { /** * 通过年龄查询用户信息并分页返回 * @param page 传入一个page对象 * @param age 年龄 * @return 返回一个page对象 */ Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age); }
映射文件编写SQL语句
<mapper namespace="com.xiaochen.mapper.UserMapper"> <select id="selectPageVo" resultType="com.xiaochen.domain.User"> select id,name,age,email from user where age > #{age} </select> </mapper>
测试方法调用自定义方法
@Autowired UserMapper mapper; @Test public void testpage() { // 创建一个page对象,设置当前页是第1页,每页包含3条记录 Page<User> page = new Page<>(2, 3); // mapper调用selectPage方法之后将结果返回给上面的page对象 // 第二个参数null的话就是查询所有的记录,如果有查询条件的话就传一个wrapper对象 mapper.selectPageVo(page, 20); // 当前页的数据 System.out.println(page.getRecords()); // 当前是第几页 System.out.println(page.getCurrent()); // 总页数 System.out.println(page.getPages()); // 每页的记录数 System.out.println(page.getSize()); // 总记录数 System.out.println(page.getTotal()); // 是否有下一页 System.out.println(page.hasNext()); // 是否有上一页 System.out.println(page.hasPrevious()); }
乐观锁插件
要想使用乐观锁插件,首先要知道什么是乐观锁以及乐观锁出现的原因。现实生活中,一个管理系统往往不仅仅只有一个管理员,以修改商品价格为例,如果有两个管理员小李和小王商品的原价为100,老板先是让小李将商品的价格上调50,一段时间后让小王将商品的价格下调20,由于小李有事耽搁,两个人同时登录管理系统获取到商品的价格对其分别进行修改操作。如果小李最后完成操作的话商品最终为150元,如果小王最后完成操作的话商品最终为80元,这样的话就会造成最终的价格不是老板想要的130。
要想使用代码实现上述案例的话,使用线程来实现的话更加真实(可以模拟两人处理先后的不确定性),但是为了简化操作,设定最后完成操作的是小王,也即是说最后商品的价格为80
@Test public void happyLockTest() { // 小李查询商品的价格 Product productLi = mapper.selectById(1); // 小王查询到商品的价格 Product productWang = mapper.selectById(1); // +50 productLi.setPrice(productLi.getPrice() + 50); mapper.updateById(productLi); // -20 productWang.setPrice(productWang.getPrice() - 20); mapper.updateById(productWang); // 查询最终的商品价格 System.out.println("最终价格为:" + mapper.selectById(1).getPrice()); } // 控制台最终打印 -> 最终价格为:80
有问题就有解决问题的方法,出现这个问题的原因就是两个管理员同时获取到了商品的信息并对他进行了修改,如果可以使用锁限制同一时间只能有一个管理员对数据进行修改操作的话,就可以避免这个问题了,这就是悲观锁。
不对啊,不是说要讲乐观锁的嘛怎么讲到了悲观锁了?悲观锁将整张表锁住了,阻止其他人对表进行修改操作,这样的话对效率有很大的折损。于是乐观锁应运而生,乐观锁允许任何人任何时候对表中数据进行修改,只不过数据表中要添加一个字段表示数据的当前版本号,数据每经过一次更新版本号就相应加一,数据每次更新的时候都会带上版本号字段作为更新的条件。这样的话就可以避免之前的问题了,两人同时获取到的版本都是0,小李修改之后就会将版本字段值加一也就是1,这时小王修改的时候就会查不到表中版本号为0的数据而无法修改。
这样的话就会避免修改冲突,但是还是无法得到想要的结果,于是可以对两人的修改结果进行判断,如果更新操作的返回结果不是0的话就说明更新成功,否则就再次获取数据表中的信息(这次就是为了获得最新的版本号)再次进行更新操作
使用MP中的乐观锁插件,首先需要在配置类中将乐观锁插件添加到拦截器中,然后再在实体类中的版本号字段上使用@Version标志,然后就是和平常一样的操作数据库即可,执行更新操作的时候会自动将当前查询到的版本号当做条件拼接到SQL语句中
// 将乐观锁插件添加到拦截器中 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 实体类标注版本号 @Version private Integer version; // 测试方法,测试两个人最后的修改结果 @Test public void happyLockTest() { // 小李查询商品的价格 Product productLi = mapper.selectById(1); // 小王查询到商品的价格 Product productWang = mapper.selectById(1); // +50 int result = 0; do { // 更新失败,重新查询并修改 productLi = mapper.selectById(1); productLi.setPrice(productLi.getPrice() + 50); result = mapper.updateById(productLi); } while (result == 0); // -20 do { // 更新失败,重新查询并修改 productWang = mapper.selectById(1); productWang.setPrice(productWang.getPrice() - 20); result = mapper.updateById(productWang); } while (result == 0); // 查询最终的商品价格 System.out.println("最终价格为:" + mapper.selectById(1).getPrice()); } // 控制台最终打印 -> 最终价格为:130