31
31
import org .apache .ibatis .executor .result .DefaultResultContext ;
32
32
import org .apache .ibatis .mapping .BoundSql ;
33
33
import org .apache .ibatis .mapping .MappedStatement ;
34
- import org .apache .ibatis .mapping .ResultFlag ;
35
34
import org .apache .ibatis .mapping .ResultMap ;
36
35
import org .apache .ibatis .mapping .ResultMapping ;
37
36
import org .apache .ibatis .reflection .MetaClass ;
@@ -112,7 +111,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
112
111
final Object resultObject = objectCache .get (combinedKey );
113
112
ancestorCache .put (absoluteKey , resultObject );
114
113
final MetaObject metaObject = configuration .newMetaObject (resultObject );
115
- applyNestedResultMappings (rs , resultMap , metaObject , columnPrefix , resultColumnCache , combinedKey );
114
+ applyNestedResultMappings (rs , resultMap , metaObject , columnPrefix , resultColumnCache , combinedKey , false );
116
115
ancestorCache .remove (absoluteKey );
117
116
return resultObject ;
118
117
} else {
@@ -128,7 +127,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
128
127
}
129
128
final List <String > mappedColumnNames = resultColumnCache .getMappedColumnNames (resultMap , columnPrefix );
130
129
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 ;
132
131
foundValues = (lazyLoader != null && lazyLoader .size () > 0 ) || foundValues ;
133
132
resultObject = foundValues ? resultObject : null ;
134
133
ancestorCache .remove (absoluteKey );
@@ -142,7 +141,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
142
141
// NESTED RESULT MAP (JOIN MAPPING)
143
142
//
144
143
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 ) {
146
145
boolean foundValues = false ;
147
146
for (ResultMapping resultMapping : resultMap .getPropertyResultMappings ()) {
148
147
final String nestedResultMapId = resultMapping .getNestedResultMapId ();
@@ -153,18 +152,19 @@ private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, Met
153
152
if (resultMapping .getColumnPrefix ()!= null ) columnPrefixBuilder .append (resultMapping .getColumnPrefix ());
154
153
final String columnPrefix = columnPrefixBuilder .length () == 0 ? null : columnPrefixBuilder .toString ().toUpperCase (Locale .ENGLISH );
155
154
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 );
158
156
final CacheKey absoluteKey = createAbsoluteKey (nestedResultMap , rs , columnPrefix , resultColumnCache );
159
157
final CacheKey combinedKey = getCombinedKey (absoluteKey , parentRowKey );
160
158
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 );
167
164
} 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
+ }
168
168
metaObject .setValue (resultMapping .getProperty (), rowValue );
169
169
}
170
170
foundValues = true ;
@@ -195,22 +195,25 @@ private boolean anyNotNullColumnHasValue(ResultMapping resultMapping, String col
195
195
196
196
private Object instantiateCollectionPropertyIfAppropriate (ResultMapping resultMapping , MetaObject metaObject ) {
197
197
final String propertyName = resultMapping .getProperty ();
198
- Class <?> type = resultMapping .getJavaType ();
199
198
Object propertyValue = metaObject .getValue (propertyName );
200
199
if (propertyValue == null ) {
200
+ Class <?> type = resultMapping .getJavaType ();
201
201
if (type == null ) {
202
202
type = metaObject .getSetterType (propertyName );
203
203
}
204
204
try {
205
205
if (objectFactory .isCollection (type )) {
206
206
propertyValue = objectFactory .create (type );
207
207
metaObject .setValue (propertyName , propertyValue );
208
+ return propertyValue ;
208
209
}
209
210
} catch (Exception e ) {
210
211
throw new ExecutorException ("Error instantiating collection property for result '" + resultMapping .getProperty () + "'. Cause: " + e , e );
211
212
}
213
+ } else if (objectFactory .isCollection (propertyValue .getClass ())) {
214
+ return propertyValue ;
212
215
}
213
- return propertyValue ;
216
+ return null ;
214
217
}
215
218
216
219
private ResultMap getNestedResultMap (ResultSet rs , String nestedResultMapId , String columnPrefix ) throws SQLException {
@@ -258,15 +261,10 @@ private List<ResultMapping> getResultMappingsForRowKey(ResultMap resultMap) {
258
261
259
262
private void createRowKeyForMappedProperties (ResultMap resultMap , ResultSet rs , CacheKey cacheKey , List <ResultMapping > resultMappings , String columnPrefix , ResultColumnCache resultColumnCache ) throws SQLException {
260
263
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 );
270
268
} else if (resultMapping .getNestedQueryId () == null ) {
271
269
final String column = prependPrefix (resultMapping .getColumn (), columnPrefix );
272
270
final TypeHandler <?> th = resultMapping .getTypeHandler ();
0 commit comments