Skip to content

Commit 949ccd3

Browse files
committed
Avoid corner case NPEs when mapping results
1 parent 0172c5b commit 949ccd3

File tree

4 files changed

+53
-1
lines changed

4 files changed

+53
-1
lines changed

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,10 @@ private Object getPropertyMappingValue(ResultSetWrapper rsw, MetaObject metaResu
600600
final String property = propertyMapping.getProperty();
601601
final Type javaType = property == null ? null : metaResultObject.getGenericSetterType(property).getKey();
602602
typeHandler = rsw.getTypeHandler(javaType, column);
603+
if (typeHandler == null) {
604+
throw new ExecutorException(
605+
"No type handler found for '" + javaType + "' and JDBC type '" + rsw.getJdbcType(column) + "'");
606+
}
603607
}
604608
return typeHandler.getResult(rs, column);
605609
}
@@ -1540,6 +1544,9 @@ private void createRowKeyForMappedProperties(ResultMap resultMap, ResultSetWrapp
15401544
if (th == null) {
15411545
th = typeHandlerRegistry.getTypeHandler(rsw.getJdbcType(column));
15421546
}
1547+
if (th == null) {
1548+
th = ObjectTypeHandler.INSTANCE;
1549+
}
15431550
final Object value = th.getResult(rsw.getResultSet(), column);
15441551
if (value != null || configuration.isReturnInstanceForEmptyRow()) {
15451552
cacheKey.update(column);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.ibatis.annotations.Options;
2424
import org.apache.ibatis.annotations.Param;
2525
import org.apache.ibatis.annotations.Result;
26+
import org.apache.ibatis.annotations.ResultMap;
2627
import org.apache.ibatis.annotations.Results;
2728
import org.apache.ibatis.annotations.Select;
2829
import org.apache.ibatis.submitted.typehandler.Product.ProductId;
@@ -70,4 +71,13 @@ public interface Mapper {
7071

7172
@Insert({ "insert into vague (vague) values (#{bean})" })
7273
int insertVague(@Param("bean") VagueBean bean);
74+
75+
@Result(property = "id", column = "id")
76+
@Result(property = "vague", column = "vague")
77+
@Select("select * from vague where id = #{id}")
78+
VagueBean selectVague(Integer id);
79+
80+
@ResultMap("vagueRM")
81+
@Select("select * from vague where id = #{id}")
82+
VagueBean selectVagueNested(Integer id);
7383
}

src/test/java/org/apache/ibatis/submitted/typehandler/TypeHandlerTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.assertj.core.api.Assertions.assertThat;
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertNotNull;
21+
import static org.junit.jupiter.api.Assertions.assertTrue;
2122
import static org.junit.jupiter.api.Assertions.fail;
2223

2324
import java.io.Reader;
@@ -29,6 +30,7 @@
2930
import java.util.Map;
3031

3132
import org.apache.ibatis.BaseDataTest;
33+
import org.apache.ibatis.executor.ExecutorException;
3234
import org.apache.ibatis.io.Resources;
3335
import org.apache.ibatis.session.SqlSession;
3436
import org.apache.ibatis.session.SqlSessionFactory;
@@ -218,4 +220,28 @@ void shouldThrowProperExceptionWhenNoHandlerFoundForParam() {
218220
}
219221
}
220222

223+
@Test
224+
void shouldThrowProperExceptionWhenNoHandlerFoundForResult() {
225+
addMapper();
226+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
227+
Mapper mapper = sqlSession.getMapper(Mapper.class);
228+
mapper.selectVague(1);
229+
fail("Should throw exception");
230+
} catch (Exception e) {
231+
assertThat(e).cause().isExactlyInstanceOf(ExecutorException.class)
232+
.hasMessage("No type handler found for 'java.util.Set<?>' and JDBC type 'OTHER'");
233+
}
234+
}
235+
236+
@Test
237+
void shouldCreateRowKeyNotThrowNpe() {
238+
addMapper();
239+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
240+
Mapper mapper = sqlSession.getMapper(Mapper.class);
241+
VagueBean bean = mapper.selectVagueNested(1);
242+
assertEquals(1, bean.getId());
243+
assertTrue(bean.getVague().isEmpty());
244+
}
245+
}
246+
221247
}

src/test/resources/org/apache/ibatis/submitted/typehandler/Mapper.xml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright 2009-2022 the original author or authors.
4+
Copyright 2009-2025 the original author or authors.
55
66
Licensed under the Apache License, Version 2.0 (the "License");
77
you may not use this file except in compliance with the License.
@@ -32,4 +32,13 @@
3232
select * from product where name = #{name}
3333
</select>
3434

35+
<resultMap
36+
type="org.apache.ibatis.submitted.typehandler.VagueBean"
37+
id="vagueRM">
38+
<result property="id" column="id" />
39+
<collection property="vague" ofType="string"
40+
javaType="java.util.HashSet">
41+
<result column="vague" />
42+
</collection>
43+
</resultMap>
3544
</mapper>

0 commit comments

Comments
 (0)