MyBatis-Plus实现分页
一、分页插件实现分页功能
MyBatis Plus自带分页插件,进行配置即可实现分页功能
1.1.添加配置类
在com.augus下创建config包,存放配置类,创建配置类 mybatisPlusInterceptor,内容如下:
package com.augus.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; @Configuration @MapperScan("com.augus.mapper") public class MybatisPlusConfig { /** * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor; } }
1.2.创建测试代码进行测试
创建测试类 MyBatisPlusPage 内容如下:
package com.augus; import com.augus.mapper.UserMapper; import com.augus.pojo.User; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest public class MyBatisPlusPage { @Autowired private UserMapper userMapper; @Test public void testPage(){ //设置分页 Page<User> userPage = new Page<>(0, 4); //如果查询条件为空,则输入null,如果需要则构建queryWrapper userMapper.selectPage(userPage, null); //获取分页数据 List<User> records = userPage.getRecords(); records.forEach(System.out::println); System.out.println("当前的页数:"+userPage.getCurrent()); System.out.println("每页显示的条数:"+userPage.getSize()); System.out.println("总记录数:"+userPage.getTotal()); System.out.println("总页数:"+userPage.getPages()); System.out.println("是否有上一页:"+userPage.hasPrevious()); System.out.println("是否有下一页:"+userPage.hasNext()); } }
结果如下:

二、xml自定义分页
2.1.在mapper下的UserMapper中定义接口方法
package com.augus.mapper; import com.augus.pojo.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.apache.ibatis.annotations.Param; public interface UserMapper extends BaseMapper<User> { /** * 通过年龄查询用户信息进行分页设置 * @param page mybatis-plus插件提供的分页对象,必须是一个参数 * @param age 根据年龄分页 * @return */ Page<User> selectPageVo(@Param("page") Page<?> page, @Param("age") Integer age); }
2.2在resources包下的创建mapper目录存储mapper映射文件
注意mybatis-plus中存放映射文件的包,默认就叫mapper切记,在下面创建UserMapper.xml,内容如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.augus.mapper.UserMapper"> <!-- 注意在yml配置文件中就应该需要指定实体类所在的位置 --> <select id="selectPageVo" resultType="User"> SELECT uid,user_name,age,email FROM t_user WHERE age > #{age} </select> </mapper>
2.3.还是在之前的测试类中进行测试
在之前测试类中添加如下测试方法:
@Test public void testPage02(){ //设置分页 Page<User> userPage = new Page<>(1, 4); //将年龄大于20岁的人员信息进行分页查询 userMapper.selectPageVo(userPage, 20); //获取分页数据 List<User> records = userPage.getRecords(); records.forEach(System.out::println); System.out.println("当前的页数:"+userPage.getCurrent()); System.out.println("每页显示的条数:"+userPage.getSize()); System.out.println("总记录数:"+userPage.getTotal()); System.out.println("总页数:"+userPage.getPages()); System.out.println("是否有上一页:"+userPage.hasPrevious()); System.out.println("是否有下一页:"+userPage.hasNext()); }
执行后,即可查看获取的信息
三、乐观锁
3.1.场景:
在数据库操作的时,有一条商品信息,有两个人同时去,要调整他的商品价格,那么如果两个同时操作,假设原本价格为40,a用户添加了60,价格就变成了100,但是如果b也在a完成调整价格之前也是获取了40,然后给减去了50,这时候就变成了-10,正常来说有一个人在操作数据,必须要等这个人操作完成后,在基于这个人的结果上操作。而乐观锁就是为了解决这个问题
3.2.模拟修改冲突的场景
3.2.1.创建表:
CREATE TABLE `t_product` ( `id` bigint(20) NOT NULL COMMENT '主键ID', `name` varchar(30) DEFAULT NULL COMMENT '商品名称', `price` int(11) DEFAULT '0' COMMENT '价格', `VERSION` int(11) DEFAULT '0' COMMENT '乐观锁版本号', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.2.2.给表中插入数据:
INSERT INTO t_product (id, name, price) VALUES (1, 'python从入门到放弃', 40);
3.2.3.在com.augus.pojo下创建实体类
package com.augus.pojo; import com.baomidou.mybatisplus.annotation.Version; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @AllArgsConstructor @NoArgsConstructor @Data public class Product implements Serializable { private Long id; private String name; private Integer price; private Integer version; }
3.2.4.在com.augus.mapper下创建接口
新建 ProductMapper 内容如下:
package com.augus.mapper; import com.augus.pojo.Product; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface ProductMapper extends BaseMapper<Product> { }
3.2.5.创建测试类
package com.augus; import com.augus.mapper.ProductMapper; import com.augus.mapper.UserMapper; import com.augus.pojo.Product; import com.augus.pojo.User; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @SpringBootTest public class MyBatisPlusLocker { @Autowired private ProductMapper productMapper; @Test public void testConcurrentUpdate(){ //李铁调整价格 Product p1 = productMapper.selectById(1); System.out.println("李铁获取的价格为:"+p1.getPrice()); //张鹭调整价格 Product p2 = productMapper.selectById(1); System.out.println("张鹭获取的价格为:"+p2.getPrice()); //李铁添加价格增加60元,保存数据 p1.setPrice(p1.getPrice()+60); int i1 = productMapper.updateById(p1); System.out.println("李铁修改结果:"+i1); //张鹭添加价格减少50元,保存数据 p2.setPrice(p2.getPrice()-50); int i2 = productMapper.updateById(p2); System.out.println("张鹭修改结果:"+i2); //最后BOSS看到的结果 Product p3 = productMapper.selectById(1); System.out.println("BOSS获取的价格为:"+p3.getPrice()); } }
执行后结果如下:

3.3.乐观锁解决上述问题
3.3.1.实现原理
给数据库表中添加version字段,取出记录时,获取当前version,更新时,version + 1,如果where语句中的version版本不对,则更新失败
3.3.2.乐观锁配置
修改实体类,给version字段添加 @version注解
package com.augus.pojo; import com.baomidou.mybatisplus.annotation.Version; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @AllArgsConstructor @NoArgsConstructor @Data public class Product implements Serializable { private Long id; private String name; private Integer price; @Version private Integer version; }
在配置类中添加乐观锁插件配置
package com.augus.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; @Configuration @MapperScan("com.augus.mapper") public class MybatisPlusConfig { /** * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //添加乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }
3.3.3.需要代码,进行测试
在 MyBatisPlusLocker 类中添加如下方法进行测试:
@Test public void testConcurrentUpdate02(){ //李铁调整价格 Product p1 = productMapper.selectById(1); System.out.println("李铁获取的价格为:"+p1.getPrice()); //张鹭调整价格 Product p2 = productMapper.selectById(1); System.out.println("张鹭获取的价格为:"+p2.getPrice()); //李铁添加价格增加60元,保存数据 p1.setPrice(p1.getPrice()+60); int i1 = productMapper.updateById(p1); System.out.println("李铁修改结果:"+i1); //张鹭添加价格减少50元,保存数据 p2.setPrice(p2.getPrice()-50); int i2 = productMapper.updateById(p2); System.out.println("张鹭修改结果:"+i2); if(i2 == 0){ //失败重试,获取version并更新 Product p3 = productMapper.selectById(1); //设置价格 p3.setPrice(p3.getPrice()-50); i2 = productMapper.updateById(p3); } System.out.println("张鹭重试后的结果为:"+i2); //最后BOSS看到的结果 Product p3 = productMapper.selectById(1); System.out.println("BOSS获取的价格为:"+p3.getPrice()); }
测试执行结果如下:


浙公网安备 33010602011771号