MyBatis 映射对象关系举例(2)

双向many2one/one2many

双向many2one/one2many是比较常见的对象关系。总体的使用方式和单向的many2one基本相同。先来看看对象的关系,在这里使用Department和Employee对象来完成双向的many2one/one2many。对象设计如下:

//员工对象
public class Employee {
    private Long id;
    private String name;
    //关联部门对象
    private Department dept;
    //getter & setter;
}        
        
//部门对象
public class Department {
    private Long id;
    private String name;
    //关联的员工对象列表
    private Set<</span>Employee> emps = new HashSet<</span>Employee>();
    //getter & setter
}

先看Department对象的映射文件:

<mapper namespace="cd.itcast.mybatis.department">
<insert id="save" keyProperty="id" parameterType="Department" useGeneratedKeys="true">
INSERT INTO department(name) values (#{name})
</insert>
<resultMap type="Department" id="departmentmap">
<id column="did" property="id"/>
<result column="dname" property="name"/>
<collection property="emps" column="dept_id" ofType="Employee">
<id column="id" property="id"/>
<result column="name" property="name"/>
<association property="dept" column="dept_id" resultMap="departmentmap"/>
</collection>
</resultMap>

<selectid="get" parameterType="int" resultMap="departmentmap">
SELECT e.*,d.name as dname,d.id as did FROM employee e LEFT JOINdepartment d on e.dept_id = d.id WHERE d.id = #{id}
</select>
</mapper>

在上面的映射中,需要特别注意的一点:在department的映射departmentmap中,使用了collection完成了内嵌的映射。 特别的,在内嵌的映射中,我们又使用了association来映射Employee中的Department对象。注意,在这里,我们必须使用resultMap="departmentmap"来映射 department,而不能使用resultType。在这里,很明显是一个循环引用,Mybatis会使用SqlSession的缓存来完成对象的嵌套引用。 下面来看看Employee的映射文件:  
<mapper namespace="cd.itcast.mybatis.employee">
    <insert id="save" keyProperty="id" parameterType="Employee"
                useGeneratedKeys="true">
            INSERT INTO employee(name) values (#{name})     
     </insert>
       
<resultMap type="Employee" id="employeemap">
     <id column="id" property="id"/>
     <result column="name" property="name"/>
     <association property="dept" column="dept_id" javaType="Department">
         <id column="did" property="id"/>
         <result column="dname" property="name"/>
    </association>
</resultMap>

<select id="get" parameterType="int" resultMap="employeemap">
          SELECT e.*,d.id as did,d.name as dname FROM employee e LEFT JOIN department d on e.dept_id = e.id WHERE e.id = #{id}
</select>

</mapper>

get方法映射还是使用内嵌的映射完成的。但是在这里,非常重要的一个问题,当我们完成了association关联完成Employee里面的Department对象的映射的时候,我们没有再次去映射这个Department对应的Employee列表对象。换句话说,当使用selectOne得到Employee对象的时候,通过这个Employee对象得到的Department对象,在从这个Department对象里面去拿Employee列表的时候,得到的是一个空的列表。要解决这个问题,不能像下面这样使用:
<resultMap type="Employee" id="employeemap">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <association property="dept" column="dept_id" javaType="Department">
            <id column="did" property="id"/>
            <result column="dname" property="name"/>
            <collection property="emps" column="dept_id" ofType="Employee" resultMap="employeemap" />
        </association>
</resultMap>

注意,如果是这样映射的话,通过employee.getDept().getEmps()得到的列表,Mybatis同样会使用SqlSession的缓存来完成这个循环引用。但是,因为这是get方法,得到的只是一个Employee对象,所以,不管Department有多少Employee和其关联,都只会只有当前的这个Employee对象。即,employee.getDept().getEmps().size()==1如果要完整的映射这个关系,就只能使用额外的select来完成了。但是这样做会导致很多额外的SQL,不建议这样做。如果需求中真需要从employee中得到department,并且再从department中得到employee,那么建议使用cd.itcast.mybatis.department.get再得一次Department对象就可以了。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值