Skip to content

Commit 30a249a

Browse files
committed
performance optimizacion (avoid calling containsKey)
1 parent d87fff1 commit 30a249a

File tree

3 files changed

+61
-58
lines changed

3 files changed

+61
-58
lines changed

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

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ protected void handleRowValues(ResultSet rs, ResultMap resultMap, ResultHandler
8080
Object rowValue = null;
8181
while (shouldProcessMoreRows(rs, resultContext, rowBounds)) {
8282
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rs, resultMap, null);
83-
final CacheKey rowKey = createAbsoluteKey(discriminatedResultMap, rs, null, resultColumnCache);
84-
final boolean knownValue = objectCache.containsKey(rowKey);
85-
if (!knownValue && rowValue != null) { // issue #542 delay calling ResultHandler until object ends
83+
final CacheKey rowKey = createRowKey(discriminatedResultMap, rs, null, resultColumnCache);
84+
Object partialObject = objectCache.get(rowKey);
85+
if (partialObject == null && rowValue != null) { // issue #542 delay calling ResultHandler until object ends
8686
if (mappedStatement.isResultOrdered()) objectCache.clear(); // issue #577 clear memory if ordered
8787
callResultHandler(resultHandler, resultContext, rowValue);
8888
}
89-
rowValue = getRowValue(rs, discriminatedResultMap, rowKey, resultColumnCache);
89+
rowValue = getRowValue(rs, discriminatedResultMap, rowKey, rowKey, null, resultColumnCache, partialObject);
9090
}
9191
if (rowValue != null) callResultHandler(resultHandler, resultContext, rowValue);
9292
}
@@ -95,40 +95,32 @@ protected void handleRowValues(ResultSet rs, ResultMap resultMap, ResultHandler
9595
// GET VALUE FROM ROW
9696
//
9797

98-
@Override
99-
protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey rowKey, ResultColumnCache resultColumnCache) throws SQLException {
100-
return getRowValue(rs, resultMap, rowKey, rowKey, null, resultColumnCache);
101-
}
102-
103-
protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
104-
Object resultObject = ancestorCache.get(absoluteKey);
105-
if (resultObject == null) {
106-
resultObject = objectCache.get(combinedKey);
107-
if (resultObject != null) {
108-
ancestorCache.put(absoluteKey, resultObject);
98+
protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combinedKey, CacheKey absoluteKey, String columnPrefix, ResultColumnCache resultColumnCache, Object partialObject) throws SQLException {
99+
Object resultObject = partialObject;
100+
if (resultObject != null) {
101+
final MetaObject metaObject = configuration.newMetaObject(resultObject);
102+
ancestorCache.put(absoluteKey, resultObject);
103+
applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, false);
104+
ancestorCache.remove(absoluteKey);
105+
} else {
106+
final ResultLoaderMap lazyLoader = instantiateResultLoaderMap();
107+
resultObject = createResultObject(rs, resultMap, lazyLoader, columnPrefix, resultColumnCache);
108+
if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
109109
final MetaObject metaObject = configuration.newMetaObject(resultObject);
110-
applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, false);
111-
ancestorCache.remove(absoluteKey);
112-
} else {
113-
final ResultLoaderMap lazyLoader = instantiateResultLoaderMap();
114-
resultObject = createResultObject(rs, resultMap, lazyLoader, columnPrefix, resultColumnCache);
115-
if (resultObject != null && !typeHandlerRegistry.hasTypeHandler(resultMap.getType())) {
116-
ancestorCache.put(absoluteKey, resultObject);
117-
final MetaObject metaObject = configuration.newMetaObject(resultObject);
118-
boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;
119-
if (shouldApplyAutomaticMappings(resultMap, AutoMappingBehavior.FULL.equals(configuration.getAutoMappingBehavior()))) {
120-
final List<String> unmappedColumnNames = resultColumnCache.getUnmappedColumnNames(resultMap, columnPrefix);
121-
foundValues = applyAutomaticMappings(rs, unmappedColumnNames, metaObject, columnPrefix, resultColumnCache) || foundValues;
122-
}
123-
final List<String> mappedColumnNames = resultColumnCache.getMappedColumnNames(resultMap, columnPrefix);
124-
foundValues = applyPropertyMappings(rs, resultMap, mappedColumnNames, metaObject, lazyLoader, columnPrefix) || foundValues;
125-
foundValues = applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, true) || foundValues;
126-
foundValues = (lazyLoader != null && lazyLoader.size() > 0) || foundValues;
127-
resultObject = foundValues ? resultObject : null;
128-
ancestorCache.remove(absoluteKey);
110+
boolean foundValues = resultMap.getConstructorResultMappings().size() > 0;
111+
if (shouldApplyAutomaticMappings(resultMap, AutoMappingBehavior.FULL.equals(configuration.getAutoMappingBehavior()))) {
112+
final List<String> unmappedColumnNames = resultColumnCache.getUnmappedColumnNames(resultMap, columnPrefix);
113+
foundValues = applyAutomaticMappings(rs, unmappedColumnNames, metaObject, columnPrefix, resultColumnCache) || foundValues;
129114
}
130-
if (combinedKey != CacheKey.NULL_CACHE_KEY) objectCache.put(combinedKey, resultObject);
115+
final List<String> mappedColumnNames = resultColumnCache.getMappedColumnNames(resultMap, columnPrefix);
116+
foundValues = applyPropertyMappings(rs, resultMap, mappedColumnNames, metaObject, lazyLoader, columnPrefix) || foundValues;
117+
ancestorCache.put(absoluteKey, resultObject);
118+
foundValues = applyNestedResultMappings(rs, resultMap, metaObject, columnPrefix, resultColumnCache, combinedKey, true) || foundValues;
119+
ancestorCache.remove(absoluteKey);
120+
foundValues = (lazyLoader != null && lazyLoader.size() > 0) || foundValues;
121+
resultObject = foundValues ? resultObject : null;
131122
}
123+
if (combinedKey != CacheKey.NULL_CACHE_KEY) objectCache.put(combinedKey, resultObject);
132124
}
133125
return resultObject;
134126
}
@@ -137,7 +129,7 @@ protected Object getRowValue(ResultSet rs, ResultMap resultMap, CacheKey combine
137129
// NESTED RESULT MAP (JOIN MAPPING)
138130
//
139131

140-
private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, MetaObject metaObject, String parentPrefix, ResultColumnCache resultColumnCache, CacheKey parentRowKey, boolean parentIsNew) {
132+
private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, MetaObject metaObject, String parentPrefix, ResultColumnCache resultColumnCache, CacheKey parentRowKey, boolean newObject) {
141133
boolean foundValues = false;
142134
for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {
143135
final String nestedResultMapId = resultMapping.getNestedResultMapId();
@@ -148,26 +140,29 @@ private boolean applyNestedResultMappings(ResultSet rs, ResultMap resultMap, Met
148140
if (resultMapping.getColumnPrefix() != null) columnPrefixBuilder.append(resultMapping.getColumnPrefix());
149141
final String columnPrefix = columnPrefixBuilder.length() == 0 ? null : columnPrefixBuilder.toString().toUpperCase(Locale.ENGLISH);
150142
final ResultMap nestedResultMap = getNestedResultMap(rs, nestedResultMapId, columnPrefix);
151-
final CacheKey absoluteKey = createAbsoluteKey(nestedResultMap, rs, columnPrefix, resultColumnCache);
152-
final CacheKey combinedKey = combineKeys(absoluteKey, parentRowKey);
153-
final boolean knownValue = objectCache.containsKey(combinedKey);
154-
final boolean isAncestor = ancestorCache.containsKey(absoluteKey);
155-
Object rowValue = getRowValue(rs, nestedResultMap, combinedKey, absoluteKey, columnPrefix, resultColumnCache);
156-
final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // even if there is no data an empty collection is set
157-
if (rowValue != null
158-
&& ((isAncestor && parentIsNew)
159-
|| (!isAncestor && !knownValue && anyNotNullColumnHasValue(resultMapping, columnPrefix, rs)))) {
160-
if (collectionProperty != null) {
161-
final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
162-
targetMetaObject.add(rowValue);
163-
} else {
164-
if (!parentIsNew) {
165-
throw new ExecutorException("Trying to overwrite a previous set value for the association '" + resultMapping.getProperty()
166-
+ "'. Check your id/result elements to ensure they identify uniquely an record.");
143+
final CacheKey rowKey = createRowKey(nestedResultMap, rs, columnPrefix, resultColumnCache);
144+
final Object ancestorObject = ancestorCache.get(rowKey);
145+
if (ancestorObject != null) {
146+
if (newObject) metaObject.setValue(resultMapping.getProperty(), ancestorObject);
147+
} else {
148+
final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);
149+
Object rowValue = objectCache.get(combinedKey);
150+
boolean knownValue = (rowValue != null);
151+
rowValue = getRowValue(rs, nestedResultMap, combinedKey, rowKey, columnPrefix, resultColumnCache, rowValue);
152+
final Object collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // even if there is no data an empty collection is set
153+
if (rowValue != null && !knownValue && anyNotNullColumnHasValue(resultMapping, columnPrefix, rs)) {
154+
if (collectionProperty != null) {
155+
final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);
156+
targetMetaObject.add(rowValue);
157+
} else {
158+
if (!newObject) {
159+
throw new ExecutorException("Trying to overwrite a previous set value for the association '" + resultMapping.getProperty()
160+
+ "'. Check your id/result elements to ensure they identify uniquely an record.");
161+
}
162+
metaObject.setValue(resultMapping.getProperty(), rowValue);
167163
}
168-
metaObject.setValue(resultMapping.getProperty(), rowValue);
164+
foundValues = true;
169165
}
170-
foundValues = true;
171166
}
172167
} catch (SQLException e) {
173168
throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'. Cause: " + e, e);
@@ -226,7 +221,7 @@ private ResultMap getNestedResultMap(ResultSet rs, String nestedResultMapId, Str
226221
// UNIQUE RESULT KEY
227222
//
228223

229-
private CacheKey createAbsoluteKey(ResultMap resultMap, ResultSet rs, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
224+
private CacheKey createRowKey(ResultMap resultMap, ResultSet rs, String columnPrefix, ResultColumnCache resultColumnCache) throws SQLException {
230225
final CacheKey cacheKey = new CacheKey();
231226
cacheKey.update(resultMap.getId());
232227
List<ResultMapping> resultMappings = getResultMappingsForRowKey(resultMap);

src/test/java/org/apache/ibatis/submitted/parent_reference_3level/BlogTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
import java.sql.Connection;
2323
import java.sql.DriverManager;
2424

25+
import junit.framework.Assert;
26+
2527
import org.apache.ibatis.io.Resources;
2628
import org.apache.ibatis.jdbc.ScriptRunner;
2729
import org.apache.ibatis.session.SqlSession;
@@ -72,6 +74,11 @@ public void testSelectBlogWithPosts() {
7274
Blog result = mapper.selectBlogByPrimaryKey(1);
7375
assertNotNull(result);
7476
assertEquals("Blog with posts", result.getTitle());
77+
Assert.assertEquals(2, result.getPosts().size());
78+
Post firstPost = result.getPosts().get(0);
79+
Assert.assertEquals(2, firstPost.getComments().size());
80+
Post secondPost = result.getPosts().get(1);
81+
Assert.assertEquals(1, secondPost.getComments().size());
7582
} finally {
7683
session.close();
7784
}
@@ -85,6 +92,7 @@ public void testSelectBlogWithoutPosts() {
8592
Blog result = mapper.selectBlogByPrimaryKey(2);
8693
assertNotNull(result);
8794
assertEquals("Blog without posts", result.getTitle());
95+
Assert.assertEquals(0, result.getPosts().size());
8896
} finally {
8997
session.close();
9098
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,19 @@
3333
<resultMap id="BlogResultMap" type="Blog">
3434
<id column="blog_id" property="id" />
3535
<result column="blog_title" property="title"/>
36-
<collection property="posts" notNullColumn="post_id" resultMap="PostResultMap"></collection>
36+
<collection property="posts" resultMap="PostResultMap"></collection>
3737
</resultMap>
3838

3939
<resultMap id="PostResultMap" type="Post">
4040
<id column="post_id" property="id" />
4141
<result column="post_body" property="body"/>
4242
<association property="blog" resultMap="BlogResultMap"></association>
43-
<collection property="comments" notNullColumn="comment_id" resultMap="CommentResultMap"></collection>
43+
<collection property="comments" resultMap="CommentResultMap"></collection>
4444
</resultMap>
4545

4646
<resultMap id="CommentResultMap" type="Comment">
4747
<id column="comment_id" property="id" />
4848
<result column="comment" property="comment"/>
49-
<association property="post" notNullColumn="post_id" resultMap="PostResultMap"></association>
49+
<association property="post" resultMap="PostResultMap"></association>
5050
</resultMap>
5151
</mapper>

0 commit comments

Comments
 (0)