Mybatis混合对象单表存储

      先吐槽几句,Mybatis的官方文档就只有那一篇User Guide,加上源码覆盖的例子和单元测试,里面覆盖的知识点最多只有7成,剩下的3成功能如果需要用到,那就悲剧了,需选择了看源码,多花一点时间,记得得到巩固,何乐而不为呢。

      我的实体对象如下所示。

      public class ProcessDefinition {

	private String id;
	private String key;
	private String name;
	private long version;
	private String description;
	private String language;
	private ProcessDefinitionResourceMapping mapping;
	private ProcessDefinitionState state;

    public ProcessDefinition(String id, String key, String name, Long version, String description,
                             ProcessDefinitionResourceMapping mapping) {
        super();
        this.id = id;
        this.key = key;
        this.name = name;
        this.version = version;
        this.description = description;
        // FIXME 现在只支持bpmn
        this.language = "bpmn";
        this.mapping = mapping;
        this.state = ProcessDefinitionState.UNPUBLISH;
    }
}

public class ProcessDefinitionResourceMapping {
    
	private String processDefinitionPath;
	private Set<String> resourcePaths = new HashSet<String>();
	
	public ProcessDefinitionResourceMapping(String processDefinitionPath, Set<String> resourcePaths) {
        super();
        this.processDefinitionPath = processDefinitionPath;
        this.resourcePaths = resourcePaths;
    }
}

  上面的符合对象,想要存储在一个数据库表中。而且映射和数据参数传递都是通构造方法。怎么实现insert和select呢?

  • insert

经过大胆的猜测,居然给我猜中了,可以通过 . 调用引用对象的属性,这里没有跟进源码去看到底使用反射,还是get方法。

per namespace="com.apusic.bpm.engine.definition.ProcessDefinition">
	<insert id="insertProcessDefinition" parameterType="com.apusic.bpm.engine.definition.ProcessDefinition">
		insert into ABPM_RE_PROCESS_DEFINITION (ID_, KEY_, NAME_, VERSION_, DESCRIPTION_, LANGUATE_, PROCESS_DEFINITION_PATH_, RESOURCE_PATHS_, PROCESS_DEFINITION_STATE_)
		values (#{id,jdbcType=VARCHAR},
		#{key, jdbcType=VARCHAR},
		#{name, jdbcType=VARCHAR},
		1,
		#{description, jdbcType=VARCHAR},
		#{language, jdbcType=VARCHAR},
		#{mapping.processDefinitionPath, jdbcType=VARCHAR},
		#{mapping.resourcePaths, jdbcType=VARCHAR, javaType=java.util.Set},
		#{state, jdbcType=VARCHAR, javaType=com.apusic.bpm.engine.definition.ProcessDefinitionState})
	</insert>

  输入的属性映射,在DefaultParameterHandler中进行逻辑处理,感兴趣的童鞋可以跟一下。

  • select

比较痛苦的是查询,折腾了好久,通过如下的设置可以完成功能。

<resultMap id="processDefinitionResultMap"
		type="com.apusic.bpm.engine.definition.ProcessDefinition">
		<constructor>
			<idArg column="ID_" jdbcType="VARCHAR" javaType="java.lang.String" />
			<arg column="KEY_" jdbcType="VARCHAR" javaType="java.lang.String" />
			<arg column="NAME_" jdbcType="VARCHAR" javaType="java.lang.String" />
			<arg column="VERSION_" jdbcType="INTEGER" javaType="java.lang.Long" />
			<arg column="DESCRIPTION_" jdbcType="VARCHAR" javaType="java.lang.String" />
			<arg javaType="com.apusic.bpm.engine.definition.ProcessDefinitionResourceMapping" resultMap="resourceMappingResultMap" />
		</constructor>
	</resultMap>
	
	<resultMap id="resourceMappingResultMap"
		type="com.apusic.bpm.engine.definition.ProcessDefinitionResourceMapping">
		<constructor>
			<arg column="PROCESS_DEFINITION_PATH_" jdbcType="VARCHAR" javaType="java.lang.String"/>
			<arg column="RESOURCE_PATHS_" jdbcType="VARCHAR" javaType="java.util.Set" />
		</constructor>
	</resultMap>

Mybatis通过NestedResultSetHandler,起到一个构造和映射的功能,将jdbc查询到的ResuleSet,进行resultMap对象的构造,传参。更详细的构造和传参构成,是在它的父类FastResultHandler中进行的,createParameterizedResultObject方法负责构造映射对象,并映射<constructor>属性,applyPropertyMappings负责映射属性<result>。再吐槽几句,svn拉下来的源码一句注视也没有,是作者没写映射,还是故意不暴露呢。

还发现了一个问题。<constructor>中使用resultMap的时候,resultMap的<result/>配置对父级别中的<constructor>不起效,进过调试,发现在构造对象之后,源码没有进入applyPropertyMappings进行属性赋值,在就想到郁闷了,如果在这个情景中,我只能通过<constructor>赋值。没确定是不是BUG。

猜你喜欢

转载自tigerlchen.iteye.com/blog/1586536