javamybatistypehandler

MyBatis custom TypeHandler not executed when put in <result> tag


I have a <resultMap> with custom typeHandler for one of the result properties:

<resultMap id="foo" type="hashmap">
    ... 
    <result property="SERVICES_XML" javaType="string" jdbcType="CLOB" typeHandler="com.foo.bar.OracleClobTypeHandler" />
    ...
</resultMap>

No matter which property I attach my handler to (I mean this is not CLOB-specific issue, tried with VARCHAR, too), the handler won't get called when I fetch results from database.

I have set breakpoints in all methods of my custom handler:

public class OracleClobTypeHandler implements TypeHandler<String> {

  @Override
  public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
    log.debug("setParameter called");   <================ BREAKPOINT HERE
  }

  @Override
  public String getResult(ResultSet rs, String columnName)
        throws SQLException {
    log.debug("getResult 2 called");    <================ BREAKPOINT HERE
    return "";
  }

  @Override
  public String getResult(ResultSet rs, int columnIndex)
        throws SQLException {
    log.debug("getResult 2 called");    <================ BREAKPOINT HERE
    return "";
  }

  @Override
  public String getResult(CallableStatement cs, int columnIndex)
        throws SQLException {
    log.debug("getResult 3 called");    <================ BREAKPOINT HERE
    return "";
  }
}

Clearly none of the above methods is executed.

I've tried to put <typeHandler javaType="java.lang.String" jdbcType="CLOB" handler="com.foo.bar.OracleClobTypeHandler"/> in myBatis <configuration>, but this didn't work too.
Neither did anything else, including extending TypeHandler<Object> and so on.

What am I doing wrong?


Solution

  • After digging a long, long while I have finally found the answer.

    This seems to be a bug in myBatis.

    In order to get your handlers to work for <result> elements, you have to specify column attribute explicitly even if property attribute already matches column name and field name in bean.
    In my case, it looks like this:

     <result property="SERVICES_XML" column="SERVICES_XML" javaType="string" jdbcType="CLOB" typeHandler="com.foo.bar.OracleClobTypeHandler" />
    

    Note that the above change will also cause handlers defined in <configuration> tag to work, so inline typeHandler may be no longer necessary - that was my case. I ended up with:

    <configuration>
      <typeHandlers>
        <typeHandler javaType="java.lang.String" jdbcType="CLOB" handler="com.foo.bar.OracleClobTypeHandler"/>        
      </typeHandlers>
    </configuration>
    

    and

    <result property="SERVICES_XML" column="SERVICES_XML" javaType="string" jdbcType="CLOB" />