Skip to content

Commit 3cacf14

Browse files
committed
fixes #1176 Deeply nested result map could cause IllegalArgumentException.
1 parent 6fe5d62 commit 3cacf14

File tree

8 files changed

+290
-6
lines changed

8 files changed

+290
-6
lines changed

src/main/java/org/apache/ibatis/session/Configuration.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.Collection;
2020
import java.util.HashMap;
2121
import java.util.HashSet;
22+
import java.util.Iterator;
2223
import java.util.LinkedList;
2324
import java.util.List;
2425
import java.util.Map;
@@ -27,6 +28,7 @@
2728

2829
import org.apache.ibatis.binding.MapperRegistry;
2930
import org.apache.ibatis.builder.CacheRefResolver;
31+
import org.apache.ibatis.builder.IncompleteElementException;
3032
import org.apache.ibatis.builder.ResultMapResolver;
3133
import org.apache.ibatis.builder.annotation.MethodResolver;
3234
import org.apache.ibatis.builder.xml.XMLStatementBuilder;
@@ -770,12 +772,7 @@ public void addCacheRef(String namespace, String referencedNamespace) {
770772
* statement validation.
771773
*/
772774
protected void buildAllStatements() {
773-
if (!incompleteResultMaps.isEmpty()) {
774-
synchronized (incompleteResultMaps) {
775-
// This always throws a BuilderException.
776-
incompleteResultMaps.iterator().next().resolve();
777-
}
778-
}
775+
parsePendingResultMaps();
779776
if (!incompleteCacheRefs.isEmpty()) {
780777
synchronized (incompleteCacheRefs) {
781778
// This always throws a BuilderException.
@@ -798,6 +795,33 @@ protected void buildAllStatements() {
798795
}
799796
}
800797

798+
private void parsePendingResultMaps() {
799+
if (incompleteResultMaps.isEmpty()) {
800+
return;
801+
}
802+
synchronized (incompleteResultMaps) {
803+
boolean resolved;
804+
IncompleteElementException ex = null;
805+
do {
806+
resolved = false;
807+
Iterator<ResultMapResolver> iterator = incompleteResultMaps.iterator();
808+
while (iterator.hasNext()) {
809+
try {
810+
iterator.next().resolve();
811+
iterator.remove();
812+
resolved = true;
813+
} catch (IncompleteElementException e) {
814+
ex = e;
815+
}
816+
}
817+
} while (resolved);
818+
if (!incompleteResultMaps.isEmpty() && ex != null) {
819+
// At least one result map is unresolvable.
820+
throw ex;
821+
}
822+
}
823+
}
824+
801825
/*
802826
* Extracts namespace from fully qualified statement id.
803827
*
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* Copyright 2009-2018 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.resolution.deepresultmap;
17+
18+
import java.io.Reader;
19+
20+
import org.apache.ibatis.BaseDataTest;
21+
import org.apache.ibatis.io.Resources;
22+
import org.apache.ibatis.session.SqlSession;
23+
import org.apache.ibatis.session.SqlSessionFactory;
24+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
25+
import org.apache.ibatis.submitted.resolution.User;
26+
import org.junit.Assert;
27+
import org.junit.BeforeClass;
28+
import org.junit.Test;
29+
30+
public class DeepResultMapTest {
31+
32+
private static SqlSessionFactory sqlSessionFactory;
33+
34+
@BeforeClass
35+
public static void setUp() throws Exception {
36+
// create an SqlSessionFactory
37+
try (Reader reader = Resources
38+
.getResourceAsReader("org/apache/ibatis/submitted/resolution/deepresultmap/mybatis-config.xml")) {
39+
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
40+
}
41+
42+
// populate in-memory database
43+
BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
44+
"org/apache/ibatis/submitted/resolution/CreateDB.sql");
45+
}
46+
47+
@Test
48+
public void shouldGetAUser() {
49+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
50+
MapperA mapper = sqlSession.getMapper(MapperA.class);
51+
User user = mapper.getUser(1);
52+
Assert.assertEquals(Integer.valueOf(1), user.getId());
53+
Assert.assertEquals("User1", user.getName());
54+
}
55+
}
56+
57+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* Copyright 2009-2018 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.resolution.deepresultmap;
17+
18+
import org.apache.ibatis.submitted.resolution.User;
19+
20+
public interface MapperA {
21+
User getUser(Integer id);
22+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE mapper
20+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
22+
23+
<mapper
24+
namespace="org.apache.ibatis.submitted.resolution.deepresultmap.MapperA">
25+
26+
<resultMap
27+
type="org.apache.ibatis.submitted.resolution.User" id="rmA"
28+
extends="org.apache.ibatis.submitted.resolution.deepresultmap.MapperB.rmB">
29+
</resultMap>
30+
31+
<select id="getUser" resultMap="rmA">
32+
select id userId, name userName
33+
from users where id = #{id}
34+
</select>
35+
36+
</mapper>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE mapper
20+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
22+
23+
<mapper
24+
namespace="org.apache.ibatis.submitted.resolution.deepresultmap.MapperB">
25+
26+
<resultMap
27+
type="org.apache.ibatis.submitted.resolution.User" id="rmB"
28+
extends="org.apache.ibatis.submitted.resolution.deepresultmap.MapperC.rmC">
29+
</resultMap>
30+
31+
</mapper>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE mapper
20+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
22+
23+
<mapper
24+
namespace="org.apache.ibatis.submitted.resolution.deepresultmap.MapperC">
25+
26+
<resultMap
27+
type="org.apache.ibatis.submitted.resolution.User" id="rmC"
28+
extends="org.apache.ibatis.submitted.resolution.deepresultmap.MapperD.rmD">
29+
</resultMap>
30+
31+
</mapper>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE mapper
20+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
22+
23+
<mapper
24+
namespace="org.apache.ibatis.submitted.resolution.deepresultmap.MapperD">
25+
26+
27+
<resultMap
28+
type="org.apache.ibatis.submitted.resolution.User" id="rmD">
29+
<id property="id" column="userId" />
30+
<result property="name" column="userName" />
31+
</resultMap>
32+
33+
</mapper>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!--
3+
4+
Copyright 2009-2018 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE configuration
20+
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-config.dtd">
22+
23+
<configuration>
24+
25+
<environments default="development">
26+
<environment id="development">
27+
<transactionManager type="JDBC">
28+
<property name="" value="" />
29+
</transactionManager>
30+
<dataSource type="UNPOOLED">
31+
<property name="driver" value="org.hsqldb.jdbcDriver" />
32+
<property name="url"
33+
value="jdbc:hsqldb:mem:deepresultmap" />
34+
<property name="username" value="sa" />
35+
</dataSource>
36+
</environment>
37+
</environments>
38+
39+
<mappers>
40+
<mapper
41+
class="org.apache.ibatis.submitted.resolution.deepresultmap.MapperA" />
42+
<mapper
43+
resource="org/apache/ibatis/submitted/resolution/deepresultmap/MapperB.xml" />
44+
<mapper
45+
resource="org/apache/ibatis/submitted/resolution/deepresultmap/MapperC.xml" />
46+
<mapper
47+
resource="org/apache/ibatis/submitted/resolution/deepresultmap/MapperD.xml" />
48+
</mappers>
49+
50+
</configuration>

0 commit comments

Comments
 (0)