org.apache.ibatis.executor.resultset.DefaultResultSetHandler Maven / Gradle / Ivy
package org.apache.ibatis.executor.resultset;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.*;
import org.apache.ibatis.executor.loader.*;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.result.*;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.reflection.*;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.type.*;
import java.sql.*;
import java.util.*;
public class DefaultResultSetHandler implements ResultSetHandler {
private static final Object NO_VALUE = new Object();
private Configuration configuration;
private final Executor executor;
private final ObjectFactory objectFactory;
private final TypeHandlerRegistry typeHandlerRegistry;
private final MappedStatement mappedStatement;
private final int rowOffset;
private final int rowLimit;
private final Object parameterObject;
private final Map nestedResultObjects;
private final ResultHandler resultHandler;
private final BoundSql boundSql;
private CacheKey currentNestedKey;
public DefaultResultSetHandler(Configuration configuration, Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, int rowOffset, int rowLimit, ResultHandler resultHandler, BoundSql boundSql) {
this.configuration = configuration;
this.executor = executor;
this.objectFactory = mappedStatement.getConfiguration().getObjectFactory();
this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
this.mappedStatement = mappedStatement;
this.rowOffset = rowOffset;
this.rowLimit = rowLimit;
this.parameterObject = parameterHandler.getParameterObject();
this.nestedResultObjects = new HashMap();
this.resultHandler = resultHandler;
this.boundSql = boundSql;
}
public List handleResultSets(Statement statement) throws SQLException {
List resultsList = new ArrayList();
ResultSet rs = getFirstResultSet(statement);
if (rs != null) {
try {
for (int i = 0, n = mappedStatement.getResultMaps().size(); i < n; i++) {
ResultMap resultMap = mappedStatement.getResultMaps().get(i);
ErrorContext.instance().activity("handling result set").object(resultMap.getId());
if (resultHandler == null) {
DefaultResultHandler defaultResultHandler = new DefaultResultHandler();
handleResults(rs, resultMap, defaultResultHandler, rowOffset, rowLimit);
resultsList.add(defaultResultHandler.getResultList());
} else {
handleResults(rs, resultMap, resultHandler, rowOffset, rowLimit);
}
if (moveToNextResultsSafely(statement)) {
rs = statement.getResultSet();
nestedResultObjects.clear();
} else {
break;
}
}
} finally {
closeResultSet(rs);
}
}
if (resultsList.size() == 1) {
return resultsList.get(0);
} else {
return resultsList;
}
}
public void handleOutputParameters(CallableStatement callableStatement) throws SQLException {
ErrorContext.instance().activity("handling output parameters");
MetaObject metaParam = MetaObject.forObject(parameterObject);
List parameterMappings = boundSql.getParameterMappings();
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
if ("java.sql.ResultSet".equalsIgnoreCase(parameterMapping.getJavaType().getName())) {
// TODO: We need an easy way to unit test this without installing Oracle.
// Mocks are obvious, but will they be effective enough? DBunit?
ResultSet rs = (ResultSet) callableStatement.getObject(i + 1);
String resultMapId = parameterMapping.getResultMapId();
if (resultMapId != null) {
ResultMap resultMap = mappedStatement.getConfiguration().getResultMap(resultMapId);
DefaultResultHandler resultHandler = new DefaultResultHandler();
handleResults(rs, resultMap, resultHandler, Executor.NO_ROW_OFFSET, Executor.NO_ROW_LIMIT);
metaParam.setValue(parameterMapping.getProperty(), resultHandler.getResultList());
} else {
throw new ExecutorException("Parameter requires ResultMap for output types of java.sql.ResultSet");
}
rs.close();
} else {
metaParam.setValue(parameterMapping.getProperty(), parameterMapping.getTypeHandler().getResult(callableStatement, i + 1));
}
}
}
}
private void handleResults(ResultSet rs, ResultMap resultMap, ResultHandler resultHandler, int skipResults, int maxResults) throws SQLException {
if (resultMap != null) {
skipResults(rs, skipResults);
ResultContext context = new ResultContext();
while ((maxResults == Executor.NO_ROW_LIMIT || context.getResultCount() < maxResults)
&& !context.isStopped() && rs.next()) {
currentNestedKey = null;
ResultMap rm = resolveSubMap(rs, resultMap);
Object resultObject = loadResultObject(rs, rm, new Reference(false));
if (resultObject != NO_VALUE) {
if (resultObject instanceof PlatformTypeHolder) {
resultObject = ((PlatformTypeHolder) resultObject).get(null);
}
context.nextResultObject(resultObject);
resultHandler.handleResult(context);
}
}
}
}
private Object loadResultObject(ResultSet rs, ResultMap rm, Reference foundValues) throws SQLException {
if (rm.getType() == null) {
throw new ExecutorException("The result class was null when trying to get results for ResultMap " + rm.getId());
}
Object resultObject = createResultObject(rs, rm);
ResultLoaderRegistry lazyLoader = null;
if (this.mappedStatement.getConfiguration().isEnhancementEnabled()) {
lazyLoader = new ResultLoaderRegistry();
resultObject = ResultObjectProxy.createProxy(rm.getType(), resultObject, lazyLoader);
}
List appliedResultMappings = new ArrayList();
resultObject = mapResults(rs, rm, lazyLoader, resultObject, appliedResultMappings, foundValues);
resultObject = processNestedJoinResults(rs, appliedResultMappings, resultObject);
return resultObject;
}
private Object mapResults(ResultSet rs, ResultMap rm, ResultLoaderRegistry lazyLoader, Object resultObject, List appliedResultMappings, Reference foundValues) throws SQLException {
MetaObject metaResultObject = MetaObject.forObject(resultObject);
Set propSet = new HashSet();
Set colSet = new HashSet();
Map autoMappings = new HashMap();
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1, n = rsmd.getColumnCount(); i <= n; i++) {
boolean useLabel = mappedStatement.getConfiguration().isUseColumnLabel();
String columnLabel = (useLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i));
columnLabel = columnLabel.toUpperCase();
String propName = metaResultObject.findProperty(columnLabel);
colSet.add(columnLabel);
if (propName != null && metaResultObject.hasSetter(propName)) {
propSet.add(propName);
Class javaType = metaResultObject.getSetterType(propName);
TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(javaType);
ResultMapping resultMapping = new ResultMapping.Builder(configuration, propName, columnLabel, typeHandler)
.javaType(javaType).build();
autoMappings.put(propName, resultMapping);
}
}
// Map results/ignore missing
for (ResultMapping resultMapping : rm.getPropertyResultMappings()) {
String propName = resultMapping.getProperty();
String colName = resultMapping.getColumn();
colName = colName == null ? null : colName.toUpperCase();
autoMappings.remove(propName);
if (colName == null || colSet.contains(colName)) {
resultObject = processResult(rs, rm, resultMapping, lazyLoader, resultObject, foundValues);
appliedResultMappings.add(resultMapping);
}
}
// Automap remaining results
for (String key : autoMappings.keySet()) {
ResultMapping autoMapping = autoMappings.get(key);
if (autoMapping.getTypeHandler() != null) {
resultObject = processResult(rs, rm, autoMapping, lazyLoader, resultObject, foundValues);
appliedResultMappings.add(autoMapping);
}
}
return resultObject;
}
private Object createResultObject(ResultSet rs, ResultMap rm) throws SQLException {
if (PlatformTypeHolder.isPlatformType(rm.getType())) {
return new PlatformTypeHolder();
}
Object resultObject;
if (rm.getConstructorResultMappings().size() > 0) {
Map constructorArgs = new HashMap();
List argTypes = new ArrayList();
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy