Skip to content

Commit fd7fc5f

Browse files
authored
Merge pull request #1277 from mybatis/pr-1240
Fix for #1240
2 parents d5f024c + b20cf31 commit fd7fc5f

File tree

10 files changed

+165
-160
lines changed

10 files changed

+165
-160
lines changed

src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java

Lines changed: 30 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2017 the original author or authors.
2+
* Copyright 2009-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -45,6 +45,7 @@
4545
import org.apache.ibatis.session.ResultContext;
4646
import org.apache.ibatis.session.ResultHandler;
4747
import org.apache.ibatis.session.RowBounds;
48+
import org.apache.ibatis.type.JdbcType;
4849
import org.apache.ibatis.type.TypeHandler;
4950
import org.apache.ibatis.type.TypeHandlerRegistry;
5051

@@ -83,22 +84,20 @@ public class DefaultResultSetHandler implements ResultSetHandler {
8384
private final ReflectorFactory reflectorFactory;
8485

8586
// nested resultmaps
86-
private final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();
87-
private final Map<String, Object> ancestorObjects = new HashMap<String, Object>();
87+
private final Map<CacheKey, Object> nestedResultObjects = new HashMap<>();
88+
private final Map<String, Object> ancestorObjects = new HashMap<>();
8889
private Object previousRowValue;
8990

9091
// multiple resultsets
91-
private final Map<String, ResultMapping> nextResultMaps = new HashMap<String, ResultMapping>();
92-
private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();
92+
private final Map<String, ResultMapping> nextResultMaps = new HashMap<>();
93+
private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<>();
9394

9495
// Cached Automappings
95-
private final Map<String, List<UnMappedColumnAutoMapping>> autoMappingsCache = new HashMap<String, List<UnMappedColumnAutoMapping>>();
96+
private final Map<String, List<UnMappedColumnAutoMapping>> autoMappingsCache = new HashMap<>();
9697

9798
// temporary marking flag that indicate using constructor mapping (use field to reduce memory usage)
9899
private boolean useConstructorMappings;
99100

100-
private final PrimitiveTypes primitiveTypes;
101-
102101
private static class PendingRelation {
103102
public MetaObject metaObject;
104103
public ResultMapping propertyMapping;
@@ -130,7 +129,6 @@ public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatemen
130129
this.objectFactory = configuration.getObjectFactory();
131130
this.reflectorFactory = configuration.getReflectorFactory();
132131
this.resultHandler = resultHandler;
133-
this.primitiveTypes = new PrimitiveTypes();
134132
}
135133

136134
//
@@ -183,7 +181,7 @@ private void handleRefCursorOutputParameter(ResultSet rs, ParameterMapping param
183181
public List<Object> handleResultSets(Statement stmt) throws SQLException {
184182
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
185183

186-
final List<Object> multipleResults = new ArrayList<Object>();
184+
final List<Object> multipleResults = new ArrayList<>();
187185

188186
int resultSetCount = 0;
189187
ResultSetWrapper rsw = getFirstResultSet(stmt);
@@ -232,7 +230,7 @@ public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException
232230
}
233231

234232
ResultMap resultMap = resultMaps.get(0);
235-
return new DefaultCursor<E>(this, resultMap, rsw, rowBounds);
233+
return new DefaultCursor<>(this, resultMap, rsw, rowBounds);
236234
}
237235

238236
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
@@ -252,7 +250,7 @@ private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
252250
return rs != null ? new ResultSetWrapper(rs, configuration) : null;
253251
}
254252

255-
private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {
253+
private ResultSetWrapper getNextResultSet(Statement stmt) {
256254
// Making this method tolerant of bad JDBC drivers
257255
try {
258256
if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {
@@ -348,7 +346,7 @@ protected void checkResultHandler() {
348346

349347
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
350348
throws SQLException {
351-
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
349+
DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
352350
skipRows(rsw.getResultSet(), rowBounds);
353351
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
354352
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
@@ -371,7 +369,7 @@ private void callResultHandler(ResultHandler<?> resultHandler, DefaultResultCont
371369
((ResultHandler<Object>) resultHandler).handleResult(resultContext);
372370
}
373371

374-
private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
372+
private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) {
375373
return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
376374
}
377375

@@ -476,7 +474,7 @@ private List<UnMappedColumnAutoMapping> createAutomaticMappings(ResultSetWrapper
476474
final String mapKey = resultMap.getId() + ":" + columnPrefix;
477475
List<UnMappedColumnAutoMapping> autoMapping = autoMappingsCache.get(mapKey);
478476
if (autoMapping == null) {
479-
autoMapping = new ArrayList<UnMappedColumnAutoMapping>();
477+
autoMapping = new ArrayList<>();
480478
final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
481479
for (String columnName : unmappedColumnNames) {
482480
String propertyName = columnName;
@@ -549,12 +547,8 @@ private void addPendingChildRelation(ResultSet rs, MetaObject metaResultObject,
549547
PendingRelation deferLoad = new PendingRelation();
550548
deferLoad.metaObject = metaResultObject;
551549
deferLoad.propertyMapping = parentMapping;
552-
List<PendingRelation> relations = pendingRelations.get(cacheKey);
550+
List<PendingRelation> relations = pendingRelations.computeIfAbsent(cacheKey, k -> new ArrayList<>());
553551
// issue #255
554-
if (relations == null) {
555-
relations = new ArrayList<DefaultResultSetHandler.PendingRelation>();
556-
pendingRelations.put(cacheKey, relations);
557-
}
558552
relations.add(deferLoad);
559553
ResultMapping previous = nextResultMaps.get(parentMapping.getResultSet());
560554
if (previous == null) {
@@ -589,8 +583,8 @@ private CacheKey createKeyForMultipleResults(ResultSet rs, ResultMapping resultM
589583

590584
private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {
591585
this.useConstructorMappings = false; // reset previous mapping result
592-
final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();
593-
final List<Object> constructorArgs = new ArrayList<Object>();
586+
final List<Class<?>> constructorArgTypes = new ArrayList<>();
587+
final List<Object> constructorArgs = new ArrayList<>();
594588
Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);
595589
if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
596590
final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();
@@ -655,12 +649,12 @@ Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType
655649
private Object createByConstructorSignature(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,
656650
String columnPrefix) throws SQLException {
657651
final Constructor<?>[] constructors = resultType.getDeclaredConstructors();
658-
final Constructor<?> annotatedConstructor = findAnnotatedConstructor(constructors);
659-
if (annotatedConstructor != null) {
660-
return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix, annotatedConstructor);
652+
final Constructor<?> defaultConstructor = findDefaultConstructor(constructors);
653+
if (defaultConstructor != null) {
654+
return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix, defaultConstructor);
661655
} else {
662656
for (Constructor<?> constructor : constructors) {
663-
if (allowedConstructor(constructor, rsw.getClassNames())) {
657+
if (allowedConstructorUsingTypeHandlers(constructor, rsw.getJdbcTypes())) {
664658
return createUsingConstructor(rsw, resultType, constructorArgTypes, constructorArgs, columnPrefix, constructor);
665659
}
666660
}
@@ -682,7 +676,9 @@ private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType,
682676
return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
683677
}
684678

685-
private Constructor<?> findAnnotatedConstructor(final Constructor<?>[] constructors) {
679+
private Constructor<?> findDefaultConstructor(final Constructor<?>[] constructors) {
680+
if (constructors.length == 1) return constructors[0];
681+
686682
for (final Constructor<?> constructor : constructors) {
687683
if (constructor.isAnnotationPresent(AutomapConstructor.class)) {
688684
return constructor;
@@ -691,29 +687,17 @@ private Constructor<?> findAnnotatedConstructor(final Constructor<?>[] construct
691687
return null;
692688
}
693689

694-
private boolean allowedConstructor(final Constructor<?> constructor, final List<String> classNames) {
690+
private boolean allowedConstructorUsingTypeHandlers(final Constructor<?> constructor, final List<JdbcType> jdbcTypes) {
695691
final Class<?>[] parameterTypes = constructor.getParameterTypes();
696-
if (typeNames(parameterTypes).equals(classNames)) return true;
697-
if (parameterTypes.length != classNames.size()) return false;
692+
if (parameterTypes.length != jdbcTypes.size()) return false;
698693
for (int i = 0; i < parameterTypes.length; i++) {
699-
final Class<?> parameterType = parameterTypes[i];
700-
if (parameterType.isPrimitive() && !primitiveTypes.getWrapper(parameterType).getName().equals(classNames.get(i))) {
701-
return false;
702-
} else if (!parameterType.isPrimitive() && !parameterType.getName().equals(classNames.get(i))) {
694+
if (!typeHandlerRegistry.hasTypeHandler(parameterTypes[i], jdbcTypes.get(i))) {
703695
return false;
704696
}
705697
}
706698
return true;
707699
}
708700

709-
private List<String> typeNames(Class<?>[] parameterTypes) {
710-
List<String> names = new ArrayList<String>();
711-
for (Class<?> type : parameterTypes) {
712-
names.add(type.getName());
713-
}
714-
return names;
715-
}
716-
717701
private Object createPrimitiveResultObject(ResultSetWrapper rsw, ResultMap resultMap, String columnPrefix) throws SQLException {
718702
final Class<?> resultType = resultMap.getType();
719703
final String columnName;
@@ -813,9 +797,9 @@ private Object prepareCompositeKeyParameter(ResultSet rs, ResultMapping resultMa
813797

814798
private Object instantiateParameterObject(Class<?> parameterType) {
815799
if (parameterType == null) {
816-
return new HashMap<Object, Object>();
800+
return new HashMap<>();
817801
} else if (ParamMap.class.equals(parameterType)) {
818-
return new HashMap<Object, Object>(); // issue #649
802+
return new HashMap<>(); // issue #649
819803
} else {
820804
return objectFactory.create(parameterType);
821805
}
@@ -826,7 +810,7 @@ private Object instantiateParameterObject(Class<?> parameterType) {
826810
//
827811

828812
public ResultMap resolveDiscriminatedResultMap(ResultSet rs, ResultMap resultMap, String columnPrefix) throws SQLException {
829-
Set<String> pastDiscriminators = new HashSet<String>();
813+
Set<String> pastDiscriminators = new HashSet<>();
830814
Discriminator discriminator = resultMap.getDiscriminator();
831815
while (discriminator != null) {
832816
final Object value = getDiscriminatorValue(rs, discriminator, columnPrefix);
@@ -863,7 +847,7 @@ private String prependPrefix(String columnName, String prefix) {
863847
//
864848

865849
private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
866-
final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
850+
final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
867851
skipRows(rsw.getResultSet(), rowBounds);
868852
Object rowValue = previousRowValue;
869853
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {

src/main/java/org/apache/ibatis/executor/resultset/PrimitiveTypes.java

Lines changed: 0 additions & 52 deletions
This file was deleted.

src/main/java/org/apache/ibatis/executor/resultset/ResultSetWrapper.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2017 the original author or authors.
2+
* Copyright 2009-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -74,6 +74,10 @@ public List<String> getClassNames() {
7474
return Collections.unmodifiableList(classNames);
7575
}
7676

77+
public List<JdbcType> getJdbcTypes() {
78+
return jdbcTypes;
79+
}
80+
7781
public JdbcType getJdbcType(String columnName) {
7882
for (int i = 0 ; i < columnNames.size(); i++) {
7983
if (columnNames.get(i).equalsIgnoreCase(columnName)) {

src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@
5454
*/
5555
public final class TypeHandlerRegistry {
5656

57-
private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<JdbcType, TypeHandler<?>>(JdbcType.class);
58-
private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new ConcurrentHashMap<Type, Map<JdbcType, TypeHandler<?>>>();
57+
private final Map<JdbcType, TypeHandler<?>> JDBC_TYPE_HANDLER_MAP = new EnumMap<>(JdbcType.class);
58+
private final Map<Type, Map<JdbcType, TypeHandler<?>>> TYPE_HANDLER_MAP = new ConcurrentHashMap<>();
5959
private final TypeHandler<Object> UNKNOWN_TYPE_HANDLER = new UnknownTypeHandler(this);
60-
private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<Class<?>, TypeHandler<?>>();
60+
private final Map<Class<?>, TypeHandler<?>> ALL_TYPE_HANDLERS_MAP = new HashMap<>();
6161

6262
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
6363

@@ -267,7 +267,7 @@ private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMapForEnumInterfaces(Class<?
267267
}
268268
if (jdbcHandlerMap != null) {
269269
// Found a type handler regsiterd to a super interface
270-
HashMap<JdbcType, TypeHandler<?>> newMap = new HashMap<JdbcType, TypeHandler<?>>();
270+
HashMap<JdbcType, TypeHandler<?>> newMap = new HashMap<>();
271271
for (Entry<JdbcType, TypeHandler<?>> entry : jdbcHandlerMap.entrySet()) {
272272
// Create a type handler instance with enum type as a constructor arg
273273
newMap.put(entry.getKey(), getInstance(enumClazz, entry.getValue().getClass()));
@@ -377,7 +377,7 @@ private void register(Type javaType, JdbcType jdbcType, TypeHandler<?> handler)
377377
if (javaType != null) {
378378
Map<JdbcType, TypeHandler<?>> map = TYPE_HANDLER_MAP.get(javaType);
379379
if (map == null || map == NULL_TYPE_HANDLER_MAP) {
380-
map = new HashMap<JdbcType, TypeHandler<?>>();
380+
map = new HashMap<>();
381381
TYPE_HANDLER_MAP.put(javaType, map);
382382
}
383383
map.put(jdbcType, handler);
@@ -446,7 +446,7 @@ public <T> TypeHandler<T> getInstance(Class<?> javaTypeClass, Class<?> typeHandl
446446
// scan
447447

448448
public void register(String packageName) {
449-
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
449+
ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
450450
resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
451451
Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
452452
for (Class<?> type : handlerSet) {

src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorMapper.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2017 the original author or authors.
2+
* Copyright 2009-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,12 +26,12 @@ public interface AutoConstructorMapper {
2626
@Select("SELECT * FROM subject")
2727
List<PrimitiveSubject> getSubjects();
2828

29-
@Select("SELECT * FROM subject")
30-
List<WrapperSubject> getWrapperSubjects();
31-
3229
@Select("SELECT * FROM subject")
3330
List<AnnotatedSubject> getAnnotatedSubjects();
3431

3532
@Select("SELECT * FROM subject")
3633
List<BadSubject> getBadSubjects();
34+
35+
@Select("SELECT * FROM extensive_subject")
36+
List<ExtensiveSubject> getExtensiveSubject();
3737
}

0 commit comments

Comments
 (0)