mybatis-plus之逻辑删除&自动填充&乐观锁

1.背景

mybatis-plus除了常规的一些CRUD还有其他的的功能如下

2.逻辑删除

2.1.实现配置

步骤一、数据库准备一个逻辑删除字段,一般是deleted

步骤二、配置文件中添加入下配置

mybatis-plus之逻辑删除&自动填充&乐观锁

 步骤三、java实体上加标签如下:

mybatis-plus之逻辑删除&自动填充&乐观锁

2.2.实际案例演示

mybatis-plus之逻辑删除&自动填充&乐观锁
package com.ldp.demo01;

import com.ldp.entity.SysUser;
import com.ldp.mapper.SysUserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 12/14 7:13
 * @description <p>
 * 逻辑删除测试
 * </p>
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test11LogicDeleted {
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 逻辑删除测试
     * <p>
     * ==>  Preparing: UPDATE sys_user SET deleted=1 WHERE id=? AND deleted=0
     * ==> Parameters: 26(Integer)
     * <==    Updates: 1
     * <p>
     * 注意观察:虽然我执行的是删除,但是因为配置了逻辑删除,使用最后执行的本质sql是更新,
     * 而且在更新的sql语句中还加入了deleted=0这个条件
     * 那么试想一想,如果是查询、修改会加入deleted=0这个条件么?
     */
    @Test
    public void test01() {
        int row = sysUserMapper.deleteById(25);
        System.out.println("受影响行数:" + row);
    }

    /**
     * 测试逻辑删除下的查询
     * <p>
     * ==>  Preparing: SELECT id,version,age,gender,name,parent_id,position,account,we_chat,password,status,type,create_time,update_time,deleted
     * FROM sys_user WHERE id=? AND deleted=0
     * ==> Parameters: 25(Integer)
     * <p>
     * 注意逻辑删除下的查询是加了  AND deleted=0 作为查条件的
     */
    @Test
    public void test02() {
        SysUser sysUser = sysUserMapper.selectById(25);
        System.out.println("sysUser=" + sysUser);
    }

    /**
     * 逻辑删除下的更新
     * <p>
     * ==>  Preparing: UPDATE sys_user SET name=? WHERE id=? AND deleted=0
     * ==> Parameters: 逻辑删除测试(String), 25(Integer)
     * <p>
     * 注意从sql语句上看也是添加了deleted=0的
     */
    @Test
    public void test03() {
        int row = sysUserMapper.updateById(new SysUser().setId(25).setName("逻辑删除测试"));
        System.out.println("受影响行数=" + row);
    }

    /**
     * 逻辑删除下的新增
     * ==>  Preparing: INSERT INTO sys_user ( age, name ) VALUES ( ?, ? )
     * ==> Parameters: 18(Integer), 新增测试(String)
     * <==    Updates: 1
     * 注意从sql语句来看,在添加的时候并没有帮我们自动添加deleted=0字段的值,
     * 所有在实际生产中最佳的作法是在数据库设置默认值为0
     */
    @Test
    public void test04() {
        int row = sysUserMapper.insert(new SysUser().setName("新增测试").setAge(18));
        System.out.println("受影响行数=" + row);
    }
}
View Code

3.自动填充

第一步:注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置!

  /**
     * 表示创建时自动填充
     */
    @TableField(value = "create_time",fill = FieldFill.INSERT)
    private Date createTime;
    /**
     * 表示更新时自动填充
     */
    @TableField(fill = FieldFill.UPDATE)
    private Date updateTime;

第二步:自定义实现类 MyMetaObjectHandler

mybatis-plus之逻辑删除&自动填充&乐观锁
package com.ldp.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 12/14 8:03
 * @description
 */
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", () -> new Date(), Date.class); // 起始版本 3.3.3(推荐)
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", () -> new Date(), Date.class); // 起始版本 3.3.3(推荐)
    }
}
View Code

第三步:测试

mybatis-plus之逻辑删除&自动填充&乐观锁
package com.ldp.demo01;

import com.ldp.entity.SysUser;
import com.ldp.mapper.SysUserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 12/14 8:10
 * @description <p>
 * 自动填充
 * </p>
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test12FieldFill {
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 新增时自动填充
     * <p>
     * ==>  Preparing: INSERT INTO sys_user ( age, name, create_time ) VALUES ( ?, ?, ? )
     * ==> Parameters: 18(Integer), 自动填充(String), 2020-12-14 19:55:36.065(Timestamp)
     * <==    Updates: 1
     */
    @Test
    public void test01() {
        int row = sysUserMapper.insert(new SysUser().setName("自动填充").setAge(18));
        System.out.println("受影响行数=" + row);
    }


    /**
     * 更新时自动填充
     * <p>
     * ==>  Preparing: UPDATE sys_user SET name=?, update_time=? WHERE id=? AND deleted=0
     * ==> Parameters: 更新自动填充(String), 2020-12-14 19:56:16.539(Timestamp), 25(Integer)
     * <==    Updates: 1
     */
    @Test
    public void test02() {
        int row = sysUserMapper.updateById(new SysUser().setId(25).setName("更新自动填充"));
        System.out.println("受影响行数=" + row);
    }
}
View Code

4.乐观锁

实现原理:

取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败

 

具体实现

第一步:数据库和java实体添加字段version,并在实体上添加注解@Version

    /**
     * 乐观锁
     */
    @Version
    private Integer version;

第二步:注册乐观锁插件

mybatis-plus之逻辑删除&自动填充&乐观锁
package com.ldp.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 12/06 4:45
 * @description
 */
@Configuration
public class MybatisPlusConfig {
    /**
     * 乐观锁配置
     *
     * @return
     */
    @Bean
    public MybatisPlusInterceptor optimisticLockerInnerInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }
}
View Code

第三步:测试

mybatis-plus之逻辑删除&自动填充&乐观锁
package com.ldp.demo01;

import com.ldp.entity.SysUser;
import com.ldp.mapper.SysUserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

/**
 * @author 姿势帝-博客园
 * @address https://www.cnblogs.com/newAndHui/
 * @WeChat 851298348
 * @create 12/14 9:40
 * @description
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test13Version {
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 乐观锁测试
     * ==>  Preparing: UPDATE sys_user SET version=?, name=?, update_time=? WHERE id=? AND version=? AND deleted=0
     * ==> Parameters: 8(Integer), 乐观锁测试(String), 2020-12-14 22:04:15.04(Timestamp), 12(Integer), 7(Integer)
     * <==    Updates: 1
     * 注意观察sql,查询出来的version=7,在更新的时候将session版本设置为8
     */
    @Test
    public void test01() {
        SysUser sysUser = sysUserMapper.selectById(12);

        int row = sysUserMapper.updateById(
                new SysUser()
                        .setId(sysUser.getId())
                        .setName("乐观锁测试")
                        .setVersion(sysUser.getVersion())
        );
        System.out.println("受影响行数=" + row);
    }
}
View Code

完美!

上一篇:小书MybatisPlus第8篇-逻辑删除实现及API细节精讲


下一篇:TP5多条件搜索,同时有必要条件