diff --git a/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java b/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java index e272f8b1d8c..8b853d096fb 100644 --- a/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java +++ b/src/main/java/org/apache/ibatis/builder/MapperBuilderAssistant.java @@ -437,7 +437,7 @@ private Class resolveResultJavaType(Class resultType, String property, Cla if (javaType == null && property != null) { try { MetaClass metaResultType = MetaClass.forClass(resultType, configuration.getReflectorFactory()); - javaType = metaResultType.getSetterType(property); + javaType = metaResultType.getGetterType(property); } catch (Exception e) { // ignore, following null check statement will deal with the situation } diff --git a/src/main/java/org/apache/ibatis/mapping/ResultMap.java b/src/main/java/org/apache/ibatis/mapping/ResultMap.java index e0b46f67e0e..341c97fc5b1 100644 --- a/src/main/java/org/apache/ibatis/mapping/ResultMap.java +++ b/src/main/java/org/apache/ibatis/mapping/ResultMap.java @@ -128,8 +128,8 @@ public ResultMap build() { final List actualArgNames = argNamesOfMatchingConstructor(constructorArgNames); if (actualArgNames == null) { throw new BuilderException("Error in result map '" + resultMap.id + "'. Failed to find a constructor in '" - + resultMap.getType().getName() + "' by arg names " + constructorArgNames - + ". There might be more info in debug log."); + + resultMap.getType().getName() + "' with arg names " + constructorArgNames + + ". Note that 'javaType' is required when there is no readable property with the same name ('name' is optional, BTW). There might be more info in debug log."); } resultMap.constructorResultMappings.sort((o1, o2) -> { int paramIdx1 = actualArgNames.indexOf(o1.getProperty()); diff --git a/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeMapper.java b/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeMapper.java index 41b4d558f01..df4f14f316a 100644 --- a/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeMapper.java +++ b/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeMapper.java @@ -32,6 +32,12 @@ public interface RecordTypeMapper { @Select("select val, id, url from prop where id = #{id}") Property selectProperty(int id); + @Arg(name = "id", column = "id", id = true) + @Arg(name = "value", column = "val") + @Arg(name = "URL", column = "url") + @Select("select val, id, url from prop where id = #{id}") + Property selectPropertyNoJavaType(int id); + @Insert("insert into prop (id, val, url) values (#{id}, #{value}, #{URL})") int insertProperty(Property property); diff --git a/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeTest.java b/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeTest.java index dbcf5b8310d..2582e3048bd 100644 --- a/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeTest.java +++ b/src/test/java/org/apache/ibatis/submitted/record_type/RecordTypeTest.java @@ -52,6 +52,16 @@ void testSelectRecord() { } } + @Test + void shouldResolveConstructorArgType() { + try (SqlSession sqlSession = sqlSessionFactory.openSession()) { + RecordTypeMapper mapper = sqlSession.getMapper(RecordTypeMapper.class); + Property prop = mapper.selectPropertyNoJavaType(1); + assertEquals("Val1!", prop.value()); + assertEquals("https://www.google.com", prop.URL()); + } + } + @Test void testSelectRecordAutomapping() { try (SqlSession sqlSession = sqlSessionFactory.openSession()) {