SpringBoot基于MyBatisPlus实现公共字段自动填充

问题背景

在增加或修改记录时,常常需要对一些公共字段进行设置,如创建时间(createTime)、创建人(createUser)、修改时间(updateTime)、修改人(updateUser),这些信息一般不来自于网页请求。实际项目中可能有很多种Entity(实体类),对每一个Entity对应的业务代码中都要写这些针对公共字段的操作,造成了代码的大量重复。

因此,可以创建一个用于公共字段自动填充的类,使得公共字段实现自动填充。

实现方式

主要分为两大部分:

1. MetaObjectHandler实现类创建

2. 实体类中公共字段添加注解



1. MetaObjectHandler实现类创建

首先,建立一个MetaObjectHandler接口的实现类(MetaObjectHandler是MyBatisPlus提供的接口)

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

之后,重写相关方法 (insertFill(MetaObject metaObject) 和 updateFill(MetaObject metaObject) )

@Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]...");
        log.info("线程id:{}", Thread.currentThread().getId());

        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", threadLocal.get());  // 动态填充 填充当前登录的用户的 ID
        metaObject.setValue("updateUser", threadLocal.get());  // 动态填充 填充当前登录的用户的 ID
    }


    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info("线程id:{}", Thread.currentThread().getId());

        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", threadLocal.get());
    }

注意:在对createUser和updateUser进行设置时(通常是设置id),无法拿到session,因此不能通过session的方式获取id。这里使用的是ThreadLocal

需要知道的是,页面向服务器发送的每一个请求,在服务器端都会有一个独立的线程根据该请求进行一系列操作。例如,页面发来一个修改用户的请求,到了服务器端,拦截器的preHandle方法、controller层的update方法,以及公共字段填充类的updateFill方法都是由同一个线程执行的

在这里插入图片描述

因此,可以在拦截器执行preHandle方法时,将session中的id数据保存到ThreadLocal对象中,在进行公共字段填充时,再将id从ThreadLocal对象中取出即可。

我将ThreadLocal配置成了一个Bean来管理(也可以用一个工具类来封装ThreadLocal,定义一个类变量)

ThreadLocal的Bean配置:

@Configuration
public class ThreadLocalConfig {
    @Bean
    public ThreadLocal<Long> threadLocal(){
        ThreadLocal<Long> threadLocal = new ThreadLocal<>();
        return threadLocal;
    }
}

拦截器注入ThreadLocal,并将id存入ThreadLocal:

public class MyInterceptor implements HandlerInterceptor {

    @Autowired
    ThreadLocal<Long> threadLocal;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        log.info("线程id:{}", Thread.currentThread().getId());
        threadLocal.set((Long) request.getSession().getAttribute("employeeId"));
        ...
        对session进行判断的代码
        ...
    }
}

之后,在MetaObjectHandler实现类中也对ThreadLocal的Bean进行注入

2. 实体类中公共字段添加注解

    @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
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要配置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的拦截器,并实现字段自动填充了。希望对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值