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


    1.背景

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

    2.逻辑删除

    2.1.实现配置

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

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

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

    2.2.实际案例演示

    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

    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

    第三步:测试

    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;

    第二步:注册乐观锁插件

    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

    第三步:测试

    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

    mybatis-plus系统化学习教程:https://www.cnblogs.com/newAndHui/p/14141950.html

    完美!

  • 相关阅读:
    lucene复合条件查询案例——查询name域 或 description域 包含lucene关键字的两种方式
    谈谈你对spring的理解?
    模拟Http请求的几种常用方式
    idea破解教程
    Pycharm 或者 idea 注册码 (亲测可用)
    超详细虚拟机工具和Centos7 Linux系统安装
    严重: Error loading WebappClassLoader context:异常的解决方法(转)
    spring cloud 笔记记录
    近一周学习之-----vue学习快乐之旅(1)
    近一周学习之-----vue开发工具visual studio code
  • 原文地址:https://www.cnblogs.com/newAndHui/p/14131368.html
Copyright © 2020-2023  润新知