' 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>


Posted by '김용환'

댓글을 달아 주세요