展开
拓展 关闭
订阅号推广码
GitHub
视频
公告栏 关闭

插件

分页插件

  • 编写配置类
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
  • 测试
@SpringBootTest
public class MyBatisPlusPluginsTest {
    @Autowired
    private UserMapper userMapper;

    @Test
    public void testPage(){
        Page<User> page = new Page<>(2, 3);
        userMapper.selectPage(page, null);
        System.out.println(page.getRecords());  // 获取当前页数据
        System.out.println(page.getPages());    // 总页数
        System.out.println(page.getTotal());    // 总记录数
        System.out.println(page.hasNext());     // 是否有上一条
        System.out.println(page.hasPrevious()); // 是否有下一条
    }
}
  • 自定义xml
# mapper
@Repository
public interface UserMapper extends BaseMapper<User> {
    /**
     * 通过年龄查询用户信息并分页
     * @param page MyBatis-Plus所提供的分页对象,必须位于第一个参数的位置
     * @param age
     * @return
     */
    Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
}

# xml
<select id="selectPageVo" resultType="User">
    select uid,user_name,age,email from t_user where age > #{age}
</select>

# yml
mybatis-plus:
  # 配置类型别名所对应的包
  type-aliases-package: com.atguigu.mybatisplus.pojo

# 测试
@Test
public void testPageVo(){
    Page<User> page = new Page<>(1, 3);
    userMapper.selectPageVo(page, 20);
    System.out.println(page.getRecords());
    System.out.println(page.getPages());
    System.out.println(page.getTotal());
    System.out.println(page.hasNext());
    System.out.println(page.hasPrevious());
}

乐观锁插件

  • 当2个事务同时操作1条数据时,会产生冲突,这时需要使用锁

  • 模拟冲突

# 创建表
CREATE TABLE t_product
(
id BIGINT(20) NOT NULL COMMENT '主键ID',
NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
price INT(11) DEFAULT 0 COMMENT '价格',
VERSION INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id)
);

# 添加数据
INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人笔记本', 100);

# 编写实体类
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    private Integer version;
}

# mapper层
public interface ProductMapper extends BaseMapper<Product> {
}

# 测试,最终查询结果预期是120,实际是70
@Test
public void testConcurrentUpdate() {
    //1、小李
    Product p1 = productMapper.selectById(1L);
    System.out.println("小李取出的价格:" + p1.getPrice());
    //2、小王
    Product p2 = productMapper.selectById(1L);
    System.out.println("小王取出的价格:" + p2.getPrice());
    //3、小李将价格加了50元,存入了数据库
    p1.setPrice(p1.getPrice() + 50);
    int result1 = productMapper.updateById(p1);
    System.out.println("小李修改结果:" + result1);
    //4、小王将商品减了30元,存入了数据库
    p2.setPrice(p2.getPrice() - 30);
    int result2 = productMapper.updateById(p2);
    System.out.println("小王修改结果:" + result2);
    //最后的结果
    Product p3 = productMapper.selectById(1L);
    //价格覆盖,最后的结果:70
    System.out.println("最后的结果:" + p3.getPrice());
}
  • 乐观锁实现流程
数据库中添加version字段
取出记录时,获取当前version
SELECT id,`name`,price,`version` FROM product WHERE id=1
更新时,version + 1,如果where语句中的version版本不对,则更新失败
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1
  • 配置乐观锁插件
@Configuration
//扫描mapper接口所在的包
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //添加分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        //添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}
  • 实体类添加乐观锁注解
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version //标识乐观锁版本号字段,数据库中version为0
    private Integer version;
}
  • 测试,第1次修改成功,由于乐观锁,第2次版本不正确,修改失败;所以最终查询结果是150
@Test
public void testProduct01(){
    //小李查询商品价格
    Product productLi = productMapper.selectById(1);
    System.out.println("小李查询的商品价格:"+productLi.getPrice());
    //小王查询商品价格
    Product productWang = productMapper.selectById(1);
    System.out.println("小王查询的商品价格:"+productWang.getPrice());
    //小李将商品价格+50
    productLi.setPrice(productLi.getPrice()+50);
    productMapper.updateById(productLi);
    //小王将商品价格-30
    productWang.setPrice(productWang.getPrice()-30);
    int result = productMapper.updateById(productWang);
    //老板查询商品价格
    Product productLaoban = productMapper.selectById(1);
    System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
}
  • 优化,第2次修改失败后,重试,最终查询为预期结果120
    @Test
    public void testProduct01(){
        //小李查询商品价格
        Product productLi = productMapper.selectById(1);
        System.out.println("小李查询的商品价格:"+productLi.getPrice());
        //小王查询商品价格
        Product productWang = productMapper.selectById(1);
        System.out.println("小王查询的商品价格:"+productWang.getPrice());
        //小李将商品价格+50
        productLi.setPrice(productLi.getPrice()+50);
        productMapper.updateById(productLi);
        //小王将商品价格-30
        productWang.setPrice(productWang.getPrice()-30);
        int result = productMapper.updateById(productWang);
        if(result == 0){
            //操作失败,重试
            Product productNew = productMapper.selectById(1);
            productNew.setPrice(productNew.getPrice()-30);
            productMapper.updateById(productNew);
        }
        //老板查询商品价格
        Product productLaoban = productMapper.selectById(1);
        System.out.println("老板查询的商品价格:"+productLaoban.getPrice());
    }
posted @ 2022-07-08 13:23  DogLeftover  阅读(15)  评论(0编辑  收藏  举报