Skip to content

Commit cc7a981

Browse files
committed
1 parent 4f56506 commit cc7a981

File tree

4 files changed

+27
-29
lines changed

4 files changed

+27
-29
lines changed

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

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.apache.ibatis.executor.result.DefaultResultContext;
3232
import org.apache.ibatis.mapping.BoundSql;
3333
import org.apache.ibatis.mapping.MappedStatement;
34-
import org.apache.ibatis.mapping.ResultFlag;
3534
import org.apache.ibatis.mapping.ResultMap;
3635
import org.apache.ibatis.mapping.ResultMapping;
3736
import org.apache.ibatis.reflection.MetaClass;
@@ -112,7 +111,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
112111
final Object resultObject = objectCache.get(combinedKey);
113112
ancestorCache.put(absoluteKey, resultObject);
114113
final MetaObject metaObject = configuration.newMetaObject(resultObject);
115-
applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey);
114+
applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, false);
116115
ancestorCache.remove(absoluteKey);
117116
return resultObject;
118117
} else {
@@ -128,7 +127,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
128127
}
129128
final List<String> mappedColumnNames = resultColumnCache.getMappedColumnNames(resultMap, columnPrefix);
130129
foundValues = applyPropertyMappings(rs, resultMap, mappedColumnNames, metaObject, lazyLoader, columnPrefix) || foundValues;
131-
foundValues = applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey) || foundValues;
130+
foundValues = applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, true) || foundValues;
132131
foundValues = (lazyLoader != null && lazyLoader.size() > 0) || foundValues;
133132
resultObject = foundValues ? resultObject : null;
134133
ancestorCache.remove(absoluteKey);
@@ -142,7 +141,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
142141
// NESTED RESULT MAP (JOIN MAPPING)
143142
//
144143

145-
private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, MetaObject metaObject, String parentPrefix, ResultColumnCache resultColumnCache, CacheKey parentRowKey) {
144+
private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, MetaObject metaObject, String parentPrefix, ResultColumnCache resultColumnCache, CacheKey parentRowKey, boolean parentIsNew) {
146145
boolean foundValues = false;
147146
for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
148147
final String nestedResultMapId = resultMapping.getNestedResultMapId();
@@ -153,18 +152,19 @@ private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, Met
153152
if (resultMapping.getColumnPrefix()!= null) columnPrefixBuilder.append(resultMapping.getColumnPrefix());
154153
final String columnPrefix = columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);
155154
final ResultMap nestedResultMap = getNestedResultMap(rs, nestedResultMapId, columnPrefix);
156-
final Object targetProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);
157-
final MetaObject targetMetaObject = configuration.newMetaObject(targetProperty);
155+
final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);
158156
final CacheKey absoluteKey = createAbsoluteKey(nestedResultMap, rs, columnPrefix, resultColumnCache);
159157
final CacheKey combinedKey = getCombinedKey(absoluteKey, parentRowKey);
160158
final boolean knownValue = objectCache.containsKey(combinedKey);
161-
Object rowValue = getRowValue(rs, nestedResultMap, combinedKey, absoluteKey, columnPrefix, resultColumnCache);
162-
if (rowValue != null && anyNotNullColumnHasValue(resultMapping, columnPrefix, rs)) {
163-
if (targetProperty != null && objectFactory.isCollection(targetProperty.getClass())) {
164-
if (!knownValue) {
165-
targetMetaObject.add(rowValue);
166-
}
159+
Object rowValue = getRowValue(rs, nestedResultMap, combinedKey, absoluteKey, columnPrefix, resultColumnCache);
160+
if (!knownValue && rowValue != null && anyNotNullColumnHasValue(resultMapping, columnPrefix, rs)) {
161+
if (collectionProperty != null) {
162+
final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
163+
targetMetaObject.add(rowValue);
167164
} else {
165+
if (!parentIsNew && !ancestorCache.containsKey(absoluteKey)) {
166+
throw new ExecutorException("Trying to set a 1 to 1 child element twice for '" + resultMapping.getProperty() + "'. Check your id properties.");
167+
}
168168
metaObject.setValue(resultMapping.getProperty(), rowValue);
169169
}
170170
foundValues = true;
@@ -195,22 +195,25 @@ private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String col
195195

196196
private Object instantiateCollectionPropertyIfAppropriate(ResultMapping resultMapping, MetaObject metaObject) {
197197
final String propertyName = resultMapping.getProperty();
198-
Class<?> type = resultMapping.getJavaType();
199198
Object propertyValue = metaObject.getValue(propertyName);
200199
if (propertyValue == null) {
200+
Class<?> type = resultMapping.getJavaType();
201201
if (type == null) {
202202
type = metaObject.getSetterType(propertyName);
203203
}
204204
try {
205205
if (objectFactory.isCollection(type)) {
206206
propertyValue = objectFactory.create(type);
207207
metaObject.setValue(propertyName, propertyValue);
208+
return propertyValue;
208209
}
209210
} catch (Exception e) {
210211
throw new ExecutorException("Error instantiating collection property for result '" + resultMapping.getProperty() + "'. Cause: " + e, e);
211212
}
213+
} else if (objectFactory.isCollection(propertyValue.getClass())) {
214+
return propertyValue;
212215
}
213-
return propertyValue;
216+
return null;
214217
}
215218

216219
private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, String columnPrefix) throws SQLException {
@@ -258,15 +261,10 @@ private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
258261

259262
private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSet rs, CacheKey cacheKey, List<ResultMapping> resultMappings, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
260263
for (ResultMapping resultMapping : resultMappings) {
261-
String nestedResultMapId = resultMapping.getNestedResultMapId();
262-
if (nestedResultMapId != null) {
263-
// Issue #433. Combine child key with parent key when 1 to 1 association is found
264-
List<ResultFlag> flags = resultMapping.getFlags();
265-
if (flags.contains(ResultFlag.ASSOCIATION) || flags.contains(ResultFlag.CONSTRUCTOR)) {
266-
final ResultMap nestedResultMap = configuration.getResultMap(nestedResultMapId);
267-
createRowKeyForMappedProperties(nestedResultMap, rs, cacheKey, getResultMappingsForRowKey(nestedResultMap),
268-
prependPrefix(resultMapping.getColumnPrefix(), columnPrefix), resultColumnCache);
269-
}
264+
if (resultMapping.getNestedResultMapId() != null) {
265+
final ResultMap nestedResultMap = configuration.getResultMap(resultMapping.getNestedResultMapId());
266+
createRowKeyForMappedProperties(nestedResultMap, rs, cacheKey, nestedResultMap.getConstructorResultMappings(),
267+
prependPrefix(resultMapping.getColumnPrefix(), columnPrefix), resultColumnCache);
270268
} else if (resultMapping.getNestedQueryId() == null) {
271269
final String column = prependPrefix(resultMapping.getColumn(), columnPrefix);
272270
final TypeHandler<?> th = resultMapping.getTypeHandler();

src/test/java/org/apache/ibatis/builder/PostMapper.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
<resultMap id="mutablePostLiteMap" type="domain.blog.PostLite">
3939
<result property="blogId" column="blog_id"/>
40-
<association property="id" column="id" resultMap="mutablePostLiteIdMap"/>
40+
<association property="id" column="id" resultMap="postLiteIdMap"/>
4141
</resultMap>
4242

4343
<resultMap id="mutablePostLiteIdMap" type="domain.blog.PostLiteId">

src/test/java/org/apache/ibatis/submitted/associationtest/AssociationTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.sql.Connection;
2020
import java.util.List;
2121

22+
import org.apache.ibatis.exceptions.PersistenceException;
2223
import org.apache.ibatis.io.Resources;
2324
import org.apache.ibatis.jdbc.ScriptRunner;
2425
import org.apache.ibatis.session.SqlSession;
@@ -62,19 +63,18 @@ public void shouldGetAllCars() {
6263
}
6364
}
6465

65-
@Test
66+
@Test(expected=PersistenceException.class)
6667
public void shouldGetAllCarsNonUnique() {
6768
// this is a little weird - we might expect 4 objects back, but there are only
6869
// 2 unique combinations of Car attributes, so we get two back.
6970

7071
// update, this was reported as an error, see Issue #433
71-
// probably is not an error but as this test shows, the expected output should be 4, not 2
72+
// in this case there is data loss, so now it fails
7273
SqlSession sqlSession = sqlSessionFactory.openSession();
7374
try {
7475
Mapper mapper = sqlSession.getMapper(Mapper.class);
7576
List<Car> cars = mapper.getCarsNonUnique();
76-
// Assert.assertEquals(2, cars.size()); // se the comment up there
77-
Assert.assertEquals(4, cars.size());
77+
Assert.assertEquals(2, cars.size());
7878
} finally {
7979
sqlSession.close();
8080
}

src/test/java/org/apache/ibatis/submitted/associationtest/Mapper.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@
3535
</select>
3636

3737
<select id="getCarsNonUnique" resultMap="carResult">
38-
select 1, cartype, enginetype, enginecylinders from cars
38+
select 1 as carid, cartype, enginetype, enginecylinders from cars
3939
</select>
4040
</mapper>

0 commit comments

Comments
 (0)