Author: cbegin
Date: Mon Sep 7 06:49:36 2009
New Revision: 812008
URL: http://svn.apache.org/viewvc?rev=812008&view=rev
Log:
Started a re-implementation of ResultSetHandler
Added:
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NewResultSetHandler.java
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/RowLimit.java
Modified:
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java
Added:
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NewResultSetHandler.java
URL:
http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NewResultSetHandler.java?rev=812008&view=auto
==============================================================================
---
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NewResultSetHandler.java
(added)
+++
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/NewResultSetHandler.java
Mon Sep 7 06:49:36 2009
@@ -0,0 +1,201 @@
+package org.apache.ibatis.executor.resultset;
+
+import org.apache.ibatis.mapping.*;
+import org.apache.ibatis.type.TypeHandler;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+import org.apache.ibatis.reflection.factory.ObjectFactory;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.executor.resultset.RowLimit;
+import org.apache.ibatis.executor.ErrorContext;
+import org.apache.ibatis.executor.ExecutorException;
+import org.apache.ibatis.executor.parameter.ParameterHandler;
+import org.apache.ibatis.executor.result.DefaultResultHandler;
+import org.apache.ibatis.executor.result.ResultHandler;
+import org.apache.ibatis.executor.result.ResultContext;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.sql.*;
+
+public class NewResultSetHandler implements ResultSetHandler {
+
+ private final Configuration configuration;
+ private final MappedStatement mappedStatement;
+ private final RowLimit rowLimit;
+ private final ParameterHandler parameterHandler;
+ private final ResultHandler resultHandler;
+ private final BoundSql boundSql;
+ private TypeHandlerRegistry typeHandlerRegistry;
+
+
+ public NewResultSetHandler(Configuration configuration, MappedStatement
mappedStatement, ParameterHandler parameterHandler, ResultHandler
resultHandler, BoundSql boundSql, int offset, int limit) {
+ this.configuration = configuration;
+ this.mappedStatement = mappedStatement;
+ this.rowLimit = new RowLimit(offset, limit);
+ this.parameterHandler = parameterHandler;
+ this.resultHandler = resultHandler;
+ this.boundSql = boundSql;
+ this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
+ }
+
+ public void handleOutputParameters(CallableStatement cs) throws SQLException
{
+ ErrorContext.instance().activity("handling output parameters");
+ Object parameterObject = parameterHandler.getParameterObject();
+ MetaObject metaParam = MetaObject.forObject(parameterObject);
+ List<ParameterMapping> 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()))
{
+ handleResultSetOutputParameter(cs, parameterMapping, i, metaParam);
+ } else {
+ metaParam.setValue(parameterMapping.getProperty(),
parameterMapping.getTypeHandler().getResult(cs, i + 1));
+ }
+ }
+ }
+ }
+
+ private void handleResultSetOutputParameter(CallableStatement cs,
ParameterMapping parameterMapping, int parameterMappingIndex, MetaObject
metaParam) throws SQLException {
+ ResultSet rs = (ResultSet) cs.getObject(parameterMappingIndex + 1);
+ String resultMapId = parameterMapping.getResultMapId();
+ if (resultMapId != null) {
+ ResultMap resultMap =
mappedStatement.getConfiguration().getResultMap(resultMapId);
+ DefaultResultHandler resultHandler = new DefaultResultHandler();
+ handleResultSet(rs, resultMap, resultHandler, new RowLimit());
+ metaParam.setValue(parameterMapping.getProperty(),
resultHandler.getResultList());
+ } else {
+ throw new ExecutorException("Parameter requires ResultMap for output
types of java.sql.ResultSet");
+ }
+ rs.close();
+ }
+
+ public List handleResultSets(Statement stmt) throws SQLException {
+ final List multipleResults = new ArrayList();
+ final List<ResultMap> resultMaps = mappedStatement.getResultMaps();
+ int count = 0;
+ ResultSet rs = stmt.getResultSet();
+ while (rs != null) {
+ final ResultMap resultMap = resultMaps.get(count);
+ if (resultHandler == null) {
+ DefaultResultHandler defaultResultHandler = new DefaultResultHandler();
+ handleResultSet(rs, resultMap, defaultResultHandler, rowLimit);
+ multipleResults.add(defaultResultHandler.getResultList());
+ } else {
+ handleResultSet(rs, resultMap, resultHandler, rowLimit);
+ }
+ rs = getNextResultSet(stmt);
+ count++;
+ }
+ return collapseSingleResultList(multipleResults);
+ }
+
+ private List collapseSingleResultList(List multipleResults) {
+ if (multipleResults.size() == 1) {
+ return (List) multipleResults.get(0);
+ } else {
+ return multipleResults;
+ }
+ }
+
+ private void handleResultSet(ResultSet rs, ResultMap resultMap,
ResultHandler resultHandler, RowLimit rowLimit) throws SQLException {
+ final ResultContext resultContext = new ResultContext();
+ final List<String> unmappedColumnNames = getUnmappedColumnNames(rs,
resultMap);
+ skipRows(rs, rowLimit);
+ while (shouldProcessMoreRows(rs, resultContext.getResultCount(),
rowLimit)) {
+ final Object resultObject = createResultObject(rs, resultMap);
+ final MetaObject metaObject = MetaObject.forObject(resultObject);
+ applyPropertyMappings(rs, resultMap, metaObject);
+ applyAutomaticMappings(rs, unmappedColumnNames, metaObject);
+ resultContext.nextResultObject(resultObject);
+ resultHandler.handleResult(resultContext);
+ }
+ }
+
+ private boolean shouldProcessMoreRows(ResultSet rs, int count, RowLimit
rowLimit) throws SQLException {
+ return rs.next() && count < rowLimit.getLimit();
+ }
+
+ private void skipRows(ResultSet rs, RowLimit rowLimit) throws SQLException {
+ if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
+ rs.absolute(rowLimit.getOffset());
+ } else {
+ for (int i=0; i < rowLimit.getOffset(); i++) rs.next();
+ }
+ }
+
+ private void applyPropertyMappings(ResultSet rs, ResultMap resultMap,
MetaObject metaObject) throws SQLException {
+ final List<ResultMapping> propertyMappings =
resultMap.getPropertyResultMappings();
+ for (ResultMapping propertyMapping : propertyMappings) {
+ final TypeHandler typeHandler = propertyMapping.getTypeHandler();
+ final String property = propertyMapping.getProperty();
+ final String column = propertyMapping.getColumn();
+ final Object value = typeHandler.getResult(rs, column);
+ metaObject.setValue(property, value);
+ }
+ }
+
+ private void applyAutomaticMappings(ResultSet rs, List<String>
unmappedColumnNames, MetaObject metaObject) throws SQLException {
+ for(String columnName : unmappedColumnNames) {
+ final String property = metaObject.findProperty(columnName);
+ if (property != null) {
+ final Class propertyType = metaObject.getSetterType(property);
+ final TypeHandler typeHandler =
typeHandlerRegistry.getTypeHandler(propertyType);
+ final Object value = typeHandler.getResult(rs, columnName);
+ metaObject.setValue(property, value);
+ }
+ }
+ }
+
+ private List<String> getUnmappedColumnNames(ResultSet rs, ResultMap
resultMap) throws SQLException {
+ final ResultSetMetaData rsmd = rs.getMetaData();
+ final int columnCount = rsmd.getColumnCount();
+ final List<String> columnNames = new ArrayList<String>();
+ final Set<String> mappedColumns = resultMap.getMappedColumns();
+ for(int i=1; i<=columnCount; i++) {
+ final String columnName = configuration.isUseColumnLabel() ?
rsmd.getColumnLabel(i) : rsmd.getColumnName(i);
+ final String upperColumnName = columnName.toUpperCase();
+ if (!mappedColumns.contains(upperColumnName)) {
+ columnNames.add(columnName);
+ }
+ }
+ return columnNames;
+ }
+
+ private Object createResultObject(ResultSet rs, ResultMap resultMap) throws
SQLException {
+ final Class resultType = resultMap.getType();
+ final ObjectFactory objectFactory = configuration.getObjectFactory();
+ final List<ResultMapping> constructorMappings =
resultMap.getConstructorResultMappings();
+ if (constructorMappings.size() == 0) {
+ return objectFactory.create(resultType);
+ } else {
+ final List<Class> parameterTypes = new ArrayList<Class>();
+ final List<Object> parameterValues = new ArrayList<Object>();
+ for(ResultMapping constructorMapping : constructorMappings) {
+ final Class parameterType = constructorMapping.getJavaType();
+ final TypeHandler typeHandler = constructorMapping.getTypeHandler();
+ final String column = constructorMapping.getColumn();
+ final Object value = typeHandler.getResult(rs, column);
+ parameterTypes.add(parameterType);
+ parameterValues.add(value);
+ }
+ return objectFactory.create(resultType, parameterTypes, parameterValues);
+ }
+ }
+
+ private ResultSet getNextResultSet(Statement stmt) throws SQLException {
+ // Making this method tolerant of bad JDBC drivers
+ try {
+ if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
+ // Crazy Standard JDBC way of determining if there are more results
+ if (!((!stmt.getMoreResults()) && (stmt.getUpdateCount() == -1))) {
+ return stmt.getResultSet();
+ }
+ }
+ } catch (Exception e) {
+ // Intentionally ignored.
+ }
+ return null;
+ }
+
+}
Added:
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/RowLimit.java
URL:
http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/RowLimit.java?rev=812008&view=auto
==============================================================================
---
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/RowLimit.java
(added)
+++
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/executor/resultset/RowLimit.java
Mon Sep 7 06:49:36 2009
@@ -0,0 +1,29 @@
+package org.apache.ibatis.executor.resultset;
+
+public class RowLimit {
+
+ public final static int NO_ROW_OFFSET = 0;
+ public final static int NO_ROW_LIMIT = Integer.MAX_VALUE;
+
+ private int offset;
+ private int limit;
+
+ public RowLimit() {
+ this.offset = NO_ROW_OFFSET;
+ this.limit = NO_ROW_LIMIT;
+ }
+
+ public RowLimit(int offset, int limit) {
+ this.offset = offset;
+ this.limit = limit;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public int getLimit() {
+ return limit;
+ }
+
+}
Modified:
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java
URL:
http://svn.apache.org/viewvc/ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java?rev=812008&r1=812007&r2=812008&view=diff
==============================================================================
---
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java
(original)
+++
ibatis/java/ibatis-3/trunk/ibatis-3-core/src/main/java/org/apache/ibatis/mapping/ResultMap.java
Mon Sep 7 06:49:36 2009
@@ -10,6 +10,7 @@
private List<ResultMapping> idResultMappings;
private List<ResultMapping> constructorResultMappings;
private List<ResultMapping> propertyResultMappings;
+ private Set<String> mappedColumns;
private Discriminator discriminator;
private ResultMap() {
@@ -34,10 +35,15 @@
}
public ResultMap build() {
+ resultMap.mappedColumns = new HashSet<String>();
resultMap.idResultMappings = new ArrayList<ResultMapping>();
resultMap.constructorResultMappings = new ArrayList<ResultMapping>();
resultMap.propertyResultMappings = new ArrayList<ResultMapping>();
for (ResultMapping resultMapping : resultMap.resultMappings) {
+ final String column = resultMapping.getColumn();
+ if (column != null) {
+ resultMap.mappedColumns.add(column.toUpperCase());
+ }
if (resultMapping.getFlags().contains(ResultFlag.CONSTRUCTOR)) {
resultMap.constructorResultMappings.add(resultMapping);
} else {
@@ -55,6 +61,7 @@
resultMap.idResultMappings =
Collections.unmodifiableList(resultMap.idResultMappings);
resultMap.constructorResultMappings =
Collections.unmodifiableList(resultMap.constructorResultMappings);
resultMap.propertyResultMappings =
Collections.unmodifiableList(resultMap.propertyResultMappings);
+ resultMap.mappedColumns =
Collections.unmodifiableSet(resultMap.mappedColumns);
return resultMap;
}
}
@@ -84,6 +91,10 @@
return idResultMappings;
}
+ public Set<String> getMappedColumns() {
+ return mappedColumns;
+ }
+
public Discriminator getDiscriminator() {
return discriminator;
}