天天看点

2108-05 xml中多表关联

常见表关系

秘诀:从一头出发,所在位置不同,得到的结果也不同

1.一对一 例子:一个老公对应一个老婆,一个员工对应一个部门

2.一对多 例子:一个部门对应多个原

3.多对多 例子:一个学生对应多个老师,一个老师对应多个学生

一个角色对应多个权限,一个权限对应多个角色 多对多其实就是双向的一对多

4.多对一 实质:站在一头出发,所以就是一对一

Mybatis中映射规则:结果集中不允许出现重名字段

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
    private Integer empId;
    private String  empName;
    //关联关系 1: 一个员工对应一个部门
    private Dept dept;
}
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
    private Integer deptId;
    private String deptName;
    //一个部门对应多个员工
    private List<Emp> emps;
}

           

需求:进行一对一查询,一个员工对应一个部门(看pojo,不要有疑问)

sql:select * from emp e,dept d where e.dept_id = d.dept_id   //一对一关联查询

难点:如何完成一对一的封装

固定用法:association:将结果集封装为单独的对象dept

       2.property 需要封装的属性名称

        3.javaType 固定用法: 属性的类型

下面是完整的代码:findAll()不必多说,就是查的sql中的数据,可以看出dept是包含deptId和deptName的,需要将dept类的两个属性封装为dept对象(实例)中

<select id = "findAll" resultMap = "empRM">
     select e.emp_id,e.emp_name,d.dept_id,d.dept_name from emp e,dept d
     where e.dept_id = d.dept_id
</select>
<resultMap id= "empRM" type = "Emp">
      //映射主键,xml中不可以使用//注释,这里图个快捷
     <id property="empId" column="emp_id'></id>
    //映射其他字段
     <result property="empName" column="emp_name'></result>
    <association property ="dept" javaType = "Dept">
    //完成dept对象的封装
        <id property="id" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
    </association>        
</resultMap>
           

需求:进行一对多查询,一个部门对应多个员工(这里看pojo就知道要封装,不要疑问)

sql:select d.dept_id,d.dept_name,e.emp_id,e.emp_name from dept d,emp e

where d.dept_id = e.emp_id

难点:如何将emp中查到的数据数据封装到集合list<Emp>集合中

固定用法:collection标签封装集合,在这里表示将同一个部门下得员工封装到一个集合中

        property表示要封装成的集合名称

        ofType表示元素类型

<select id="findAll" resultMap="deptRM">
    select d.dept_id,d.dept_name,e.emp_id,e.emp_name
    from dept d,emp e
    where d.dept_id=e.emp_id
</select>

<resultMap id="deptRM" type="Dept">
    <id property="deptId" column="dept_id'></id>
    <result propery="deptName" column="dept_name"></result>
    <collection property="emps" ofType="Emp">
        <id property="empId" column="emp_id"></id>
        <result property="empName" column="emp_name"></result>
    </collection>
</resultMap>
    
           

注意:表有主次之分的,分的主次可以简单很多,Mybatis的封装一般都是一级封装

Mybatis的子查询

矛盾点:1.如果想简化sql,则映射文件肯定复杂 2。如果想简化映射文件,则sql语句复杂

需求:使用子查询来完成封装

子查询本质特点:将多表关联查询,转化为多个单表查询

思考;这个既然要使用子查询的,但是返回值不仅仅是dept一张表的数据(这里和上面一样实现一对多,只是换种方法),所以常规的sql:

select dept_id,dept_name from emp where dept_id in (select dept_id from emp)肯定不可以

最终目的是将emp查询的数据封装List<Emp> emps集合对象中

代码如下:

<select id="selectChildren" resultMap="deptRM">
    select * from dept  
    //这里可以写成select dept_id,dept_name from dept, 由于表中没有字段emps,
写在这里报错,就这样写结果也是可以封装的,自己已经验证过,所以遇到当字段只是表中
的一部分但是业务需要封装时,这时就需要将指定的字段写在这里,而不能只写个*就可以
</select>
<resultMap id="deptRM" type="Dept">
    //映射主键
    <id property="deptId" column="dept_id"></id>
    //映射其他字段
    <result property="deptName" column="dept_name"></result>
    //数据集合封装
   <collection property="emps" ofType="Emp" select="findEmp" column="dept_id"></collection>
</resultMap>
//二次查询,将column="dept_id"字段的值作为参数,传递给子查询
<select id="findEmp" resultMap="empRM">
    select * from where dept_id=#{dept_id}
    //这里的#{dept_id}就是上面映射字段的dept_id,通俗点的意思就是
将dept_id中查出来dept_id给到当前表中使用。这里的*可以替换为具体的
字段emp_id,emp_name
</select>
<resultMap id="empRM" type="Emp">
    //映射主键
    <id property="empId" column="emp_id"></id>
    //映射其他字段
    <result property="empName" column="emp_name">
</resultMap>
           

同理,一对一的封装,一个员工对应一个部门的封装代码为:

<select id="findAllSelect" resultMap="empRM2">
        select * from emp
    </select>
    
    <!--进行数据封装-->
    <resultMap id="empRM2" type="Emp">
        <id column="emp_id" property="empId"/>
        <result column="emp_name" property="empName"/>
        <association property="dept" javaType="Dept" select="selectDept" column="dept_id"></association>
    </resultMap>
    
    <select id="selectDept" resultMap="deptRM">
        select * from dept where dept_id= #{dept_id}
    </select>
    
    <resultMap id="deptRM" type="Dept">
        <id column="dept_id" property="deptId"/>
        <result column="dept_name" property="deptName"/>
    </resultMap>