SpringBoot结合MyBatisPlus的公共字段自动填充

问题描述

MyBatisPlus公共自动填充,也就是在插入或更新的时候为指定字段赋予指定的值,常见的例子就是更新时间一般都是现在的时间,就可以将这个字段进行统一处理,使用它的好处就是可以统一对这些字段进行处理,避免了重复代码


解决方案:

实现步骤:

1、在实体类的属性加入@TableField注解,指定自动生成的策略

下面以员工实体类为例,模仿如何使用即可

/**
 * 员工实体类
 */
@Data
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    private String username;

    private String name;

    private String password;

    private String phone;

    private String sex;

    private String idNumber;//身份证号码

    private Integer status;
    
    @TableField(fill = FieldFill.INSERT)//插入时自动填充字段
    private LocalDateTime createTime;
    
    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private LocalDateTime updateTime;
    
    @TableField(fill = FieldFill.INSERT)//插入时自动填充字段
    private Long createUser;

    @TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新时填充字段
    private Long updateUser;

}

2、按照MyBatisPlus框架要求编写元数据对象处理器,在此类中统一为公共字段赋值,此类需要实现MetaObjectHandle接口。

创建该类一般放在common包下,就是公共包下

代码如下:

/**
 * 自定义元数据处理器
 * @author mrs
 * @create 2022-06-01 16:13
 */
@Component//使用Spring框架管理
@Slf4j//日志
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 该方法指向插入语句时执行
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert...]");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());//创建时间统一赋值
        metaObject.setValue("updateTime", LocalDateTime.now());//更新时间统一赋值
        metaObject.setValue("createUser",new Long(1));//创建人暂时写死
        metaObject.setValue("updateUser" ,new Long(1));//更新人暂时写死

    }
    /**
     * 该方法指向更新语句时执行
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update...]");
        log.info(metaObject.toString());
        metaObject.setValue("updateTime", LocalDateTime.now());//更新时间统一赋值
        metaObject.setValue("updateUser" ,new Long(1));//更新人暂时写死
    }
}

完善上面的写死的代码

有时在元数据对象处理器中需要得到对应的用户session的id,所以扩展知识:就是客户端发送的每次http请求,对应的在服务器都会分配一个新的线程来处理,在处理过程中涉及的公共字段和创建修改的方法都是属于相同的线程

这个时候就需要ThreadLocal

什么是ThreadLocal?

ThreadLocal并不是一个Thread,而是Thread的局部变量。使用ThreadLocal维护变量时,ThreadLocal为每一个使用该变量的线程提供独立的变量副本,所以每一个线程可以独立的改变自己的副本,而不会影响它线程所对应的副本。

ThreadLocal为每个线程提供单独存储空间,具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问。

ThreadLocal常用方法

public void set(T value)     设置当前线程的线程局部变量

public T get()                     设置当前线程所对应的线程局部变量的值

所以这里完善代码获取对应的session中的id就使用这个类的线程特性来解决,就是在过滤器中的doFilter方法中(Springboot添加过滤器的设置请看我的CSDN上的记录文章)获取当前登录的用户id,并调用ThreadLocal的set设置当前线程的线程局部变量的值(用户id),然后在上面的元数据处理器中的updateFil方法中调用ThreadLocal的get方法来获取当前线程suo对应的线程局部变量的值(用户id)

完善用户id存储到公共字段填充的问题

实现步骤

1、编写BaseContext工具类存在common(公共)包下,基于ThreadLocal封装的工具类

/**
 * 基于ThreadLocal封装的工具类,用户保存和获取当前登录用户的id
 * @author mrs
 * @create 2022-06-01 17:03
 */
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();//这里我的id是long,使用的雪花算法生成的
    public void setCurrentId(Long id){
        threadLocal.set(id);
    }
    public static Long getCurrentId(){
        return threadLocal.get();
    }
}

2、在登录的过滤器的doFilter方法中调用BaseContext来设置当前登录用户的id

//将session的id存入ThreadLocal里面
Long empId = (Long)request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);

3、在MyMetaObjectHandler的方法中调用BaseContext获取登录用户的id

上面MyMetaObjectHandler类更新如下:

/**
 * 自定义元数据处理器
 * @author mrs
 * @create 2022-06-01 16:13
 */
@Component//使用Spring框架管理
@Slf4j//日志
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 该方法指向插入语句时执行
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert...]");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());//创建时间统一赋值
        metaObject.setValue("updateTime", LocalDateTime.now());//更新时间统一赋值
        metaObject.setValue("createUser",BaseContext.getCurrentId());//创建人更新人使用ThreadLocal进行传输用户id
        metaObject.setValue("updateUser" ,BaseContext.getCurrentId());//更新人更新人使用ThreadLocal进行传输用户id

    }
    /**
     * 该方法指向更新语句时执行
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update...]");
        log.info(metaObject.toString());
        metaObject.setValue("updateTime", LocalDateTime.now());//更新时间统一赋值
        metaObject.setValue("updateUser" ,BaseContext.getCurrentId());//更新人使用ThreadLocal进行传输用户id
    }
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要配置MyBatis Plus的拦截器以实现字段自动填充,你可以按照以下步骤进行操作: 1. 创建一个类实现`MetaObjectHandler`接口,该接口包含了字段自动填充的方法。在这个类中,你可以实现`insertFill`和`updateFill`方法,在插入和更新操作时自动填充指定字段。 ```java @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.strictInsertFill(metaObject, "createUser", String.class, "defaultUser"); this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); } @Override public void updateFill(MetaObject metaObject) { this.strictUpdateFill(metaObject, "updateUser", String.class, "defaultUser"); this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); } } ``` 在这个示例中,我们在插入和更新操作时分别填充了`createUser`、`createTime`、`updateUser`和`updateTime`字段。 2. 在你的配置类中添加对拦截器的配置。例如: ```java @Configuration public class MyBatisPlusConfig { @Autowired private MyMetaObjectHandler myMetaObjectHandler; @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new MybatisPlusInnerInterceptor()); // 添加自动填充拦截器 interceptor.addInnerInterceptor(new IAutoFillInnerInterceptor(myMetaObjectHandler)); return interceptor; } } ``` 在这个示例中,我们创建了一个`MybatisPlusInterceptor`对象,并通过`addInnerInterceptor`方法添加了自定义的内部拦截器`IAutoFillInnerInterceptor`,并将`MyMetaObjectHandler`作为参数传递给拦截器。 3. 创建一个自定义的内部拦截器`IAutoFillInnerInterceptor`,继承自`AbstractSqlParserHandler`,并实现其中的方法。 ```java public class IAutoFillInnerInterceptor extends AbstractSqlParserHandler { private final MetaObjectHandler metaObjectHandler; public IAutoFillInnerInterceptor(MetaObjectHandler metaObjectHandler) { this.metaObjectHandler = metaObjectHandler; } @Override public SqlNode handler(MetaObject metaObject, SqlNode sqlNode) { // 在这里执行字段自动填充逻辑 metaObjectHandler.insertFill(metaObject); metaObjectHandler.updateFill(metaObject); return super.handler(metaObject, sqlNode); } } ``` 在这个示例中,我们在`handler`方法中调用了`MetaObjectHandler`的插入和更新填充方法。 通过以上步骤,你就可以成功配置MyBatis Plus的拦截器,并实现字段自动填充了。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值