Skip to content

Commit be848e4

Browse files
committed
fix(#2932): remove ability to partially specify property name for constructor args
- see #3378 (comment)
1 parent 45716cf commit be848e4

File tree

3 files changed

+21
-10
lines changed

3 files changed

+21
-10
lines changed

Diff for: src/main/java/org/apache/ibatis/builder/ResultMappingConstructorResolver.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public List<ResultMapping> resolveWithConstructor() {
103103
.filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
104104

105105
// arg order can only be 'fixed' if all mappings have property names
106-
final boolean allMappingsHavePropertyNames = constructorResultMappings.size() == constructorArgsByName.size();
106+
final boolean allMappingsHavePropertyNames = verifyPropertyNaming(constructorArgsByName);
107107

108108
// only do this if all property mappings were set
109109
if (allMappingsHavePropertyNames) {
@@ -147,6 +147,19 @@ public List<ResultMapping> resolveWithConstructor() {
147147
return resultMappings;
148148
}
149149

150+
private boolean verifyPropertyNaming(Set<String> constructorArgsByName) {
151+
final boolean allMappingsHavePropertyNames = constructorResultMappings.size() == constructorArgsByName.size();
152+
153+
// If property names have been partially specified, throw an exception, as this case does not make sense
154+
// either specify all names and (optional random order), or type info.
155+
if (!allMappingsHavePropertyNames && !constructorArgsByName.isEmpty()) {
156+
throw new BuilderException("Error in result map '" + resultMapId
157+
+ "'. We do not support partially specifying a property name. Either specify all property names, or none.");
158+
}
159+
160+
return allMappingsHavePropertyNames;
161+
}
162+
150163
List<ConstructorMetaInfo> retrieveConstructorCandidates(int withLength) {
151164
return Arrays.stream(resultType.getDeclaredConstructors())
152165
.filter(constructor -> constructor.getParameterTypes().length == withLength).map(ConstructorMetaInfo::new)

Diff for: src/test/java/org/apache/ibatis/builder/ResultMappingConstructorResolverTest.java

+5-7
Original file line numberDiff line numberDiff line change
@@ -177,18 +177,16 @@ void testReturnOriginalMappingsWhenNoPropertyNamesDefinedAndCannotResolveConstru
177177
}
178178

179179
@Test
180-
void testCanResolveWithMissingPropertyNameAndPartialTypeInfo() {
180+
void testThrowExceptionWithPartialPropertyNameSpecified() {
181181
ResultMapping mappingA = createConstructorMappingFor(Object.class, "a", "a");
182182
ResultMapping mappingB = createConstructorMappingFor(Object.class, null, "b");
183183
ResultMapping mappingC = createConstructorMappingFor(LocalDate.class, null, "c");
184-
ResultMapping[] constructorMappings = new ResultMapping[] { mappingA, mappingB, mappingC };
185184

186-
final ResultMappingConstructorResolver resolver = createResolverFor(ResultType1.class, TEST_ID,
187-
constructorMappings);
188-
final List<ResultMapping> mappingList = resolver.resolveWithConstructor();
185+
final ResultMappingConstructorResolver resolver = createResolverFor(ResultType1.class, TEST_ID, mappingA, mappingB,
186+
mappingC);
189187

190-
assertThat(mappingList).extracting(ResultMapping::getProperty, mapping -> mapping.getJavaType().getSimpleName())
191-
.containsExactly(tuple("a", "long"), tuple(null, "String"), tuple(null, "LocalDate"));
188+
assertThatThrownBy(resolver::resolveWithConstructor).isInstanceOf(BuilderException.class)
189+
.hasMessageContaining("Either specify all property names, or none.");
192190
}
193191

194192
@Test

Diff for: src/test/java/org/apache/ibatis/submitted/auto_type_from_non_ambiguous_constructor/Mapper1.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ public interface Mapper1 {
2626
String SELECT_SQL = "select a.id, a.name, a.type from account a where a.id = #{id}";
2727
String SELECT_WITH_DOB_SQL = "select id, name, type, date '2025-01-05' dob from account where id = #{id}";
2828

29-
@ConstructorArgs({ @Arg(column = "id"), @Arg(column = "name"), @Arg(column = "type")})
29+
@ConstructorArgs({ @Arg(column = "id"), @Arg(column = "name"), @Arg(column = "type") })
3030
@Select(SELECT_SQL)
3131
Account getAccountJavaTypesMissing(long id);
3232

33-
@ConstructorArgs({ @Arg(column = "id"), @Arg(column = "name", javaType = String.class), @Arg(column = "type")})
33+
@ConstructorArgs({ @Arg(column = "id"), @Arg(column = "name", javaType = String.class), @Arg(column = "type") })
3434
@Select(SELECT_SQL)
3535
Account3 getAccountPartialTypesProvided(long id);
3636

0 commit comments

Comments
 (0)