Mybatis中级联有关联(association)、集合(collection)、鉴别器(discriminator)三种。其中,association对应一对一关系、collection对应一对多关系、discriminator可以根据情况选择采用哪个类作为实例,关联不同的结果集。
一、关联
Mybatis的关联有两种方式:
- 嵌套查询:通过执行另外一个 sql映射语句来返回预期的复杂类型
- 嵌套结果:使用嵌套结果映射来处理重复了联合结果的子集
场景一:一个部门Department有一个部门经理Leader
<!-- 嵌套查询 (N+1查询问题) --> <resultMap type="Department" id="deptResult"> <id property="id" column="d_id"/> <result property="name" column="d_name"/> <association property="leader" column="leader_id" select="getLeader" javaType="Leader"/> </resultMap> <select id="getDept" parameterType="int" resultMap="deptResult"> select * from department where d_id=#{id} </select> <select id="getLeader" parameterType="int" resultType="Leader"> select * from leader where l_id=#{id} </select> <!-- 嵌套结果 --> <resultMap type="task.Department" id="deptResult"> <id property="id" column="d_id"/> <result property="name" column="d_name"/> <association property="leader" javaType="Leader"> <id property="id" column="l_id"/> <result property="name" column="l_name"/> </association> </resultMap> <select id="getDept" parameterType="int" resultMap="deptResult"> select * from department d, leader l where d.leader_id = l.l_id and d.d_id=#{id} </select>
场景二:获取指定部门的所有上级部门(获取子结点的所有父结点,一个结点最多只有一个直接父结点)
<resultMap type="Department" id="deptResult"> <id column='id' property='id'/> <result column='name' property='name'/> <association property='parent' javaType='Department' select='getPDept' column='p_id'/> </resultMap> <select id="getDept" resultMap="deptResult"> select id,name,p_id from department where id =#{id} </select>
二、集合
和关联一样,集合也有嵌套查询和嵌套结果两种方式,只是多了个关键字ofType,用来区分JavaBean属性类型和集合包含的类型。
场景:一个部门Department有多个员工Worker
<!-- 嵌套查询 --> <resultMap type="Department" id="deptResult"> <id property="id" column="id"/> <result property="name" column="d_name"/> <!-- javaType属性不是必需的 --> <collection property="workers" javaType="ArrayList" column="id" ofType="Worker" select="getWorkers"/> </resultMap> <resultMap type="Worker" id="workerResult" > <id property="id" column="w_id"/> <result property="name" column="w_name"/> <result property="age" column="age"/> </resultMap> <select id="getDept" parameterType="int" resultMap="deptResult"> select id,d_name from department where id=#{id} </select> <select id="getWorkers" parameterType="int" resultMap="workerResult"> select w_id,w_name,age from worker where d_id=#{id} </select> <!-- 嵌套结果 --> <resultMap type="Department" id="deptResult"> <id property="id" column="id"/> <result property="name" column="d_name"/> <collection property="workers" ofType="Worker"> <id property="id" column="w_id"/> <result property="name" column="w_name"/> <result property="age" column="age"/> </collection> </resultMap> <select id="getDept" parameterType="int" resultMap="deptResult"> select id,d_name,w_id,w_name,age from department,worker where id=d_id and id=#{id} </select>
三、鉴别器
有时一个数据库查询语句会返回很多不同数据类型的结果集。鉴别器用于处理这种情况,还包括类的继承层次结构,其表现相当于Java中的switch语句。
场景:交通工具Vehicle,有子类小汽车Car,卡车Truck两种类型,根据vehicle表中type字段区别数据,将查询出的数据自动封装成不同类型的对象
<resultMap type="Vehicle" id="vehicleResult"> <id property="id" column="id"/> <result property="color" column="color"/> <discriminator javaType="int" column="type"> <case value="1" resultType="Car"> <result property="doorCount" column="door_count"></result> </case> <case value="2" resultType="Truck"> <result property="boxSize1" column="box_size1"></result> <result property="boxSize2" column="box_size2"></result> </case> </discriminator> </resultMap> <select id="getVehicle" resultMap="vehicleResult"> select * from vehicle </select>