MyBatis基于XML的详细使用——高级结果映射

目录

联合查询

emp.java

EmpMapper.xml

QueryEmpDTO

嵌套结果

多对一

嵌套查询

多对一

一对多

延迟查询

总结

一对一

一对多

多对多


联合查询

emp.java

public class Emp {
    private Integer id;
    private String username;
    private LocalDate createDate;
    private deptId deptId;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public LocalDate getCreateDate() {
        return createDate;
    }

    public void setCreateDate(LocalDate createDate) {
        this.createDate = createDate;
    }

    public Integer getDeptId() {
        return dept;
    }

    public void setDeptId(Integer deptId) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", createDate=" + createDate +
                ", deptId=" + deptId+
                '}';
    }

}

EmpMapper.xml

<!-- 实现表联结查询的方式:  可以映射: DTO -->
<resultMap id="QueryEmp_Map" type="QueryEmpDTO">
    <id column="e_id" property="id"></id>
    <result column="user_name" property="username"></result>
    <result column="d_id" property="deptId"></result>
    <result column="dept_name" property="deptName"></result>
</resultMap>

<select id="QueryEmp"  resultMap="QueryEmp_Map">
    select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
    INNER JOIN dept t2 on t1.dept_id=t2.id
    where t1.id=#{id}
</select>




<!-- 实现表联结查询的方式:  可以映射map -->
<resultMap id="QueryEmp_Map" type="map">
    <id column="e_id" property="id"></id>
    <result column="user_name" property="username"></result>
    <result column="d_id" property="deptId"></result>
    <result column="dept_name" property="deptName"></result>
</resultMap>

<select id="QueryEmp"  resultMap="QueryEmp_Map">
    select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
    INNER JOIN dept t2 on t1.dept_id=t2.id
    where t1.id=#{id}
</select>

QueryEmpDTO

public class QueryEmpDTO {

    private String deptName;
    private Integer deptId;
    private Integer id;
    private String username;

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "QueryEmpDTO{" +
                "deptName='" + deptName + '\'' +
                ", deptId=" + deptId +
                ", id=" + id +
                ", username='" + username + '\'' +
                '}';
    }
}
Test
  /**
 * 徐庶老师实际开发中的实现方式
 */
@Test
public void test01() {
    try(SqlSession sqlSession = sqlSessionFactory.openSession()){
        // Mybatis在getMapper就会给我们创建jdk动态代理
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        QueryEmpDTO dto = mapper.QueryEmp(4);
        System.out.println(dto);
    }
}

嵌套结果

多对一

EmpMapper.xml

<!--嵌套结果   多 对 一  -->
<resultMap id="QueryEmp_Map2" type="Emp">
    <id column="e_id" property="id"></id>
    <result column="user_name" property="username"></result>
    <!--
    association 实现多对一中的  “一”
        property 指定对象中的嵌套对象属性
    -->
    <association property="dept">
        <id column="d_id" property="id"></id>
        <id column="dept_name" property="deptName"></id>
    </association>
</resultMap>

<select id="QueryEmp2"  resultMap="QueryEmp_Map2">
    select t1.id as e_id,t1.user_name,t2.id as d_id,t2.dept_name from emp t1
    INNER JOIN dept t2 on t1.dept_id=t2.id
    where t1.id=#{id}
</select>
 
2.2一对多
    <!-- 嵌套结果: 一对多  查询部门及所有员工 -->
<resultMap id="SelectDeptAndEmpsMap" type="Dept">
    <id column="d_id"  property="id"></id>
    <id column="dept_name"  property="deptName"></id>
    <!--
    <collection  映射一对多中的 “多”
        property 指定需要映射的“多”的属性,一般声明为List
        ofType  需要指定list的类型
    -->
    <collection property="emps" ofType="Emp" >
        <id column="e_id" property="id"></id>
        <result column="user_name" property="username"></result>
        <result column="create_date" property="createDate"></result>
    </collection>
</resultMap>

<select id="SelectDeptAndEmps" resultMap="SelectDeptAndEmpsMap">
    select t1.id as d_id,t1.dept_name,t2.id e_id,t2.user_name,t2.create_date from dept t1
    LEFT JOIN emp t2 on t1.id=t2.dept_id
    where t1.id=#{id}
</select>

Emp.java

public class Emp {
    private Integer id;
    private String username;
    private LocalDate createDate;
    private Dept dept;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public LocalDate getCreateDate() {
        return createDate;
    }

    public void setCreateDate(LocalDate createDate) {
        this.createDate = createDate;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", createDate=" + createDate +
                ", dept=" + dept +
                '}';
    }

}

Dept.java:

public class Dept {
    private Integer id;
    private String deptName;
    private List<Emp> emps;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }


    @Override
    public String toString() {
        return "Dept{" +
                "id=" + id +
                ", deptName='" + deptName + '\'' +
                ", emps=" + emps +
                '}';
    }
}

EmpMapper.java:

public interface EmpMapper {

    /*徐庶老师实际开发中的实现方式*/
    QueryEmpDTO QueryEmp(Integer id);

    /*实用嵌套结果实现联合查询  多对一 */
    Emp QueryEmp2(Integer id);


    /*实用嵌套查询实现联合查询  多对一 */
    Emp QueryEmp3(Integer id);
}

DeptMapper.java:

public interface DeptMapper {
    //嵌套查询: 一对多   使用部门id查询员工
   Dept SelectDeptAndEmps(Integer id);

   // 嵌套查询(异步查询): 一对多  查询部门及所有员工
    Dept SelectDeptAndEmps2(Integer id);
}

嵌套查询

在上述逻辑的查询中,是由我们自己来完成sql语句的关联查询的,那么,我们能让mybatis帮我们实现自动的关联查询吗?

多对一

EmpMapper.xml:

<!--嵌套查询(分步查询)   多 对 一
  联合查询和分步查询区别:   性能区别不大
                            分部查询支持 懒加载(延迟加载)
   需要设置懒加载,一定要使用嵌套查询的。
   要启动懒加载可以在全局配置文件中设置 lazyLoadingEnabled=true
   还可以单独为某个分步查询设置立即加载 <association fetchType="eager"
  -->
<resultMap id="QueryEmp_Map3" type="Emp">
    <id column="id" property="id"></id>
    <result column="user_name" property="username"></result>
    <!-- association 实现多对一中的  “一”
        property 指定对象中的嵌套对象属性
        column  指定将哪个字段传到分步查询中
        select 指定分步查询的 命名空间+ID
        以上3个属性是实现分步查询必须的属性
        fetchType 可选, eager|lazy   eager立即加载   lazy跟随全局配置文件中的lazyLoadingEnabled
     -->
    <association property="dept"    column="dept_id"  select="cn.tulingxueyuan.mapper.DeptMapper.SelectDept">
    </association>
</resultMap>

<select id="QueryEmp3"  resultMap="QueryEmp_Map3">
   select  * from emp where id=#{id}
</select>

DeptMapper.xml

<!-- 根据部门id查询部门-->
<select id="SelectDept" resultType="dept">
    SELECT * FROM dept where id=#{id}
</select>

一对多

DeptMapper.xml

<!-- 嵌套查询(异步查询): 一对多  查询部门及所有员工 -->
<resultMap id="SelectDeptAndEmpsMap2" type="Dept">
    <id column="d_id"  property="id"></id>
    <id column="dept_name"  property="deptName"></id>
    <!--
    <collection  映射一对多中的 “多”
        property 指定需要映射的“多”的属性,一般声明为List
        ofType  需要指定list的类型
        column 需要将当前查询的字段传递到异步查询的参数
        select 指定异步查询
    -->
    <collection property="emps" ofType="Emp" column="id" select="cn.tulingxueyuan.mapper.EmpMapper.SelectEmpByDeptId" >
    </collection>
</resultMap>

<select id="SelectDeptAndEmps2" resultMap="SelectDeptAndEmpsMap2">
    SELECT * FROM dept where id=#{id}
</select>
EmpMapper.xml

<!-- 根据部门id所有员工 -->
<select id="SelectEmpByDeptId"  resultType="emp">
    select  * from emp where dept_id=#{id}
</select>

EmpMapper.xml

<!-- 根据部门id所有员工 -->
<select id="SelectEmpByDeptId"  resultType="emp">
    select  * from emp where dept_id=#{id}
</select>

Emp.java

public class Emp {
    private Integer id;
    private String username;
    private LocalDate createDate;
    private Dept dept;


    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public LocalDate getCreateDate() {
        return createDate;
    }

    public void setCreateDate(LocalDate createDate) {
        this.createDate = createDate;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", createDate=" + createDate +
                ", dept=" + dept +
                '}';
    }

}

Dept.java:

public class Dept {
    private Integer id;
    private String deptName;
    private List<Emp> emps;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }


    @Override
    public String toString() {
        return "Dept{" +
                "id=" + id +
                ", deptName='" + deptName + '\'' +
                ", emps=" + emps +
                '}';
    }
}

EmpMapper.java:

public interface EmpMapper {

    /*徐庶老师实际开发中的实现方式*/
    QueryEmpDTO QueryEmp(Integer id);

    /*实用嵌套结果实现联合查询  多对一 */
    Emp QueryEmp2(Integer id);


    /*实用嵌套查询实现联合查询  多对一 */
    Emp QueryEmp3(Integer id);
}

DeptMapper.java:

public interface DeptMapper {
    //嵌套查询: 一对多   使用部门id查询员工
   Dept SelectDeptAndEmps(Integer id);

   // 嵌套查询(异步查询): 一对多  查询部门及所有员工
    Dept SelectDeptAndEmps2(Integer id);
}

延迟查询

当我们在进行表关联的时候,有可能在查询结果的时候不需要关联对象的属性值,那么此时可以通过延迟加载来实现功能。在全局配置文件中添加如下属性

mybatis-config.xml

<!-- 开启延迟加载,所有分步查询都是懒加载 (默认是立即加载)-->
<setting name="lazyLoadingEnabled" value="true"/>
<!--当开启式, 使用pojo中任意属性都会加载延迟查询 ,默认是false
<setting name="aggressiveLazyLoading" value="false"/>-->
<!--设置对象的哪些方法调用会加载延迟查询   默认:equals,clone,hashCode,toString-->
<setting name="lazyLoadTriggerMethods" value=""/>

如果设置了全局加载,但是希望在某一个sql语句查询的时候不使用延时策略,可以添加fetchType下属性:

<association property="dept" fetchType="eager"  column="dept_id"  select="cn.tulingxueyuan.mapper.DeptMapper.SelectDept">
    </association>

总结

三种关联guan关系都有两种关联查询的方式,嵌套查询,嵌套结果

*Mybatis的yanc延迟加载配置

在全局配置文件中加入下面代码

<settings>
<setting name=”lazyLoadingEnabled” value=”true” />
<setting name=”aggressiveLazyLoading” value=”false”/>
</settings>

 在映射文件中,元素和元素中都已默认配置了延迟加载属性,即默认属性fetchType=”lazy”(属性fetchType=”eager”表示立即加载),所以在配置文件中开启延迟加载后,无需在映射文件中再做配置

一对一

使用元素进行一对一关联映射非常简单,只需要参考如下两种示例配置即可

一对多

元素中,包含了一个子元素,MyBatis就是通过该元素来处理一对多关联关系的

子元素的属性大部分与元素相同,但其还包含一个特殊属性–ofType

ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型。

元素的使用也非常简单,同样可以参考如下两种示例进行配置,具体代码如下:

多对多

多对多的关联关系查询,同样可以使用前面介绍的元素进行处理(其用法和一对多关联关系查询语句用法基本相同)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值