Mybatis3的资源优先,官方除了用户指南之外,没有别的资料。源码中的单元测试也没有完整的覆盖业务。
遇到这样的问题,在一个JavaBean中,有一个Map属性,希望这个属性可以映射到Table中的一列。
public class TaskEntity implements Task, Serializable, PersistentObject {
protected Map<String, String> properties = new HashMap<String, String>();
public String getProperty(String key) {
return properties.get(key);
}
public void setProperty(String key, String value) {
properties.put(key, value);
}
}
希望properties可以映射 column="EXECUTION_ID_"。
很明显,需要实现一个TypeHandler,将这个实现命名为 MapTypeHandler
public class MapTypeHandler implements TypeHandler<Map<String, String>> {
private static JsonBinder binder = JsonBinder.buildNonDefaultBinder();
@Override
public Map<String, String> getResult(ResultSet rs, String columnName) throws SQLException {
String value = rs.getString(columnName);
return binder.fromJson(value, Map.class);
}
@Override
public Map<String, String> getResult(CallableStatement cs, int columnIndex) throws SQLException {
String value = cs.getString(columnIndex);
return binder.fromJson(value, Map.class);
}
@Override
public void setParameter(PreparedStatement ps, int i, Map<String, String> parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
ps.setNull(i, Types.VARCHAR);
} else {
ps.setString(i, binder.toJson(parameter));
}
}
}
setParameter是在Jdbc insert,update会调用到的方法。getResult是在Jdbc select会调用到的方法。
MapTypeHandler中的逻辑很简单,就是用json将Map进行序列化和反序列化,将json格式的内容存储在 column="EXECUTION_ID_"中。
我们有了MapTypeHandler之后,怎么让他在转换类型时生效呢?
答案就是配置类型映射。配置javaType="java.util.Map"与jdbcType="VARCHAR"之间的转换,使用MapTypeHandler。这个配置要写入mappings.xml中。
<configuration> <settings> <setting name="lazyLoadingEnabled" value="false" /> </settings> <typeHandlers> <typeHandler handler="com.apusic.bpm.engine.persistence.MapTypeHandler" javaType="java.util.Map" jdbcType="VARCHAR" /> </typeHandlers> <mappers> <mapper resource="com/apusic/bpm/db/mapping/entity/Task.xml" /> </mappers> </configuration>
最后一步就是配置Entity具体的信息,Task.xml中Insert,Update,resultMap中,只要指定property="properties" column="EXECUTION_ID_" javaType="java.util.Map" jdbcType="VARCHAR",系统就会调用MapTypeHandler进行类型映射。
<mapper namespace="com.apusic.bpm.engine.task.impl.TaskEntity"> <!-- TASK INSERT --> <insert id="insertTask" parameterType="com.apusic.bpm.engine.task.impl.TaskEntity"> insert into ACT_RU_TASK (EXECUTION_ID_) values ( #{properties, jdbcType=VARCHAR, javaType=java.util.Map} ) </insert> <update id="updateTask" parameterType="com.apusic.bpm.engine.task.impl.TaskEntity"> update ACT_RU_TASK <set> EXECUTION_ID_ = #{properties, jdbcType=VARCHAR, javaType=java.util.Map} </set> </update> <resultMap id="taskResultMap" type="com.apusic.bpm.engine.task.impl.TaskEntity"> <result property="properties" column="EXECUTION_ID_" javaType="java.util.Map" jdbcType="VARCHAR"/> </resultMap></mapper>