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>