前言
通过MetaObjectHandler ,可以全局对一些实体类参数进行填充值。
一、自定义MetaObjectHandler
(1)CustomMetaObjectHandler
public class CustomMetaObjectHandler implements MetaObjectHandler {
//insert操作的字段填充
@Override
public void insertFill(MetaObject metaObject) {
Object createBy = getFieldValByName("createBy", metaObject);
if (createBy == null) {
setFieldValByName("createBy", "admin", metaObject);
}
}
//update操作的字段填充
@Override
public void updateFill(MetaObject metaObject) {
Object updateBy = getFieldValByName("updateBy", metaObject);
if (updateBy == null) {
setFieldValByName("updateBy", "admin", metaObject);
}
}
}
(2)开启填充功能
字段上添加注解
@TableField(fill = FieldFill.UPDATE)
private String updateBy;
(3)注册CustomMetaObjectHandler
如果让mybatisplus自动注入该类,就在类上加@Compoment注解;
如果重写了SqlSessionFactory,就手动注入该类
GlobalConfigUtils.getGlobalConfig(configuration).setMetaObjectHandler(new CustomMetaObjectHandler());
private GlobalConfig globalConfiguration() {
GlobalConfig conf = GlobalConfigUtils.defaults();
conf.setMetaObjectHandler(new CustomMetaObjectHandler());
return conf;
}
二、实现原理
是通过MybatisParameterHandler来实现的
(1)MybatisParameterHandler
public class MybatisParameterHandler implements ParameterHandler {
public MybatisParameterHandler(MappedStatement mappedStatement, Object parameter, BoundSql boundSql) {
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
this.mappedStatement = mappedStatement;
this.boundSql = boundSql;
this.configuration = mappedStatement.getConfiguration();
this.sqlCommandType = mappedStatement.getSqlCommandType();
//这里处理参数的入口
this.parameterObject = processParameter(parameter);
}
}
(2)processParameter( )
public Object processParameter(Object parameter) {
/* 只处理插入或更新操作 */
if (parameter != null
&& (SqlCommandType.INSERT == this.sqlCommandType || SqlCommandType.UPDATE == this.sqlCommandType)) {
//检查 parameterObject
if (ReflectionKit.isPrimitiveOrWrapper(parameter.getClass())
|| parameter.getClass() == String.class) {
return parameter;
}
Collection<Object> parameters = getParameters(parameter);
if (null != parameters) {
// 感觉这里可以稍微优化一下,理论上都是同一个.
parameters.forEach(this::process);
} else {
process(parameter);
}
}
return parameter;
}
(3)process( )
private void process(Object parameter) {
if (parameter != null) {
TableInfo tableInfo = null;
Object entity = parameter;
if (parameter instanceof Map) {
Map<?, ?> map = (Map<?, ?>) parameter;
if (map.containsKey(Constants.ENTITY)) {
Object et = map.get(Constants.ENTITY);
if (et != null) {
entity = et;
tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
}
}
} else {
tableInfo = TableInfoHelper.getTableInfo(parameter.getClass());
}
if (tableInfo != null) {
//到这里就应该转换到实体参数对象了,因为填充和ID处理都是争对实体对象处理的,不用传递原参数对象下去.
MetaObject metaObject = this.configuration.newMetaObject(entity);
if (SqlCommandType.INSERT == this.sqlCommandType) {
//填充主键
populateKeys(tableInfo, metaObject, entity);
//插入时填充字段
insertFill(metaObject, tableInfo);
} else {
//更新时填充字段
updateFill(metaObject, tableInfo);
}
}
}
}
(4)populateKeys( )
//处理主键
protected static void populateKeys(TableInfo tableInfo, MetaObject metaObject, Object entity) {
final IdType idType = tableInfo.getIdType();
final String keyProperty = tableInfo.getKeyProperty();
if (StringUtils.isNotBlank(keyProperty) && null != idType && idType.getKey() >= 3) {
final IdentifierGenerator identifierGenerator = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getIdentifierGenerator();
Object idValue = metaObject.getValue(keyProperty);
if (StringUtils.checkValNull(idValue)) {
if (idType.getKey() == IdType.ASSIGN_ID.getKey()) {
//雪花算法
if (Number.class.isAssignableFrom(tableInfo.getKeyType())) {
metaObject.setValue(keyProperty, identifierGenerator.nextId(entity));
} else {
metaObject.setValue(keyProperty, identifierGenerator.nextId(entity).toString());
}
} else if (idType.getKey() == IdType.ASSIGN_UUID.getKey()) {
//UUID
metaObject.setValue(keyProperty, identifierGenerator.nextUUID(entity));
}
}
}
}
(5)insertFill( )
protected void insertFill(MetaObject metaObject, TableInfo tableInfo) {
GlobalConfigUtils.getMetaObjectHandler(this.configuration).ifPresent(metaObjectHandler -> {
//开启了InsertFill,并且有需要填充的字段
if (metaObjectHandler.openInsertFill() && tableInfo.isWithInsertFill()) {
metaObjectHandler.insertFill(metaObject);
}
});
}
(6)updateFill( )
protected void updateFill(MetaObject metaObject, TableInfo tableInfo) {
GlobalConfigUtils.getMetaObjectHandler(this.configuration).ifPresent(metaObjectHandler -> {
//开启了UpdateFill,并且有需要填充的字段
if (metaObjectHandler.openUpdateFill() && tableInfo.isWithUpdateFill()) {
metaObjectHandler.updateFill(metaObject);
}
});
}
总结
本文介绍了Mybatisplus字段填充器MetaObjectHandler的使用及原理。