多表连接查询的几种情况

多对一查询

- 关联方式查询
例:
通过多表关联的SQL语法进行查询, 需要使用join, on, …来实现查询. 执行一条SQL语句就可以将所有需要的数据全部查询到. 我们需要做的就是将查到的数据进行映射即可.
StudentMapper.xml:

 <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjsxt.mapper.StudentMapper">
    <resultMap id="smap" type="student" autoMapping="true">
        <!--<id column="id" property="id" />
        <result column="name" property="name" />
        <result column="gender" property="gender" />
        <result column="birthday" property="birthday" />-->
        <!--关联单个对象要使用association-->
        <association property="clazz" javaType="clazz" autoMapping="true">
            <id column="cid" property="id" />
            <result column="cname" property="name" />
            <!--<result column="room" property="room" />-->
        </association>
    </resultMap>

    <select id="selAll" resultMap="smap">
        select
            s.*, c.name cname, c.room
        from
            tb_student s
        left join
            tb_class c
        on
            s.cid = c.id
    </select>
</mapper>


 



- N+1方式查询
表示所有数据要获取到需要执行N+1条SQL语句. 每次查询都是单表查询, 查多次就拿到所有数据了.
例:
StudentMapper.xml:

<resultMap id="smap2" type="student">
    <!--映射单个对象-->
    <association
            property="clazz"
            javaType="clazz"
            select="com.bjsxt.mapper.ClazzMapper.selById"
            column="cid" />
</resultMap>
<select id="selAll2" resultMap="smap2">
    select * from tb_student
</select>

ClazzMapper.xml:

<mapper namespace="com.bjsxt.mapper.ClazzMapper">
    <select id="selById" resultType="clazz">
        select * from tb_class where id=#{id}
    </select>
</mapper>

一对多查询

  • 关联查询:
<resultMap id="cmap" type="clazz" autoMapping="true">
    <!--关联集合对象, 使用collection标签-->
    <collection property="students" javaType="list" ofType="student" autoMapping="true">
        <id column="sid" property="id" />
        <result column="sname" property="name" />
    </collection>
</resultMap>

<select id="selAll" resultMap="cmap">
    select
        c.*, s.id sid, s.name sname, s.gender, s.birthday
    from
        tb_class c
    left join
        tb_student s
    on
        c.id = s.cid
</select>
  • N+1查询
    StudentMapper.xml:
<resultMap id="cmap2" type="clazz">
    <!--如果这一列作为参数继续传递, 会导致自动映射失败-->
    <id column="id" property="id" />
    <collection
            property="students"
            javaType="list"
            ofType="student"
            select="com.bjsxt.mapper.StudentMapper.selByCid"
            column="id" />
</resultMap>
<select id="selAll2" resultMap="cmap2">
    select * from tb_class
</select>

ClazzMapper.xml:

<mapper namespace="com.bjsxt.mapper.StudentMapper">
    <select id="selByCid" resultType="student">
        select * from tb_student where cid=#{cid}
    </select>
</mapper>

业务装配方式查询
EmpMapper.xml

<select id="selAll" resultType="emp">
    select * from tb_emp
</select>
@Test
public void test2() {
    SqlSession session = MyBatisUtil.getSession();

    EmpMapper mapper = session.getMapper(EmpMapper.class);
    List<Emp> list = mapper.selAll();
    // 将平级结构转换为树状结构 -- 业务装配
    List<Emp> tree = list2Tree(list);
    System.out.println(tree);

    session.close();
}

private List<Emp> list2Tree(List<Emp> dataList) {
    List<Emp> result = new ArrayList<>();
    // 将list集合转换为Map集合, 方便查出领导使用
    Map<Integer, Emp> temp = new HashMap<>();
    for (Emp emp : dataList) {
        temp.put(emp.getEmpno(), emp);
    }
    // 结构转换
    for (Emp emp : dataList) {
        // 判断当前员工是不是顶级员工(总裁)
        if(emp.getMgr() == null) {
            result.add(emp);
            continue;
        }
        // 普通员工, 找上级领导
        temp.get(emp.getMgr()).getEmps().add(emp);
    }
    return result;
}

关联查询和N+1查询对比

a) 关联查询:

  • sql语句是关联语法, 需要使用join…on…
  • 只需要执行1条SQL语句
  • 默认情况下, 不会自动映射, 可以通过设置autoMapping=true开启自动映射

b) N+1查询:

  • SQL语句都是单表查询

  • 需要执行N+1次查询才能得到结果

  • 默认情况下, 就会自动映射.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值