MyBatis -Plus进阶必学-逻辑删除、自动填充。乐观锁、性能分析

MyBatis -Plus进阶必学


测试实体:

#创建用户表
CREATE TABLE tb_user (
  id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',
  name VARCHAR(30) DEFAULT NULL COMMENT '姓名',
  age INT(11) DEFAULT NULL COMMENT '年龄',
  email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',
  manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',
  create_time DATETIME DEFAULT NULL COMMENT '创建时间',
   update_time DATETIME DEFAULT NULL COMMENT '修改时间',
   version INT(11) DEFAULT '1' COMMENT '版本',
   deleted INT(1) DEFAULT '0' COMMENT '逻辑删除标识(0.未删除,1.已删除)',
  CONSTRAINT manager_fk FOREIGN KEY (manager_id)
    REFERENCES tb_user (id)
) ENGINE=INNODB CHARSET=UTF8;

INSERT INTO tb_user (id, name, age, email, manager_id
   , create_time)
VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL
     , '2019-01-11 14:20:20'),
   (1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553
     , '2019-02-05 11:12:22'),
   (1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385
     , '2019-02-14 08:31:16'),
   (1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385
     , '2019-01-14 09:15:15'),
   (1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385
     , '2019-01-14 09:48:16');


mybatis-plus 逻辑删除:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yPDadc6h-1662625881344)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906104747236.png)]

1、配置文件添加逻辑删除标识;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kBVbBwzs-1662625881345)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906090627626.png)]

application.yml配置:
mybatis-plus:  
 global-config:      
  db-config:         
   logic-not-delete-value: 0         l
   logic-delete-value: 1

2、3.1版本之前需要配置类;

配置类configuration:3.1.1以下版本

img

3、实体添加注解tablelogic。

在实体类加注解,设置全局@TableLogic/@TableLogic()局部
@TableLogic
    private Integer deleted;

img

测试类:

@Springtest

public calss MyTest{

      

       @Autowired

       private UserMapper userMapper;

      

       @Test

       public void deletedById(){

             int rows = userMapper.deleteById(1092344455666L);

             System.out.println("影响行数:  "+rows);

       }

}

结果是update语句,而不是删除语句。在继续进行update、select方法的的时候,会忽略被标记为“已删除”的记录。

4. 查询中排除删除标识字段及注意事项

  1. 通过在TableField加入select=false排除
  2. 对于自定义的需要在sql中加入where deletd=0或者在条件中排除
package com.autel.mpsdemo.mapper;

import com.autel.mpsdemo.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @Author: X22020
 * @Date: 2022/09/06/9:52
 * @Description:
 */
public interface UserMapper extends BaseMapper<User> {

    @Select("Select *  from tb_user ${ew.customSqlSegment}")
    List<User> mySelectList(@Param(Constants.WRAPPER) Wrapper<User> wrapper);

}
    @Test
    public void selectS(){
        List<User> list = userMapper.mySelectList(Wrappers.<User>lambdaQuery()
                .gt(User::getAge,25)
                .eq(User::getDeleted,0)
        );
        list.forEach(System.out::println);
    }

mybatis-plus 自动填充:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3dORAYYj-1662625881346)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906141437806.png)]

1.-配置实体的自动填充注解值

img

2.实现MetaObjectHandler

其中的metaObject是为传入的对象,可通过判断对象是否有对应的属性,是否有值等方法来进行个性化填充

img

package com.autel.mpsdemo.component;

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

import java.time.LocalDateTime;

/**
 * @Author: X22020
 * @Date: 2022/09/06/11:35
 * @Description:
 */
@Component
public class  MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        boolean hasSetter = metaObject.hasSetter("createTime");
        if (hasSetter) {
            // 起始版本 3.3.0(推荐使用)
            this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
            // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
//      this.setFieldValByName("createTime", LocalDateTime.now(),metaObject);
//      this.fillStrategy(metaObject, "createTime", LocalDateTime.now());
//      上面选其一使用,下面的已过时(注意 strictInsertFill 有多个方法,详细查看源码)
//       this.setInsertFieldValByName("operator", "Jerry", metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        Object val = getFieldValByName("updateTime", metaObject);
        if (val == null) {
    
            // 起始版本 3.3.0(推荐使用)
            this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
            // 也可以使用(3.3.0 该方法有bug请升级到之后的版本如`3.3.1.8-SNAPSHOT`)
//        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now());
//        /* 上面选其一使用,下面的已过时(注意 strictUpdateFill 有多个方法,详细查看源码) */
//        this.setFieldValByName("operator", "Tom", metaObject);
//        this.setUpdateFieldValByName("operator", "Tom", metaObject);
        }
    }
}

mybatis-plus 乐观锁:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q47QPxIq-1662625881347)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906143035370.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4gI0ekiL-1662625881347)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906143406122.png)]

1.乐观锁实现,实体类增加@Version

img

2.乐观锁实现,创建配置类

img

    @Test
    public  void update(){
        //数据库查出来
        int version = 1;
        User user = new User();
        user.setId(1567030448007110657L);
        user.setEmail("kobe@lakers.com");
        user.setVersion(version);
        int insert = userMapper.updateById(user);
        System.out.println("影响行数" + insert);

    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BxFIYXwg-1662625881348)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906150141929.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzPwMxv3-1662625881348)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906144331497.png)]

mybatis-plus 性能分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQIVSB04-1662625881349)(C:\Users\x22020\AppData\Roaming\Typora\typora-user-images\image-20220906151740440.png)]

1.性能分析,增加配置.

格式化true

img

2.IDEA中配置性能分析插件

在IDEA中配置性能分析插件只需要配置开发环境就可以了:
新建application-dev.yml,之后把application.yml中的代码剪切放到application-dev.yml里面,现在你application.yml是空的了,我们来配置当前环境为开发环境,只需要在application.yml中配置以下代码即可:

spring:
profiles:
active: dev

3.执行SQL分析打印

引入p6spy,第三方打印sql

 <dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
     <version>3.8.2</version>
 </dependency>

p6sy配置:

img

spy.properties配置:

#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

img

mybatis_plus 多租户SQL解析器

  多租户是一种架构,目的是在多用户条件下,实现用户使用同一套程序且保证用户间数据隔离。
  一种方式是不同用户使用独立的数据库,
  第二种是设置不同的角色,
  第三种是每插入一条数据都有该用户的标识
  
  多租户是为了让一套程序面向多个用户(企业)且数据隔离

用户数据库一对一

用户Schema一对一,逻辑隔离,都在一个数据库

用户都在一个表里,通过clientId之类的隔离,维护成本低,安全低,恢复成本大

属性介绍

属性名类型默认值描述
tenantLineHandlerTenantLineHandler租户处理器( TenantId 行级 )
public interface TenantLineHandler {

    /**
     * 获取租户 ID 值表达式,只支持单个 ID 值
     * <p>
     *
     * @return 租户 ID 值表达式
     */
    Expression getTenantId();

    /**
     * 获取租户字段名
     * <p>
     * 默认字段名叫: tenant_id
     *
     * @return 租户字段名
     */
    default String getTenantIdColumn() {
        return "tenant_id";
    }

    /**
     * 根据表名判断是否忽略拼接多租户条件
     * <p>
     * 默认都要进行解析并拼接多租户条件
     *
     * @param tableName 表名
     * @return 是否忽略, true:表示忽略,false:需要解析并拼接多租户条件
     */
    default boolean ignoreTable(String tableName) {
        return false;
    }
}

说明:

多租户 != 权限过滤,不要乱用,租户之间是完全隔离的!!!
启用多租户后所有执行的method的sql都会进行处理.
自写的sql请按规范书写(sql涉及到多个表的每个表都要给别名,特别是 inner join 的要写标准的 inner join)

版权声明:本文为weixin_51439775原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。