Michał Rybak Michał Rybak - 1 month ago 16
Java Question

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?

Answer

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" />