Skip to content

Commit e73e023

Browse files
authored
Merge pull request #2627 from sogoagain/arg-name-based-constructor-automapping-only-one-automap-constructor
Throw Exception when adding @AutomapConstructor to multiple constructors
2 parents e49fb1f + 68447e2 commit e73e023

File tree

4 files changed

+69
-8
lines changed

4 files changed

+69
-8
lines changed

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

+8-6
Original file line numberDiff line numberDiff line change
@@ -710,12 +710,14 @@ 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-
}
717-
}
718-
if (configuration.isArgNameBasedConstructorAutoMapping()) {
713+
Optional<Constructor<?>> annotated = Arrays.stream(constructors)
714+
.filter(x -> x.isAnnotationPresent(AutomapConstructor.class))
715+
.reduce((x, y) -> {
716+
throw new ExecutorException("@AutomapConstructor should be used in only one constructor.");
717+
});
718+
if (annotated.isPresent()) {
719+
return annotated;
720+
} else if (configuration.isArgNameBasedConstructorAutoMapping()) {
719721
// Finding-best-match type implementation is possible,
720722
// but using @AutomapConstructor seems sufficient.
721723
throw new ExecutorException(MessageFormat.format(

src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorMapper.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,6 +29,9 @@ public interface AutoConstructorMapper {
2929
@Select("SELECT * FROM subject")
3030
List<AnnotatedSubject> getAnnotatedSubjects();
3131

32+
@Select("SELECT * FROM subject")
33+
List<BadAnnotatedSubject> getBadAnnotatedSubjects();
34+
3235
@Select("SELECT * FROM subject")
3336
List<BadSubject> getBadSubjects();
3437

src/test/java/org/apache/ibatis/autoconstructor/AutoConstructorTest.java

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2021 the original author or authors.
2+
* Copyright 2009-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
1515
*/
1616
package org.apache.ibatis.autoconstructor;
1717

18+
import static org.junit.jupiter.api.Assertions.assertEquals;
1819
import static org.junit.jupiter.api.Assertions.assertNotNull;
1920
import static org.junit.jupiter.api.Assertions.assertThrows;
2021

@@ -23,6 +24,7 @@
2324

2425
import org.apache.ibatis.BaseDataTest;
2526
import org.apache.ibatis.exceptions.PersistenceException;
27+
import org.apache.ibatis.executor.ExecutorException;
2628
import org.apache.ibatis.io.Resources;
2729
import org.apache.ibatis.session.SqlSession;
2830
import org.apache.ibatis.session.SqlSessionFactory;
@@ -71,6 +73,16 @@ void annotatedSubject() {
7173
}
7274
}
7375

76+
@Test
77+
void badMultipleAnnotatedSubject() {
78+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
79+
final AutoConstructorMapper mapper = sqlSession.getMapper(AutoConstructorMapper.class);
80+
final PersistenceException ex = assertThrows(PersistenceException.class, mapper::getBadAnnotatedSubjects);
81+
final ExecutorException cause = (ExecutorException) ex.getCause();
82+
assertEquals("@AutomapConstructor should be used in only one constructor.", cause.getMessage());
83+
}
84+
}
85+
7486
@Test
7587
void badSubject() {
7688
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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.autoconstructor;
17+
18+
import org.apache.ibatis.annotations.AutomapConstructor;
19+
20+
public class BadAnnotatedSubject {
21+
private final int id;
22+
private final String name;
23+
private final int age;
24+
private final int height;
25+
private final int weight;
26+
27+
@AutomapConstructor
28+
public BadAnnotatedSubject(final int id, final String name, final int age, final int height, final int weight) {
29+
this.id = id;
30+
this.name = name;
31+
this.age = age;
32+
this.height = height;
33+
this.weight = weight;
34+
}
35+
36+
@AutomapConstructor
37+
public BadAnnotatedSubject(final int id, final String name, final int age) {
38+
this.id = id;
39+
this.name = name;
40+
this.age = age;
41+
this.height = 0;
42+
this.weight = 0;
43+
}
44+
}

0 commit comments

Comments
 (0)