Skip to content

Commit 541fc61

Browse files
committed
Added coverage for failing cases
- Removed label outer: structure
1 parent aa1f246 commit 541fc61

File tree

6 files changed

+181
-8
lines changed

6 files changed

+181
-8
lines changed

src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -480,32 +480,40 @@ private Class<?> resolveParameterJavaType(Class<?> resultType, String property,
480480
* the current mappings
481481
*
482482
* @return null if there are no missing javaType mappings, or if no suitable mapping could be determined
483+
*
484+
* @see <a href="https://github.com/mybatis/mybatis-3/issues/2618">#2618</a>
483485
*/
484486
public List<ResultMapping> autoTypeResultMappingsForUnknownJavaTypes(Class<?> resultType,
485487
List<ResultMapping> resultMappings) {
488+
final List<Class<?>> typesToMatch = resultMappings.stream().map(ResultMapping::getJavaType)
489+
.collect(Collectors.toList());
490+
486491
// check if we have any undefined java types present, and try to set them automatically
487-
if (resultMappings.stream().noneMatch(resultMapping -> Object.class.equals(resultMapping.getJavaType()))) {
492+
if (typesToMatch.stream().noneMatch(type -> type == null || Object.class.equals(type))) {
488493
return null;
489494
}
490495

491496
final List<List<Class<?>>> matchingConstructors = Arrays.stream(resultType.getDeclaredConstructors())
492497
.map(Constructor::getParameterTypes).filter(parameters -> parameters.length == resultMappings.size())
493498
.map(Arrays::asList).collect(Collectors.toList());
494499

495-
final List<Class<?>> typesToMatch = resultMappings.stream().map(ResultMapping::getJavaType)
496-
.collect(Collectors.toList());
497-
498500
List<Class<?>> matchingTypes = null;
499-
500-
outer: for (final List<Class<?>> actualTypes : matchingConstructors) {
501+
for (List<Class<?>> actualTypes : matchingConstructors) {
502+
boolean matchesType = true;
501503
for (int j = 0; j < typesToMatch.size(); j++) {
502504
final Class<?> type = typesToMatch.get(j);
505+
503506
// pre-filled a type, check if it matches the constructor
504-
if (!Object.class.equals(type) && !type.equals(actualTypes.get(j))) {
505-
continue outer;
507+
if (type != null && !Object.class.equals(type) && !type.equals(actualTypes.get(j))) {
508+
matchesType = false;
509+
break;
506510
}
507511
}
508512

513+
if (!matchesType) {
514+
continue;
515+
}
516+
509517
if (matchingTypes != null) {
510518
// multiple matches found, abort as we cannot reliably guess the correct one.
511519
matchingTypes = null;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2009-2025 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+
* https://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.auto_type_from_non_ambiguous_constructor;
17+
18+
public record Account1(long accountId, String accountName, String accountType) {
19+
public Account1(long accountId, String accountName, int accountTypeId) {
20+
this(accountId, accountName, String.valueOf(accountTypeId));
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2009-2025 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+
* https://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.auto_type_from_non_ambiguous_constructor;
17+
18+
import java.io.IOException;
19+
import java.io.Reader;
20+
21+
import org.apache.ibatis.builder.BuilderException;
22+
import org.apache.ibatis.io.Resources;
23+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
24+
import org.assertj.core.api.Assertions;
25+
import org.junit.jupiter.api.Test;
26+
27+
class AutoTypeFromNonAmbiguousConstructorFailingTest {
28+
29+
@Test
30+
void testCannotResolveAmbiguousConstructor() throws IOException {
31+
// Account1 has more than 1 matching constructor, and auto type cannot decide which one to use
32+
try (Reader reader = Resources.getResourceAsReader(
33+
"org/apache/ibatis/submitted/auto_type_from_non_ambiguous_constructor/mybatis-config-failing.xml")) {
34+
35+
Assertions.assertThatThrownBy(() -> new SqlSessionFactoryBuilder().build(reader)).isNotNull()
36+
.hasCauseInstanceOf(BuilderException.class).hasMessageContaining("Failed to find a constructor");
37+
}
38+
}
39+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright 2009-2025 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+
* https://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.auto_type_from_non_ambiguous_constructor;
17+
18+
public interface FailingMapper {
19+
20+
Account1 getAccountAmbiguous(long id);
21+
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2025 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+
https://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 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
20+
<mapper namespace="org.apache.ibatis.submitted.auto_type_from_non_ambiguous_constructor.FailingMapper">
21+
22+
<resultMap id="account1RM" type="org.apache.ibatis.submitted.auto_type_from_non_ambiguous_constructor.Account1">
23+
<constructor>
24+
<idArg name="accountId" column="id"/>
25+
<arg name="accountName" column="name"/>
26+
<arg name="accountType" column="type"/>
27+
</constructor>
28+
</resultMap>
29+
30+
<sql id="accountSelect">
31+
select a.id
32+
, a.name
33+
, a.type
34+
from account a
35+
where a.id = #{id}
36+
</sql>
37+
38+
<select id="getAccountAmbiguous" resultMap="account1RM">
39+
<include refid="accountSelect"/>
40+
</select>
41+
</mapper>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!--
3+
4+
Copyright 2009-2025 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+
https://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+
"https://mybatis.org/dtd/mybatis-3-config.dtd">
22+
23+
<configuration>
24+
<environments default="development">
25+
<environment id="development">
26+
<transactionManager type="JDBC">
27+
<property name="" value=""/>
28+
</transactionManager>
29+
<dataSource type="UNPOOLED">
30+
<property name="driver" value="org.hsqldb.jdbcDriver"/>
31+
<property name="url"
32+
value="jdbc:hsqldb:mem:argNameBasedConstructorAutoMapping"/>
33+
<property name="username" value="sa"/>
34+
</dataSource>
35+
</environment>
36+
</environments>
37+
38+
<mappers>
39+
<mapper class="org.apache.ibatis.submitted.auto_type_from_non_ambiguous_constructor.FailingMapper"/>
40+
</mappers>
41+
</configuration>

0 commit comments

Comments
 (0)