项目中一些表的基础字段命名不规范且不方便全部一次性改,比如创建时间有两种命名:createdAt,createAt,对应类的属性也存在 Date 以及 LocalDateTime。看到同事利用 MyBatis-Plus 的 自动填充功能 以及 Java 8 中的 函数式接口 玩了一把花活儿来兼容不同命名的填充,正好有 1024 的发帖活动,特此记录。
前提
按照 MyBatis-Plus 的 自动填充功能 对类的相关属性进行了配置,不再赘述。
代码
/**
* ,MyBatis-Plus
*/
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
private static final String CREATED_AT_NAME = "createdAt";
private static final String CREATED_BY_NAME = "createdBy";
private static final String LAST_MODIFIED_AT_NAME = "lastModifiedAt";
private static final String LAST_MODIFIED_BY_NAME = "lastModifiedBy";
private static final String CREATE_AT_NAME = "createAt";
private static final String CREATE_BY_NAME = "createBy";
@Getter
private enum FillFieldEnum {
CREATED_AT(CREATED_AT_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
if (LocalDateTime.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATED_AT_NAME,LocalDateTime.now(),metaObject);
} else if (LocalDate.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATED_AT_NAME,LocalDate.now(),metaObject);
} else if (Date.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATED_AT_NAME,new Date(),metaObject);
}
}),
CREATED_BY(CREATED_BY_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
Long userId = getUserId();
if (userId != -1) {
if (Long.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATED_BY_NAME,userId,metaObject);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATED_BY_NAME,userId.intValue(),metaObject);
}
} else {
//如果当前没有登录人,使用 strictInsertFill,这个方法可以判断实体中是否已经存在,不存在则补充-1
if (Long.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,CREATED_BY_NAME,Long.class,userId);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,CREATED_BY_NAME,Integer.class,userId.intValue());
}
}
}),
CREATE_AT(CREATE_AT_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
if (LocalDateTime.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATE_AT_NAME,LocalDateTime.now(),metaObject);
} else if (LocalDate.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATE_AT_NAME,LocalDate.now(),metaObject);
} else if (Date.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATE_AT_NAME,new Date(),metaObject);
}
}),
CREATE_BY(CREATE_BY_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
Long userId = getUserId();
if (userId != -1) {
if (Long.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATE_BY_NAME,userId,metaObject);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(CREATE_BY_NAME,userId.intValue(),metaObject);
}
} else {
//如果当前没有登录人,使用 strictInsertFill,这个方法可以判断实体中是否已经存在,不存在则补充-1
if (Long.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,CREATE_BY_NAME,Long.class,userId);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,CREATE_BY_NAME,Integer.class,userId.intValue());
}
}
}),
LAST_MODIFIED_AT(LAST_MODIFIED_AT_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
if (LocalDateTime.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(LAST_MODIFIED_AT_NAME,LocalDateTime.now(),metaObject);
} else if (LocalDate.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(LAST_MODIFIED_AT_NAME,LocalDate.now(),metaObject);
} else if (Date.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(LAST_MODIFIED_AT_NAME,new Date(),metaObject);
}
}),
LAST_MODIFIED_BY(LAST_MODIFIED_BY_NAME, (clazz, metaObject, myMetaObjectHandler) -> {
Long userId = getUserId();
if (userId != -1) {
if (Long.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(LAST_MODIFIED_BY_NAME,userId,metaObject);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.setFieldValByName(LAST_MODIFIED_BY_NAME,userId.intValue(),metaObject);
}
} else {
//如果当前没有登录人,使用 strictInsertFill,这个方法可以判断实体中是否已经存在,不存在则补充-1
if (Long.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,LAST_MODIFIED_BY_NAME,Long.class,userId);
} else if (Integer.class.equals(clazz)) {
myMetaObjectHandler.strictInsertFill(metaObject,LAST_MODIFIED_BY_NAME,Integer.class,userId.intValue());
}
}
}),
;
final String name;
final FillConsumer consumer;
FillFieldEnum(String name, FillConsumer consumer) {
this.name = name;
this.consumer = consumer;
}
private static FillConsumer getConsumerByName(String name) {
return Arrays.stream(FillFieldEnum.values()).filter(o -> o.name.equals(name)).findAny().map(FillFieldEnum::getConsumer).orElse((clazz, metaObject, myMetaObjectHandler) -> log.info("no consumer"));
}
}
/**
* FillConsumer
*/
@FunctionalInterface
private interface FillConsumer{
/**
* accept
*
* @param clazz 类
* @param metaObject 元数据
* @param myMetaObjectHandler 自定义元数据处理器
*/
void accept(Class<?> clazz, MetaObject metaObject, MyMetaObjectHandler myMetaObjectHandler);
}
/**
* 插入元对象字段填充(用于插入时对公共字段的填充)
*
* @param metaObject 元对象
*/
@Override
public void insertFill(MetaObject metaObject) {
TableInfo tableInfo = findTableInfo(metaObject);
tableInfo.getFieldList().forEach(j -> FillFieldEnum.getConsumerByName(j.getProperty()).accept(j.getPropertyType(),metaObject,this));
}
/**
* 更新元对象字段填充(用于更新时对公共字段的填充)
*
* @param metaObject 元对象
*/
@Override
public void updateFill(MetaObject metaObject) {
TableInfo tableInfo = findTableInfo(metaObject);
tableInfo.getFieldList().forEach(j -> FillFieldEnum.getConsumerByName(j.getProperty()).accept(j.getPropertyType(),metaObject,this));
}
private static Long getUserId() {
return 1L;
}
}
分析
代码读起来倒是不难,如果自己实现的话,可能就是 if…else…
,想不到 @FunctionalInterface
,同事用 @FunctionalInterface
非常熟练,将好多用 if…else…
看起来很脏的地方用 @FunctionalInterface
藏了起来。
思考
- 团队可以制定相关的规范
- 建表 DDL 的审核流程完善
- 建表的时候可以用通用的 DDL 对基础字段进行规范
- 如果没用通用 DDL 建表,建立的时候应该按照正确的标准来还是和之前表中的多数命名,个人更倾向于后者
- 刚生成相关代码的时候再对相关字段检查,避免和别人的大多数不一致
好久没在 CSDN 输出内容了,下次可能发 FunctionalInterface 相关的内容,敬请期待吧。
本文含有隐藏内容,请 开通VIP 后查看