🎉🎉《Spring Boot实战案例合集》目前已更新191个案例,我们将持续不断的更新。文末有电子书目录。
💪💪永久更新承诺
我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务。
💌💌如何获取
订阅我们的合集《点我订阅》,并通过私信联系我们,我们将第一时间将电子书发送给您。
环境:SpringBoot3.4.2
1. 简介
在软件开发中,为了更好地管理数据、追踪数据变更情况以及明确数据操作责任,许多数据表都会设置一些公共字段,例如记录数据创建者的“创建人”字段、标记数据创建时刻的“创建时间”字段,以及记录数据最后修改者和修改时间的“更新人”“更新时间”字段等。如下表结构,其中4个字段用来记录数据创建时间,修改时间,创建人,修改人:
这些公共字段对于数据管理、审计追踪等至关重要,但在常规开发模式下,每当进行数据的新增、修改等操作时,开发人员都需要在代码中手动为这些公共字段赋值。随着项目规模的不断扩大,业务逻辑日益复杂,涉及的数据操作场景也越来越多,这种手动设置公共字段的方式不仅效率低下,增加了开发人员的工作量,还极易因为人为疏忽而导致字段值设置错误或遗漏,进而影响数据的准确性和完整性。
本篇文章,我们将介绍4种实用的方案实现公共字段的填充。如下是第四种实现方案:
pack:fill:tables:'[t_product]':INSERT:- field: create_timename: timeValueFill- field: created_byname: userValueFillUPDATE:- field: update_timename: timeValueFill- field: updated_byname: userValueFill
我们只需要配置哪些表中的哪些字段需要进行填充,以及具体使用哪个Bean提供的值进行填充。针对每一个字段,我们都可以进行自定义填充对象(声明为bean)。
2.1 基于JPA实现
JPA的实现比较简单,我们只需要使用一些注解即可:
第一步:使用 @EntityListeners 注解
// 定义实体对象基类public abstract class BaseEntity {private LocalDateTime createTime;private LocalDateTime updateTime;private String createdBy;private String updatedBy;}public class Product extends BaseEntity {// ...其它属性}
public class PackAuditorAware implements AuditorAware<String> {public Optional<String> getCurrentAuditor() {return Optional.of("pack") ;}}
该对象是用来提供当前的操作人信息。会自动应用到@CreatedBy 和 @LastModifiedBy 注解对应的字段所需要的值。
当我们对Product实体进行新增和修改的时候会自动的更新相应的字段。
到此,基于JPA的实现就完成了,是不是非常的简单?
2.2 基于MyBatis实现
在MyBatis中,我们可以通过自定义拦截器Interceptor来实现字段的填充,如下自定义拦截器:
({(type = Executor.class,method = "update",args = { MappedStatement.class, Object.class })})public class AutoFillInterceptor implements Interceptor {public Object intercept(Invocation invocation) throws Throwable {MappedStatement ms = (MappedStatement) invocation.getArgs()[0];Object parameter = invocation.getArgs()[1];// 获取 SQL 命令类型SqlCommandType sqlCommandType = ms.getSqlCommandType();if (parameter instanceof BaseEntity entity) {fillField(sqlCommandType, entity);} else if (parameter instanceof Map param) {Collection<Object> values = param.values() ;values.forEach(value -> {if (value instanceof BaseEntity entity) {fillField(sqlCommandType, entity);}}) ;}return invocation.proceed();}private void fillField(SqlCommandType sqlCommandType, BaseEntity entity) {LocalDateTime now = LocalDateTime.now() ;String currentUser = getCurrentUser() ;if (SqlCommandType.INSERT == sqlCommandType) {entity.setCreateTime(now);entity.setCreatedBy(currentUser);}if (SqlCommandType.INSERT == sqlCommandType || SqlCommandType.UPDATE == sqlCommandType) {entity.setUpdateTime(now);entity.setUpdatedBy(currentUser);}}private String getCurrentUser() {return "m-pack";}public Object plugin(Object target) {return Plugin.wrap(target, this);}public void setProperties(Properties properties) {}}
只需要定义如上的拦截器并注册为bean,即可实现公共字段的填充。


