[mybatis]' select * .. query시, binding하는 java domain object 의 필드와 매핑되지 못할때 어떤 일이 벌어지는가?
general java 2014. 4. 28. 20:16' select * .. query시, binding하는 java domain object의 필드와 매핑되지 못할 때 어떤 일이 벌어지는가?
Table ABC 에 다음과 같은 데이터가 있.
id | surName | name
0 | kim | yonghwan
1 | lee | junghwan
2 | yang | jungpil
즉, "select * from ABC" 를 mybatis에서 호출할때 resultType 을 Property 로 저장토록 했다.
Property는 id, name 이렇게 있는 경우라면. 어떻게 될 것 인가? 에 대한 문제이다.
경험상, 문제없이 동작할 것 같다는 느낌이 온다만, 과연 코드로 어떻게 되어 있는지 체크해본다.
------------------------------------------------------------------------
<org.apache.ibatis.executor.resultset.DefaultResultSetHandler 클래스>
private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
final List<String> unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);
boolean foundValues = false;
for (String columnName : unmappedColumnNames) {
String propertyName = columnName;
if (columnPrefix != null && columnPrefix.length() > 0) {
// When columnPrefix is specified,
// ignore columns without the prefix.
if (columnName.startsWith(columnPrefix)) {
propertyName = columnName.substring(columnPrefix.length());
} else {
continue;
}
}
final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());
//(1)
if (property != null && metaObject.hasSetter(property)) {
final Class<?> propertyType = metaObject.getSetterType(property);
if (typeHandlerRegistry.hasTypeHandler(propertyType)) {
final TypeHandler<?> typeHandler = rsw.getTypeHandler(propertyType, columnName);
final Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
if (value != null || configuration.isCallSettersOnNulls()) { // issue #377, call setter on nulls
if (value != null || !propertyType.isPrimitive()) {
metaObject.setValue(property, value);
}
foundValues = true;
}
}
}
}
// (2)
return foundValues;
}
(1) table query로부터 읽을 때 column name이 존재하면 Java domain object의 setter를 호출하여 value를 매핑한다. (자세히 보면 타입체크와 설정 관련 정보가 연관되어 있지만 패스한다.)
(2) 그러나 만약 column name 이 존재하지 않으면, 그냥 넘어간다. 저장하지 않게 된다.
따라서 select * 하는 코드가 안전할 수 있다. 그러나, 좀 더 detail 개발(적확히는 유지보수관점) 을 위해서는 select 문에 필드를 명시적으로 추가하는 것이 좋은 듯 하다. java domain object와 매핑 자체가 편리하다.
참고로 위 메소드에서 연관된 정보를 소개한다.
1) configuration.isCallSettersOnNulls()
과거에는 null 일 때는 호출하지 않았는데, 반드시 초기화가 필요한 부분이 존재 해서 설정할 수 있도록 지정할 수 있게 되어 있다.
http://mybatis.github.io/mybatis-3/ko/configuration.html
Specifies if setters or map's put method will be called when a retrieved value is null. It is useful when you rely on Map.keySet() or null value initialization. Note primitives such as (int,boolean,etc.) will not be set to null.
<settings> <setting name="callSettersOnNulls" value="true"/>
<settings>
2) configuration.isMapUnderscoreToCamelCase()
db property가 underbar를 많이 쓴다. 이 때 camel case로 바꿔주는 작업을 할지를 결정할 수 있다.
즉, car_maker 라는 property는 carMaker 라는 java domain object로 만들 수 있다.
http://mybatis.github.io/mybatis-3/configuration.html#settings
Enables automatic mapping from classic database column names A_COLUMN to camel case classic Java property names aColumn.
<settings> <setting name="mapUnderscoreToCamelCase" value="true"/>
<settings>