MybatisPlus源码解析3:元数据处理器-MetaObjectHandler
功能:MetaObjectHandler在insert和update的时候,对参数的属性进行填充,可以对数据库的通用字段(比如:创建人、创建时间、更新人和时间等)进行赋值操作。
原理:
MetaObjectHandler对参数的元数据进行处理。创建ParameterHandler -> 创建ParameterHandler -> 对传入的对象进行了参数的填充。
1. 执行流程
BaseStatementHandler#BaseStatementHandler - 创建StatementHandler
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = mappedStatement.getConfiguration();
this.executor = executor;
this.mappedStatement = mappedStatement;
this.rowBounds = rowBounds;
this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
this.objectFactory = configuration.getObjectFactory();
if (boundSql == null) { // issue #435, get the key before calculating the statement
generateKeys(parameterObject);
boundSql = mappedStatement.getBoundSql(parameterObject);
}
this.boundSql = boundSql;
this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
}
创建ParameterHandler
public class MybatisXMLLanguageDriver extends XMLLanguageDriver {
@Override
public MybatisDefaultParameterHandler createParameterHandler(MappedStatement mappedStatement,
Object parameterObject, BoundSql boundSql) {
// TODO 使用 MybatisDefaultParameterHandler 而不是 ParameterHandler
return new MybatisDefaultParameterHandler(mappedStatement, parameterObject, boundSql);
}
}
public MybatisDefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
super(mappedStatement, processParameter(mappedStatement, parameterObject), boundSql);
this.mappedStatement = mappedStatement;
this.configuration = mappedStatement.getConfiguration();
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
this.parameterObject = parameterObject;
this.boundSql = boundSql;
}
通过processParameter(mappedStatement, parameterObject)对参数进行增强
protected static Object processParameter(MappedStatement ms, Object parameterObject) {
/* 只处理插入或更新操作 */
if (parameterObject != null
&& (SqlCommandType.INSERT == ms.getSqlCommandType() || SqlCommandType.UPDATE == ms.getSqlCommandType())) {
//检查 parameterObject
if (ReflectionKit.isPrimitiveOrWrapper(parameterObject.getClass())
|| parameterObject.getClass() == String.class) {
return parameterObject;
}
Collection<Object> parameters = getParameters(parameterObject);
if (null != parameters) {
// 感觉这里可以稍微优化一下,理论上都是同一个.
parameters.forEach(obj -> process(ms, obj));
} else {
process(ms, parameterObject);
}
}
return parameterObject;
}
如果参数不为空,并且是Insert或者Update,那么就对参数进行处理
private static void process(MappedStatement ms, Object parameterObject) {
if (parameterObject != null) {
TableInfo tableInfo = null;
Object entity = parameterObject;
if (parameterObject instanceof Map) {
Map<?, ?> map = (Map<?, ?>) parameterObject;
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(parameterObject.getClass());
}
if (tableInfo != null) {
//到这里就应该转换到实体参数对象了,因为填充和ID处理都是争对实体对象处理的,不用传递原参数对象下去.
MetaObject metaObject = ms.getConfiguration().newMetaObject(entity);
if (SqlCommandType.INSERT == ms.getSqlCommandType()) {
populateKeys(tableInfo, metaObject, entity);
insertFill(metaObject, tableInfo);
} else {
updateFill(metaObject, tableInfo);
}
}
}
}
- 获取到实体类entity 对象
- 通过实体对象获取表的信息tableInfo
- 具体调用insertFill和updateFill进行属性填充