iBATIS 실행 시 특정 property에 대한 typeHandler를 찾지 못한다는 예외가 발생할때 sqlMapConfig에서 typeHandler 의 jdbcType를 확인해본다.

아래와 비슷하게 자바빈 클래스의 Alias명인 "key" 에 대해서 typeHandler를 찾을 수 없다는 예외 메세지가 던져질 때가 있다.

Caused by: com.ibatis.common.jdbc.exception.NestedSQLException:  
--- The error occurred in properties/User.xml. 
--- The error occurred while applying a result map. 
--- Check the Users.RM_User. 
--- Check the result mapping for the 'key' property. 
--- Cause: com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'key' to the column 'userId'.  One or both of the types, or the combination of types is not supported.
    at com.ibatis.sqlmap.engine.mapping.statement.MappedStatement.executeQueryWithCallback(MappedStatement.java:204)
........
    ... 17 more
Caused by: com.ibatis.sqlmap.client.SqlMapException: No type handler could be found to map the property 'key' to the column 'userId'.  One or both of the types, or the combination of types is not supported.
    at com.ibatis.sqlmap.engine.mapping.result.ResultMap.getPrimitiveResultMappingValue(ResultMap.java:613)

다음과 같이 jdbcType의 "INTEGER"로 지정해서 특정 자바빈 클래스와 jdbcType을 변환해줄 typeHandler를 등록할 때

<sqlMapConfig>
    ...
    <typeHandler jdbcType="INTEGER" javaType="SpecificJavaBean.class"... />
    ...
</sqlMapConfig>

아래와같이 <parameter .../> 에서 jdbcType을 "INTEGER"로 맞추어줘야 한다.(대소문자 구별해야한다)

<sqlMap>
    ...
    <parameterMap id="PM_Tx" .... >
        <parameter property="id" javaType="SpecificJavaBean.class" jdbcType="INTEGER"/>
    </parameterMap>
    ....
</sqlMap>

위의 설정을 통해서 쿼리를 조립할 때 SpecificJavaBean 클래스를 "INTEGER"값으로 변환하고 쿼리를 실행한 후 resultset을 얻어온 후 해당 column의 값을 읽어서 곧바로 SpecificBean.class 타입의 인스턴스를 생성한다.

jdbcType의 값을 typeHandler에서 지정한 "INTEGER"가 아닌 다른 형태(Integer, integer 등)로 설정했을때 나중에 쿼리가 생성, 실행된후 자바 인스턴스를 만들거나 반환값을 넘길때 관련 프로퍼티를 제대로 읽어들이지 못하는 문제가 발생한다.(만일 쿼리가 또다른 쿼리를 내포할 경우에는 에러 메세지조차 제대로 나오지 않는다.)

소스코드를 보면 "/sqlMap/parameterMap/parameter" element가 SqlMapParser.java의 Line 166에 등장하는 Nodelet 인스턴스에 의해서 해석된다.

이 때

Line 144 : TypeHandlerFactory.getTypeHandler(Class, String)

에서 문제가 발생한다.

TypeHandlerFactory에는 다음의 두가지 HashMap 인스턴스가 중요한 역할을 한다.

java.util.Map typeHandlerMap;
java.util.Map jdbcHandlerMap

위의 typehandler 설정 xml 코드가 해석되면 alias인 "key"를 SpecificJavaBean.class로 해석하고 jdbcType="INTEGER" 의 값을 추출해서 다음과 같이 등록한다.

jdbcHandlerMap.put("INTEGER", userDefinedTypeHandler);
typeHandlerMap.put(SpecificJavaBean.class, jdbcHandlerMap);

만일 <parameter...> element에서 jdbcType 프로퍼티를 "INTEGER"가 아닌 다른 형태(Integer, integer등)로 입력하면

<sqlMap>
    ...
    <parameterMap id="PM_Tx" .... >
        <parameter property="id" javaType="SpecificJavaBean.class" jdbcType="Integer"/>
    </parameterMap>
    ....
</sqlMap>

최종적으로 typeHandler를 찾지 못하고 null로 설정된다."PM_Tx" 를 파라미터맵으로 사용하는 관련 쿼리를 조합할때 typeHandler가 null이므로 NullPointerException이 던져진다.

"Integer"로 등록된 jdbcHandlerMap은 없다.


단순 쿼리일 경우에는 에러메세지가 제대로 나오지만 <parameter ... select="..." /> 나 <parameter ... resultMap=".."/> 과 같이 다중 쿼리로 구성되었을때 포함된 쿼리에서 위와같은 문제가 발생하면 에러메세지조차 나오지 않아서 문제를 해결하는데 애를 먹는다.

이런 문제를 피하는 가장 간단한 원칙은 모든 iBATIS 설정 파일에서 jdbcType은 항상 대문자로 입력하는 것이다.

'Dev > iBATIS' 카테고리의 다른 글

iBATIS 2.x vs iBATIS 3.0  (0) 2010.04.30
iBatis Inline parameter map Exception 다루기  (0) 2008.10.26
iBATIS Inline parameter Map  (3) 2008.09.10
Posted by yeori
,