MybatisPlus自动填充功能和乐观锁处理功能

前提: 数据库表一般都需要有 create_timeupdate_time字段,这两个字段的值可以通过数据库级别进行自动填充,但是通常在公司中不允许直接修改数据库。

通过MybatisPlus实现自动填充功能

数据库表
在这里插入图片描述

pojo类

@Data
public class AdminUser {
    //使用基本类型包装类

    /*  枚举类型的值含义
    AUTO(0),  //数据库id自增1
    NONE(1),  //未设置主键
    INPUT(2),  //手动输入
    ID_WORKER(3), //默认的全局唯一id
    UUID(4),  //全局唯一id uuid
    ID_WORKER_STR(5);  // ID_WORKER的字符串表示法
     */

    //mybatisPlus主键生成策略:雪花算法,自动生成的ID全球唯一,Long类型
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userName;
    private String password;
    private String nickName;
    private Byte locked;

    @TableField(fill = FieldFill.INSERT) //插入的时候
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE) //插入完更新的时候
    private Date updateTime;

}

元对象处理类

  • insertFill方法,插入时自动填充策略(插入数据时,更新时间和插入时间相同)
  • updateFill方法,更新时自动填充策略
//元对象处理类
@Component  //把处理器加到IOC容器中
@Slf4j
public class MyMetaObjectHandle implements MetaObjectHandler {
    //插入时填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("开始插入填充");
        this.setFieldValByName("createTime",new Date(),metaObject);

        this.setFieldValByName("updateTime",new Date(),metaObject);

    }

    //修改时填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

乐观锁处理功能

数据库表

  • 添加一个version字段,默认值是1

在这里插入图片描述
pojo

@Data
public class AdminUser {
  
    //mybatisPlus主键生成策略:雪花算法,自动生成的ID全球唯一,Long类型
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userName;
    private String password;
    private String nickName;
    private Byte locked;

    @TableField(fill = FieldFill.INSERT) //插入的时候填充
    private Date createTime;

    @TableField(fill = FieldFill.INSERT_UPDATE) //插入完更新的时候填充
    private Date updateTime;

    @Version   
    private Integer version;  //乐观锁字段

}

配置类

  • 注册乐观锁插件
@Configuration  //表明该类是一个配置类
@EnableTransactionManagement //自动管理事务注解
@MapperScan("com.rm.dao")   //扫描mapper接口
public class MyBatisPlusConfig {

    //注册乐观锁插件
    @Bean
     //注意mybatisPlus版本,3.4.0以上有这个类
    public MybatisPlusInterceptor MybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }

}

启动测试的时候碰到了缓存满了,报了CodeCache is full. Compiler has been disabled.
解决:将项目缓存改大一点
在这里插入图片描述

测试乐观锁

   //测试乐观锁成功,单线程
    @Test
    public void testOptimisticLocker(){
        //alt+shift+insert 进入多行操作模式

        //通过ID获取对象
        AdminUser user = adminUserMapper.selectById(1L);
        //修改对象
        user.setNickName("我是管理员");
        //更新操作
        adminUserMapper.updateById(user);
    }

查看日志

  • 执行更新的时候将version字段也带上了
==>  Preparing: 
UPDATE admin_user 
SET user_name=?, password=?, nick_name=?, locked=?, update_time=?, version=?
WHERE id=? AND version=?
==> Parameters: 
admin(String), e10adc3949ba59abbe56e057f20f883e(String),
 我是管理员(String), 0(Byte), 2021-06-02 15:59:43.816(Timestamp), 2(Integer), 
 1(Long), 1(Integer)

测试乐观锁失败情况

    @Test
    //测试乐观锁失败 模拟多线程
    public void testOptimisticLocker2(){

        //通过ID获取对象
        AdminUser user1 = adminUserMapper.selectById(1L);
        //修改对象
        user1.setNickName("我是管理员1");

        //user1设置值了但是还没有执行更新操作
        AdminUser user2 = adminUserMapper.selectById(1L);
        user2.setNickName("我是管理员2");
        //user2已经设置值并执行了更新操作
        adminUserMapper.updateById(user2);

        //user1再次执行更新操作就会失败,因为查不到user2更新前的version
        //如果没有乐观锁的情况下,执行更新操作会覆盖user2的值
        adminUserMapper.updateById(user1);
    }

查看日志

  • user2对象执行更新操作成功
==>  Preparing: 
UPDATE admin_user 
SET user_name=?, password=?, nick_name=?, locked=?, update_time=?, version=? 
WHERE id=? AND version=?
==> Parameters: 
admin(String), e10adc3949ba59abbe56e057f20f883e(String), 
我是管理员2(String), 0(Byte), 2021-06-02 16:10:28.29(Timestamp), 3(Integer),

 1(Long), 2(Integer)  //where条件
<==    Updates: 1
  • user1对象执行更新操作失败
  • 由于user2对象已经执行了更新操作,version变为了3,此时再查询version=2就查不到数据了
==>  Preparing: 
UPDATE admin_user 
SET user_name=?, password=?, nick_name=?, locked=?, update_time=?, version=? 
WHERE id=? AND version=?
==> Parameters: admin(String), e10adc3949ba59abbe56e057f20f883e(String),
 我是管理员1(String), 0(Byte), 2021-06-02 16:10:28.308(Timestamp), 3(Integer),
 
 1(Long), 2(Integer) 
<==    Updates: 0

mybatisPlus查询操作

通过多个id进行查询

//测试查询多个用户
 @Test
 public void testBatchSelect(){
     //查询id为1和2的用户
     List<AdminUser> list = adminUserMapper.selectBatchIds(Arrays.asList(1, 2));
     for (AdminUser adminUser : list) {
         System.out.println(adminUser);
     }
 }

根据条件进行查询

  • 使用map进行操作
   @Test  //测试根据条件查询
    public void testCondition(){
        HashMap<String, Object> map = new HashMap<>();
        map.put("user_name","admin");  //键是数据库字段
        List<AdminUser> list1 = adminUserMapper.selectByMap(map);
        for (AdminUser adminUser : list1) {
            System.out.println(adminUser);
        }
    }

日志

==>  Preparing: 
SELECT id,user_name,password,nick_name,locked,create_time,update_time,version 
FROM admin_user 
WHERE user_name = ?
==> Parameters:
 admin(String)
<==    Columns:
 id, user_name, password, nick_name, locked, create_time, update_time, version
<==        Row: 
1, admin, e10adc3949ba59abbe56e057f20f883e, 我是管理员2, 0, null, 
2021-06-02 16:10:28, 3

分页查询功能

注册分页插件

@Configuration  //表明该类是一个配置类
@EnableTransactionManagement //自动管理事务注解
@MapperScan("com.rm.dao")   //扫描mapper接口
public class MyBatisPlusConfig {

    //注册乐观锁插件
    @Bean
     //注意mybatisPlus版本,3.4.0以上有这个类
    public MybatisPlusInterceptor MybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }

    //注册分页插件
    // 最新版 3.4.0以上
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // DbType.MYSQL参数为空时会自动根据url查询对应的数据库
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }

}

测试分页功能

@Test //测试分页查询
 public void tsetPage(){
     //当前页是1,一页显示5条数据
     Page<AdminUser> page = new Page<>(2,3);

     adminUserMapper.selectPage(page, null);
     List<AdminUser> userList = page.getRecords();
     for (AdminUser adminUser : userList) {
         System.out.println(adminUser);
     }

 }

查看日志

  • 先查询出来数据总数
  • 每页显示3条,从第二页查,所以是查询第4,5,6条数据
==>  Preparing: SELECT COUNT(1) FROM admin_user
==> Parameters: 
<==    Columns: COUNT(1)
<==        Row: 7
==>  Preparing: 

SELECT id,user_name,password,nick_name,locked,create_time,update_time,version
 FROM admin_user 
 LIMIT ?,?
==> Parameters: 
3(Long), 3(Long)
<==    Columns: 
id, user_name, password, nick_name, locked, create_time, update_time, version
<==        Row: 
4, cxnph, 123456, 测试2号, 0, 2021-06-02 16:44:02, 2021-06-02 16:44:02, 1
<==        Row: 
5, cxnph, 123456, 测试2号, 0, 2021-06-02 16:44:11, 2021-06-02 16:44:11, 1
<==        Row: 
6, cxnph, 123456, 测试2号, 0, 2021-06-02 16:44:19, 2021-06-02 16:44:19, 1
<==      Total: 3
posted @ 2021-11-04 16:26  初夏那片海  阅读(273)  评论(0)    收藏  举报