Mybatis深入剖析 - typeHandlerRegistry parameterHandler resultSetHandler
Statement在具体orm的过程总,主要靠这三个类进行参数装配,结果装配和相应的类型转换
- parameterHandler
- resultSetHandler
- typeHandlerRegistry
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) { this.configuration = mappedStatement.getConfiguration(); this.executor = executor; this.mappedStatement = mappedStatement; this.rowBounds = rowBounds; this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.objectFactory = configuration.getObjectFactory(); this.boundSql = mappedStatement.getBoundSql(parameterObject); this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); }
?
?
typeHandlerRegistry?
parameterHandler
? ? 只有一个实现类,DefaultParameterHandler,它负责把代码传入的参数,装配到preparestatement中去,根据下面的代码可以看出,根据mapper中配置的解析出的parameterMapping规则从代码传入parameterObject的对象出反射取出属性值,在根据TypeHandler做java到jdbc类型的数据格式转换,最终装配到jdbc的statement中去
?
?
MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject); for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); PropertyTokenizer prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName.startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = configuration.newMetaObject(value).getValue(propertyName.substring(prop.getName().length())); } } else { value = metaObject == null ? null : metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); if (typeHandler == null) { throw new ExecutorException("There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId()); } typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType()); }
?
?
resultSetHandler
?有两个实现,一般结果集处理由FastResultSetHandler完成,嵌套符合结果集的处理由NestedResultSetHandler完成,看下面的resultset的配置就能明白是啥意思了
ResultSetHandler resultSetHandler = mappedStatement.hasNestedResultMaps() ? new NestedResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds) : new FastResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
?
<resultMap id="processDefinitionResultMap" type="com.apusic.bpm.engine.definition.ProcessDefinition"> <constructor> <idArg column="ID_" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg column="KEY_" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg column="NAME_" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg column="VERSION_" jdbcType="INTEGER" javaType="java.lang.Long" /> <arg column="DESCRIPTION_" jdbcType="VARCHAR" javaType="java.lang.String" /> <arg javaType="com.apusic.bpm.engine.definition.ProcessDefinitionResourceMapping" resultMap="resourceMappingResultMap" /> </constructor> </resultMap> <resultMap id="resourceMappingResultMap" type="com.apusic.bpm.engine.definition.ProcessDefinitionResourceMapping"> <constructor> <arg column="PROCESS_DEFINITION_PATH_" jdbcType="VARCHAR" javaType="java.lang.String"/> <arg column="RESOURCE_PATHS_" jdbcType="VARCHAR" javaType="java.util.Set" /> </constructor> </resultMap>
?FastResultSetHandler的核心代码如下,从jdbc resultset结果集中去除结果,根据TypeHandler将jdbc类型的数据转换成java类型的数据,塞回到结果集java对象中
public List handleResultSets(Statement stmt) throws SQLException { final List multipleResults = new ArrayList(); final List<ResultMap> resultMaps = mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); int resultSetCount = 0; ResultSet rs = stmt.getResultSet(); while (rs == null) { // move forward to get the first resultset in case the driver // doesn't return the resultset as the first result (HSQLDB 2.1) if (stmt.getMoreResults()) { rs = stmt.getResultSet(); } else { if (stmt.getUpdateCount() == -1) { // no more results. Must be no resultset break; } } } validateResultMapsCount(rs, resultMapCount); while (rs != null && resultMapCount > resultSetCount) { final ResultMap resultMap = resultMaps.get(resultSetCount); handleResultSet(rs, resultMap, multipleResults); rs = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } return collapseSingleResultList(multipleResults); }
?