Mybatis 基础字段自动维护

670 字
3 分钟
Mybatis 基础字段自动维护

当前系统中,表的 创建日期更新日期,整理了有以下取名

创建日期更新日期
create_tslast_mnt_ts
created_timeupdated_time
create_timeupdate_ts
update_time
modified_ts

在使用 Mybatis Plus 时,其自带的 自动填充功能,遇到这种基础字段命名不统一的场景时,不够灵活,所以有了以下的自定义插件,通过 在不同的基础数据库实体映射类中,标记对应的 创建日期、更新日期等字段,满足基础字段自动填充功能。

自定义注解说明#

注解用途
@Created填充记录创建时间
@Modified填充记录最后更新时间
@CreatedBy填充记录创建人
@ModifiedBy填充记录更新人

使用例子#

@Data
public abstract class AbstractEntity implements Serializable {
@Serial
private static final long serialVersionUID = -6362917626913479219L;
/**
* 创建人
*/
@CreatedBy
protected Long createdBy;
/**
* 创建时间
*/
@Created
protected LocalDateTime createdTime;
/**
* 创建日期
*/
@ModifiedBy
protected Long updatedBy;
/**
* 更新时间
*/
@Modified
protected LocalDateTime updatedTime;
}

底层实现#

通过自定义 mybatis 的插件,拦截 Executor 的 update 方法,找到对应的实体类对象,进行值插入

@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class AutoFillInterceptor implements Interceptor {
private ConcurrentHashMap<Class, AuditingConfig> auditingConfigMap = new ConcurrentHashMap<>();
private CurrentUserExtractor currentUserExtractor;
public void setCurrentUserExtractor(CurrentUserExtractor currentUserExtractor) {
this.currentUserExtractor = currentUserExtractor;
}
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
if (args.length > 1) {
Object arg = args[1];
Class<?> clazz = arg.getClass();
AuditingConfig config = auditingConfigMap.computeIfAbsent(clazz, this::extractConfig);
Field createField = config.getCreateField();
Field modifiedField = config.getModifiedField();
BeanWrapper beanWrapper = null;
MappedStatement mappedStatement = (MappedStatement)args[0];
SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
if (createField != null || modifiedField != null) {
beanWrapper = new BeanWrapperImpl(arg);
Date now = new Date();
if (sqlCommandType == SqlCommandType.INSERT) {
if (createField != null) {
setAuditingDateValue(beanWrapper, createField, now);
}
if (modifiedField != null) {
setAuditingDateValue(beanWrapper, modifiedField, now);
}
// if (config.getVersionFiled() != null) {
// setDefaultVersion(beanWrapper, config.getVersionFiled());
// }
} else if (sqlCommandType == SqlCommandType.UPDATE) {
setAuditingDateValue(beanWrapper, modifiedField, now);
}
}
if (currentUserExtractor != null) {
Field createdByField = config.getCreatedByField();
Field modifiedByField = config.getModifiedByField();
if (createdByField != null && modifiedByField != null) {
Object user = currentUserExtractor.getCurrentUser();
if (beanWrapper == null) {
beanWrapper = new BeanWrapperImpl(arg);
}
if (sqlCommandType == SqlCommandType.INSERT) {
if (createField != null) {
setAuditingUserValue(beanWrapper, createdByField, user);
}
if (modifiedField != null) {
setAuditingUserValue(beanWrapper, modifiedByField, user);
}
} else if (sqlCommandType == SqlCommandType.UPDATE) {
setAuditingUserValue(beanWrapper, modifiedByField, user);
}
}
}
}
return invocation.proceed();
}
private void setAuditingDateValue(BeanWrapper beanWrapper, Field field, Date value) {
String name = field.getName();
if (field.getType() == Date.class) {
beanWrapper.setPropertyValue(name, value);
}
}
private void setAuditingUserValue(BeanWrapper beanWrapper, Field field, Object user) {
String name = field.getName();
if (beanWrapper.getPropertyValue(name) == null) {
beanWrapper.setPropertyValue(name, user);
}
}
private AuditingConfig extractConfig(Class<?> clazz) {
AuditingConfig config = new AuditingConfig();
ReflectionUtils.doWithFields(clazz, new ReflectionUtils.FieldCallback() {
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
Created created = field.getAnnotation(Created.class);
if (created != null) {
config.setCreateField(field);
} else {
Modified modified = field.getAnnotation(Modified.class);
if (modified != null) {
config.setModifiedField(field);
}
}
CreatedBy createdBy = field.getAnnotation(CreatedBy.class);
if (createdBy != null) {
config.setCreatedByField(field);
} else {
ModifiedBy modifiedBy = field.getAnnotation(ModifiedBy.class);
if (modifiedBy != null) {
config.setModifiedByField(field);
}
}
// Version version = field.getAnnotation(Version.class);
// if (version != null) {
// config.setVersionFiled(field);
// }
}
});
return config;
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
@Data
private static class AuditingConfig {
private Field createField;
private Field modifiedField;
private Field createdByField;
private Field modifiedByField;
private Field versionFiled;
}
}

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Mybatis 基础字段自动维护
https://blog.sephy.top/posts/mybatis-基础字段自动维护/
作者
虾米
发布于
2019-07-02
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
虾米
coder
分类
标签
站点统计
文章
61
分类
4
标签
52
总字数
64,663
运行时长
0
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.13.9
文章许可
CC BY-NC-SA 4.0