Skip to content

Commit 330159a

Browse files
committed
when using the argNameBasedConstructorAutoMapping setting, @AutomapConstructor can only be used in one constructor.
1 parent 034cacd commit 330159a

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,12 @@ private Optional<Constructor<?>> findConstructorForAutomapping(final Class<?> re
710710
if (constructors.length == 1) {
711711
return Optional.of(constructors[0]);
712712
}
713-
for (final Constructor<?> constructor : constructors) {
714-
if (constructor.isAnnotationPresent(AutomapConstructor.class)) {
715-
return Optional.of(constructor);
716-
}
713+
List<Constructor<?>> automapConstructors = Arrays.stream(constructors).filter(x -> x.isAnnotationPresent(AutomapConstructor.class)).toList();
714+
if (automapConstructors.size() > 1) {
715+
throw new ExecutorException("@AutomapConstructor should be used in only one constructor.");
716+
}
717+
if (automapConstructors.size() == 1) {
718+
return Optional.of(automapConstructors.get(0));
717719
}
718720
if (configuration.isArgNameBasedConstructorAutoMapping()) {
719721
// Finding-best-match type implementation is possible,

src/test/java/org/apache/ibatis/submitted/arg_name_baesd_constructor_automapping/ArgNameBasedConstructorAutoMappingTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,17 @@ void shouldApplyColumnPrefix() {
135135
assertEquals(99, task.getAssignee().getTeam());
136136
}
137137
}
138+
139+
@Test
140+
void shouldBeOnlyOneAutomapConstructorAnnotation() {
141+
// This test requires -parameters compiler option
142+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
143+
Mapper mapper = sqlSession.getMapper(Mapper.class);
144+
mapper.selectNameAndIdWithAmbiguousConstructor(1);
145+
fail("Exception should be thrown");
146+
} catch (PersistenceException e) {
147+
ExecutorException ex = (ExecutorException) e.getCause();
148+
assertEquals("@AutomapConstructor should be used in only one constructor.", ex.getMessage());
149+
}
150+
}
138151
}

src/test/java/org/apache/ibatis/submitted/arg_name_baesd_constructor_automapping/Mapper.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,8 @@ public interface Mapper {
3434
@Select("select name user_name, id user_id from users where id = #{id}")
3535
User2 selectUserIdAndUserNameUnderscore(Integer id);
3636

37+
@Select("select name, id from users where id = #{id}")
38+
User3 selectNameAndIdWithAmbiguousConstructor(Integer id);
39+
3740
Task selectTask(Integer id);
3841
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2009-2022 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.arg_name_baesd_constructor_automapping;
17+
18+
import org.apache.ibatis.annotations.AutomapConstructor;
19+
20+
public class User3 {
21+
22+
private Integer id;
23+
private String name;
24+
private Long team;
25+
26+
@AutomapConstructor
27+
public User3(Integer id, String name, Long team) {
28+
super();
29+
this.id = id;
30+
this.name = name;
31+
this.team = team;
32+
}
33+
34+
@AutomapConstructor
35+
public User3(Integer id, String name) {
36+
super();
37+
this.id = id;
38+
this.name = name;
39+
this.team = 100L;
40+
}
41+
42+
public Integer getId() {
43+
return id;
44+
}
45+
46+
public String getName() {
47+
return name;
48+
}
49+
50+
public void setTeam(Long team) {
51+
this.team = team;
52+
}
53+
54+
public Long getTeam() {
55+
return team;
56+
}
57+
}

0 commit comments

Comments
 (0)