Skip to content

Commit 82c85dc

Browse files
committed
Fixes #273 An extra call to ResultHandler#handleResult is made for a nested result map.
1 parent cbacd88 commit 82c85dc

File tree

7 files changed

+346
-5
lines changed

7 files changed

+346
-5
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap r
286286
throws SQLException {
287287
DefaultResultContext resultContext = new DefaultResultContext();
288288
skipRows(rsw.getResultSet(), rowBounds);
289-
while (shouldProcessMoreRows(rsw.getResultSet(), resultContext, rowBounds)) {
289+
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
290290
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
291291
Object rowValue = getRowValue(rsw, discriminatedResultMap);
292292
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
@@ -306,8 +306,8 @@ private void callResultHandler(ResultHandler resultHandler, DefaultResultContext
306306
resultHandler.handleResult(resultContext);
307307
}
308308

309-
private boolean shouldProcessMoreRows(ResultSet rs, ResultContext context, RowBounds rowBounds) throws SQLException {
310-
return !context.isStopped() && rs.next() && context.getResultCount() < rowBounds.getLimit();
309+
private boolean shouldProcessMoreRows(ResultContext context, RowBounds rowBounds) throws SQLException {
310+
return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
311311
}
312312

313313
private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
@@ -699,7 +699,7 @@ private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap r
699699
final DefaultResultContext resultContext = new DefaultResultContext();
700700
skipRows(rsw.getResultSet(), rowBounds);
701701
Object rowValue = null;
702-
while (shouldProcessMoreRows(rsw.getResultSet(), resultContext, rowBounds)) {
702+
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
703703
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
704704
final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);
705705
Object partialObject = nestedResultObjects.get(rowKey);
@@ -716,7 +716,7 @@ private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap r
716716
}
717717
}
718718
}
719-
if (rowValue != null && mappedStatement.isResultOrdered()) {
719+
if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
720720
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
721721
}
722722
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*-
2+
* Copyright 2009-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.submitted.nestedresulthandler_association;
18+
19+
import java.util.Date;
20+
21+
public class Account {
22+
private String accountUuid;
23+
24+
private String accountName;
25+
26+
private Date birthDate;
27+
28+
private AccountAddress address;
29+
30+
public String getAccountUuid() {
31+
return accountUuid;
32+
}
33+
34+
public void setAccountUuid(String accountUuid) {
35+
this.accountUuid = accountUuid;
36+
}
37+
38+
public String getAccountName() {
39+
return accountName;
40+
}
41+
42+
public void setAccountName(String accountName) {
43+
this.accountName = accountName;
44+
}
45+
46+
public Date getBirthDate() {
47+
return birthDate;
48+
}
49+
50+
public void setBirthDate(Date birthDate) {
51+
this.birthDate = birthDate;
52+
}
53+
54+
public AccountAddress getAddress() {
55+
return address;
56+
}
57+
58+
public void setAddress(AccountAddress address) {
59+
this.address = address;
60+
}
61+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*-
2+
* Copyright 2009-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.apache.ibatis.submitted.nestedresulthandler_association;
18+
19+
public class AccountAddress {
20+
private String accountUuid;
21+
22+
private String zipCode;
23+
24+
private String address;
25+
26+
public String getAccountUuid() {
27+
return accountUuid;
28+
}
29+
30+
public void setAccountUuid(String accountUuid) {
31+
this.accountUuid = accountUuid;
32+
}
33+
34+
public String getZipCode() {
35+
return zipCode;
36+
}
37+
38+
public void setZipCode(String zipCode) {
39+
this.zipCode = zipCode;
40+
}
41+
42+
public String getAddress() {
43+
return address;
44+
}
45+
46+
public void setAddress(String address) {
47+
this.address = address;
48+
}
49+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
Copyright 2009-2014 the original author or authors.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
18+
<mapper namespace="org.apache.ibatis.submitted.nestedresulthandler_association.AccountRepository">
19+
<resultMap id="resultMapAccount" type="org.apache.ibatis.submitted.nestedresulthandler_association.Account">
20+
<id property="accountUuid" column="account_uuid" />
21+
<result property="accountName" column="account_name" />
22+
<result property="birthDate" column="birth_date" />
23+
<association property="address" javaType="org.apache.ibatis.submitted.nestedresulthandler_association.AccountAddress">
24+
<id property="accountUuid" column="account_uuid" />
25+
<result property="zipCode" column="zip_code" />
26+
<result property="address" column="address" />
27+
</association>
28+
</resultMap>
29+
<select id="collectPageByBirthMonth" resultMap="resultMapAccount" resultOrdered="true">
30+
<![CDATA[
31+
SELECT
32+
a.account_uuid
33+
,a.account_name
34+
,a.birth_date
35+
,aa.zip_code
36+
,aa.address
37+
FROM
38+
t_account a
39+
LEFT OUTER JOIN
40+
t_account_address aa
41+
ON aa.account_uuid = a.account_uuid
42+
WHERE
43+
a.birth_date >= #{birthMonth} AND a.birth_date < ADD_MONTHS(#{birthMonth}, 1)
44+
ORDER BY
45+
a.account_uuid
46+
]]>
47+
</select>
48+
</mapper>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--
2+
-- Copyright 2009-2014 the original author or authors.
3+
--
4+
-- Licensed under the Apache License, Version 2.0 (the "License");
5+
-- you may not use this file except in compliance with the License.
6+
-- You may obtain a copy of the License at
7+
--
8+
-- http://www.apache.org/licenses/LICENSE-2.0
9+
--
10+
-- Unless required by applicable law or agreed to in writing, software
11+
-- distributed under the License is distributed on an "AS IS" BASIS,
12+
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
-- See the License for the specific language governing permissions and
14+
-- limitations under the License.
15+
--
16+
17+
DROP TABLE t_account_address if exists;
18+
DROP TABLE t_account if exists;
19+
CREATE TABLE t_account(
20+
account_uuid CHAR(36) PRIMARY KEY
21+
,account_name VARCHAR(256)
22+
,birth_date DATETIME
23+
);
24+
CREATE TABLE t_account_address(
25+
account_uuid CHAR(36) PRIMARY KEY
26+
,zip_code CHAR(7)
27+
,address VARCHAR(256)
28+
);
29+
30+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc01', 'Bob1', '2014-01-01 00:00:00.000');
31+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc02', 'Bob2', '2014-01-02 00:00:00.000');
32+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc03', 'Bob3', '2014-01-03 00:00:00.000');
33+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc04', 'Bob4', '2014-01-04 00:00:00.000');
34+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc05', 'Bob5', '2014-01-05 00:00:00.000');
35+
INSERT INTO t_account (account_uuid,account_name,birth_date) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc11', 'Mark1', '2014-02-01 00:00:00.000');
36+
37+
INSERT INTO t_account_address (account_uuid,zip_code,address) VALUES ('4d3c8bdd-5379-4aeb-bc56-fcb01eb7cc02', '1710051', 'Tokyo Toshimaku Nagasaki');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
* Copyright 2009-2014 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.apache.ibatis.submitted.nestedresulthandler_association;
17+
18+
import static org.junit.Assert.*;
19+
20+
import java.io.Reader;
21+
import java.sql.Connection;
22+
import java.text.SimpleDateFormat;
23+
import java.util.ArrayList;
24+
import java.util.Date;
25+
import java.util.List;
26+
27+
import org.apache.ibatis.io.Resources;
28+
import org.apache.ibatis.jdbc.ScriptRunner;
29+
import org.apache.ibatis.session.ResultContext;
30+
import org.apache.ibatis.session.ResultHandler;
31+
import org.apache.ibatis.session.RowBounds;
32+
import org.apache.ibatis.session.SqlSession;
33+
import org.apache.ibatis.session.SqlSessionFactory;
34+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
35+
import org.junit.BeforeClass;
36+
import org.junit.Test;
37+
38+
public class NestedResultHandlerAssociationTest {
39+
40+
private static SqlSessionFactory sqlSessionFactory;
41+
42+
@BeforeClass
43+
public static void setUp() throws Exception {
44+
// create an SqlSessionFactory
45+
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/nestedresulthandler_association/mybatis-config.xml");
46+
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
47+
reader.close();
48+
49+
// populate in-memory database
50+
SqlSession session = sqlSessionFactory.openSession();
51+
Connection conn = session.getConnection();
52+
reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/nestedresulthandler_association/CreateDB.sql");
53+
ScriptRunner runner = new ScriptRunner(conn);
54+
runner.setLogWriter(null);
55+
runner.runScript(reader);
56+
reader.close();
57+
session.close();
58+
}
59+
60+
@Test
61+
public void shouldHandleRowBounds() throws Exception {
62+
SqlSession sqlSession = sqlSessionFactory.openSession();
63+
final SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
64+
Date targetMonth = fmt.parse("2014-01-01");
65+
final List<Account> accounts = new ArrayList<Account>();
66+
try {
67+
sqlSession.select("collectPageByBirthMonth", targetMonth, new RowBounds(1, 2), new ResultHandler() {
68+
@Override
69+
public void handleResult(ResultContext context) {
70+
Account account = (Account) context.getResultObject();
71+
accounts.add(account);
72+
}
73+
});
74+
} finally {
75+
sqlSession.close();
76+
}
77+
assertEquals(2, accounts.size());
78+
assertEquals("Bob2", accounts.get(0).getAccountName());
79+
assertEquals("Bob3", accounts.get(1).getAccountName());
80+
}
81+
82+
@Test
83+
public void shouldHandleStop() throws Exception {
84+
SqlSession sqlSession = sqlSessionFactory.openSession();
85+
final SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
86+
final List<Account> accounts = new ArrayList<Account>();
87+
try {
88+
Date targetMonth = fmt.parse("2014-01-01");
89+
sqlSession.select("collectPageByBirthMonth", targetMonth, new ResultHandler() {
90+
@Override
91+
public void handleResult(ResultContext context) {
92+
Account account = (Account) context.getResultObject();
93+
accounts.add(account);
94+
if (accounts.size() > 1)
95+
context.stop();
96+
}
97+
});
98+
} finally {
99+
sqlSession.close();
100+
}
101+
assertEquals(2, accounts.size());
102+
assertEquals("Bob1", accounts.get(0).getAccountName());
103+
assertEquals("Bob2", accounts.get(1).getAccountName());
104+
}
105+
106+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!--
3+
Copyright 2009-2014 the original author or authors.
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
-->
17+
<!DOCTYPE configuration
18+
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
19+
"http://mybatis.org/dtd/mybatis-3-config.dtd">
20+
21+
<configuration>
22+
23+
<environments default="development">
24+
<environment id="development">
25+
<transactionManager type="JDBC">
26+
<property name="" value="" />
27+
</transactionManager>
28+
<dataSource type="UNPOOLED">
29+
<property name="driver" value="org.hsqldb.jdbcDriver" />
30+
<property name="url" value="jdbc:hsqldb:mem:nestedresulthandler_association" />
31+
<property name="username" value="sa" />
32+
</dataSource>
33+
</environment>
34+
</environments>
35+
36+
<mappers>
37+
<mapper resource="org/apache/ibatis/submitted/nestedresulthandler_association/AccountRepository.xml" />
38+
</mappers>
39+
40+
</configuration>

0 commit comments

Comments
 (0)