Skip to content

Commit 79f2c1d

Browse files
authored
Merge pull request #1693 from kazuki43zoo/gh-1551
Change to refers useColumnLabel at UnknownTypeHandler
2 parents 91dcd4e + c524574 commit 79f2c1d

File tree

12 files changed

+479
-13
lines changed

12 files changed

+479
-13
lines changed

src/main/java/org/apache/ibatis/session/Configuration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public class Configuration {
146146

147147
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
148148
protected final InterceptorChain interceptorChain = new InterceptorChain();
149-
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
149+
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry(this);
150150
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
151151
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
152152

src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import org.apache.ibatis.binding.MapperMethod.ParamMap;
4747
import org.apache.ibatis.io.ResolverUtil;
4848
import org.apache.ibatis.io.Resources;
49+
import org.apache.ibatis.session.Configuration;
4950

5051
/**
5152
* @author Clinton Begin
@@ -55,14 +56,29 @@ public final class TypeHandlerRegistry {
5556

5657
private final Map<JdbcType, TypeHandler<?>> jdbcTypeHandlerMap = new EnumMap<>(JdbcType.class);
5758
private final Map<Type, Map<JdbcType, TypeHandler<?>>> typeHandlerMap = new ConcurrentHashMap<>();
58-
private final TypeHandler<Object> unknownTypeHandler = new UnknownTypeHandler(this);
59+
private final TypeHandler<Object> unknownTypeHandler;
5960
private final Map<Class<?>, TypeHandler<?>> allTypeHandlersMap = new HashMap<>();
6061

6162
private static final Map<JdbcType, TypeHandler<?>> NULL_TYPE_HANDLER_MAP = Collections.emptyMap();
6263

6364
private Class<? extends TypeHandler> defaultEnumTypeHandler = EnumTypeHandler.class;
6465

66+
/**
67+
* The default constructor.
68+
*/
6569
public TypeHandlerRegistry() {
70+
this(new Configuration());
71+
}
72+
73+
/**
74+
* The constructor that pass the MyBatis configuration.
75+
*
76+
* @param configuration a MyBatis configuration
77+
* @since 3.5.4
78+
*/
79+
public TypeHandlerRegistry(Configuration configuration) {
80+
this.unknownTypeHandler = new UnknownTypeHandler(configuration);
81+
6682
register(Boolean.class, new BooleanTypeHandler());
6783
register(boolean.class, new BooleanTypeHandler());
6884
register(JdbcType.BOOLEAN, new BooleanTypeHandler());

src/main/java/org/apache/ibatis/type/UnknownTypeHandler.java

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,42 @@
2222
import java.sql.SQLException;
2323
import java.util.HashMap;
2424
import java.util.Map;
25+
import java.util.function.Supplier;
2526

2627
import org.apache.ibatis.io.Resources;
28+
import org.apache.ibatis.session.Configuration;
2729

2830
/**
2931
* @author Clinton Begin
3032
*/
3133
public class UnknownTypeHandler extends BaseTypeHandler<Object> {
3234

3335
private static final ObjectTypeHandler OBJECT_TYPE_HANDLER = new ObjectTypeHandler();
36+
// TODO Rename to 'configuration' after removing the 'configuration' property(deprecated property) on parent class
37+
private final Configuration config;
38+
private final Supplier<TypeHandlerRegistry> typeHandlerRegistrySupplier;
3439

35-
private TypeHandlerRegistry typeHandlerRegistry;
40+
/**
41+
* The constructor that pass a MyBatis configuration.
42+
*
43+
* @param configuration a MyBatis configuration
44+
* @since 3.5.4
45+
*/
46+
public UnknownTypeHandler(Configuration configuration) {
47+
this.config = configuration;
48+
this.typeHandlerRegistrySupplier = configuration::getTypeHandlerRegistry;
49+
}
3650

51+
/**
52+
* The constructor that pass the type handler registry.
53+
*
54+
* @param typeHandlerRegistry a type handler registry
55+
* @deprecated Since 3.5.4, please use the {@link #UnknownTypeHandler(Configuration)}.
56+
*/
57+
@Deprecated
3758
public UnknownTypeHandler(TypeHandlerRegistry typeHandlerRegistry) {
38-
this.typeHandlerRegistry = typeHandlerRegistry;
59+
this.config = new Configuration();
60+
this.typeHandlerRegistrySupplier = () -> typeHandlerRegistry;
3961
}
4062

4163
@Override
@@ -73,7 +95,7 @@ private TypeHandler<?> resolveTypeHandler(Object parameter, JdbcType jdbcType) {
7395
if (parameter == null) {
7496
handler = OBJECT_TYPE_HANDLER;
7597
} else {
76-
handler = typeHandlerRegistry.getTypeHandler(parameter.getClass(), jdbcType);
98+
handler = typeHandlerRegistrySupplier.get().getTypeHandler(parameter.getClass(), jdbcType);
7799
// check if handler is null (issue #270)
78100
if (handler == null || handler instanceof UnknownTypeHandler) {
79101
handler = OBJECT_TYPE_HANDLER;
@@ -88,8 +110,9 @@ private TypeHandler<?> resolveTypeHandler(ResultSet rs, String column) {
88110
columnIndexLookup = new HashMap<>();
89111
ResultSetMetaData rsmd = rs.getMetaData();
90112
int count = rsmd.getColumnCount();
113+
boolean useColumnLabel = config.isUseColumnLabel();
91114
for (int i = 1; i <= count; i++) {
92-
String name = rsmd.getColumnName(i);
115+
String name = useColumnLabel ? rsmd.getColumnLabel(i) : rsmd.getColumnName(i);
93116
columnIndexLookup.put(name,i);
94117
}
95118
Integer columnIndex = columnIndexLookup.get(column);
@@ -111,11 +134,11 @@ private TypeHandler<?> resolveTypeHandler(ResultSetMetaData rsmd, Integer column
111134
JdbcType jdbcType = safeGetJdbcTypeForColumn(rsmd, columnIndex);
112135
Class<?> javaType = safeGetClassForColumn(rsmd, columnIndex);
113136
if (javaType != null && jdbcType != null) {
114-
handler = typeHandlerRegistry.getTypeHandler(javaType, jdbcType);
137+
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType, jdbcType);
115138
} else if (javaType != null) {
116-
handler = typeHandlerRegistry.getTypeHandler(javaType);
139+
handler = typeHandlerRegistrySupplier.get().getTypeHandler(javaType);
117140
} else if (jdbcType != null) {
118-
handler = typeHandlerRegistry.getTypeHandler(jdbcType);
141+
handler = typeHandlerRegistrySupplier.get().getTypeHandler(jdbcType);
119142
}
120143
return handler;
121144
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
--
2+
-- Copyright 2009-2019 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+
17+
drop table product_sku if exists;
18+
drop table product_info if exists;
19+
drop table product if exists;
20+
21+
create table product (
22+
id varchar(32) not null,
23+
code varchar(80) not null,
24+
name varchar(240) not null
25+
);
26+
27+
create table product_sku (
28+
id varchar(32) not null,
29+
product_id varchar(32) not null,
30+
code varchar(80) not null,
31+
color varchar(40),
32+
size varchar(40)
33+
);
34+
35+
create table product_info (
36+
id int not null,
37+
product_id varchar(32) not null,
38+
other_info varchar(240)
39+
);
40+
41+
insert into product(id, code, name) values('10000000000000000000000000000001', 'P001', 'Product 001');
42+
insert into product_sku(id ,product_id, code, color, size) values('20000000000000000000000000000001', '10000000000000000000000000000001', 'S001', 'red', '80');
43+
insert into product_sku(id ,product_id, code, color, size) values('20000000000000000000000000000002', '10000000000000000000000000000001', 'S001', 'blue', '10');
44+
insert into product_info(id, product_id, other_info) values(1, '10000000000000000000000000000001', 'Sale 50% Off');
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* Copyright 2009-2019 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.nestedresulthandler_gh1551;
17+
18+
import java.io.Reader;
19+
20+
import org.apache.ibatis.BaseDataTest;
21+
import org.apache.ibatis.exceptions.PersistenceException;
22+
import org.apache.ibatis.io.Resources;
23+
import org.apache.ibatis.session.SqlSession;
24+
import org.apache.ibatis.session.SqlSessionFactory;
25+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
26+
import org.junit.jupiter.api.Assertions;
27+
import org.junit.jupiter.api.BeforeAll;
28+
import org.junit.jupiter.api.Test;
29+
30+
class NestedResultHandlerGh1551Test {
31+
private static SqlSessionFactory sqlSessionFactory;
32+
33+
@BeforeAll
34+
static void setUp() throws Exception {
35+
// create a SqlSessionFactory
36+
try (Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/nestedresulthandler_gh1551/mybatis-config.xml")) {
37+
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
38+
}
39+
40+
// populate in-memory database
41+
BaseDataTest.runScript(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(),
42+
"org/apache/ibatis/submitted/nestedresulthandler_gh1551/CreateDB.sql");
43+
}
44+
45+
@Test
46+
void useColumnLabelIsTrue() {
47+
sqlSessionFactory.getConfiguration().setUseColumnLabel(true);
48+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
49+
ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
50+
51+
ProductResp productResp = mapper.selectAllInfo("P001").get(0);
52+
53+
Assertions.assertEquals("10000000000000000000000000000001", productResp.getId());
54+
Assertions.assertEquals("P001", productResp.getCode());
55+
Assertions.assertEquals("Product 001", productResp.getName());
56+
57+
Assertions.assertEquals(1, productResp.getProductInfo().getId());
58+
Assertions.assertEquals("10000000000000000000000000000001", productResp.getProductInfo().getProductId());
59+
Assertions.assertEquals("Sale 50% Off", productResp.getProductInfo().getOtherInfo());
60+
61+
Assertions.assertEquals("20000000000000000000000000000001", productResp.getSkus().get(0).getId());
62+
Assertions.assertEquals("10000000000000000000000000000001", productResp.getSkus().get(0).getProductId());
63+
Assertions.assertEquals("red", productResp.getSkus().get(0).getColor());
64+
Assertions.assertEquals("80", productResp.getSkus().get(0).getSize());
65+
Assertions.assertEquals("20000000000000000000000000000002", productResp.getSkus().get(1).getId());
66+
Assertions.assertEquals("10000000000000000000000000000001", productResp.getSkus().get(1).getProductId());
67+
Assertions.assertEquals("blue", productResp.getSkus().get(1).getColor());
68+
Assertions.assertEquals("10", productResp.getSkus().get(1).getSize());
69+
}
70+
}
71+
72+
@Test
73+
void useColumnLabelIsFalse() {
74+
sqlSessionFactory.getConfiguration().setUseColumnLabel(false);
75+
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
76+
ProductMapper mapper = sqlSession.getMapper(ProductMapper.class);
77+
PersistenceException exception = Assertions.assertThrows(PersistenceException.class, () -> mapper.selectAllInfo("P001"));
78+
Assertions.assertTrue(exception.getMessage().contains("Error attempting to get column 'ID' from result set. Cause: java.sql.SQLSyntaxErrorException: incompatible data type in conversion: from SQL type VARCHAR to java.lang.Integer, value: 10000000000000000000000000000001"));
79+
}
80+
}
81+
82+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/**
2+
* Copyright 2009-2019 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.nestedresulthandler_gh1551;
17+
18+
public class ProductInfo {
19+
20+
private Long id;
21+
private String productId;
22+
private String otherInfo;
23+
24+
public Long getId() {
25+
return id;
26+
}
27+
28+
public void setId(Long id) {
29+
this.id = id;
30+
}
31+
32+
public String getProductId() {
33+
return productId;
34+
}
35+
36+
public void setProductId(String productId) {
37+
this.productId = productId;
38+
}
39+
40+
public String getOtherInfo() {
41+
return otherInfo;
42+
}
43+
44+
public void setOtherInfo(String otherInfo) {
45+
this.otherInfo = otherInfo;
46+
}
47+
48+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/**
2+
* Copyright 2009-2019 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.nestedresulthandler_gh1551;
17+
18+
import java.util.List;
19+
20+
import org.apache.ibatis.annotations.Param;
21+
22+
public interface ProductMapper {
23+
List<ProductResp> selectAllInfo(@Param("code") String code);
24+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Copyright 2009-2019 the original author or authors.
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
18+
-->
19+
<!DOCTYPE mapper
20+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
21+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
22+
23+
<mapper namespace="org.apache.ibatis.submitted.nestedresulthandler_gh1551.ProductMapper">
24+
<resultMap id="AllInfoResultMap" type="ProductResp">
25+
<id column="ID" property="id"/>
26+
<result column="NAME" property="name"/>
27+
<result column="CODE" property="code"/>
28+
<result column="INFO_ID" property="productInfo.id"/>
29+
<result column="ID" property="productInfo.productId"/>
30+
<result column="INFO_OTHER_INFO" property="productInfo.otherInfo"/>
31+
<collection property="skus" select="selectSkuByPk1" column="ID"/>
32+
</resultMap>
33+
<select id="selectAllInfo" resultMap="AllInfoResultMap">
34+
select
35+
p.id,
36+
p.code,
37+
p.name,
38+
i.id as INFO_ID,
39+
i.other_info as INFO_OTHER_INFO
40+
from
41+
product p
42+
left join product_info i on p.id = i.product_id
43+
where p.code = #{code}
44+
</select>
45+
<resultMap id="SkuResultMap" type="ProductSku">
46+
<id column="ID" property="id"/>
47+
<result column="PRODUCT_ID" property="productId"/>
48+
<result column="COLOR" property="color"/>
49+
<result column="SIZE" property="size"/>
50+
</resultMap>
51+
<select id="selectSkuByPk1" resultMap="SkuResultMap">
52+
select * from product_sku where product_id = #{id} ORDER BY id
53+
</select>
54+
</mapper>

0 commit comments

Comments
 (0)