专栏首页Danny的专栏【MyBatis框架点滴】——MyBatis一对多查询

【MyBatis框架点滴】——MyBatis一对多查询

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/details/51588119

上篇文章说了MyBatis中的一对一查询的两种方法,这里总结一下MyBatis中一对多和多对一的查询方法。

  业务还用上篇文章中的订单业务来分析,表结构如下:

  如上图订单和用户的关系,一个订单对应多个订单明细表,这里以订单为主查询表,在查询订单的同时,查询出每个订单所包含的订单明细集合,顺便把每个订单对应的用户也查询出来。(即在上篇文章的基础上,再查询出每个订单所包含的订单明细)

  由于每个订单可能有多个订单明细,所以这时需要用esultMap映射结果集。如果使用resultType会很麻烦,需要去重(比如文章末尾的图片中,sql查询出的是8条记录,但实际上这8条订单明细只属于4个订单实体,所以需要手动循环、判断、去重~)。


  具体用法如下:

  订单实体在上篇文章的基础上,添加订单明细的集合 orderDetails:

public class Orders {
    private Integer id;
    private Integer userId;
    private String number;
    private Date createtime;
    private String note;
    private User user;//订单对应用户
    private List<OrderDetail> orderDetails;//订单所包含的订单明细集合
    //getter、setter
}

  映射文件OrdersMapper.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.danny.mybatis.mapper.OrdersMapper" >

    <resultMap type="com.danny.mybatis.po.Orders" id="OrdersUserOrderDetailResultMap">
        <!-- 配置映射的订单信息 -->  
        <!-- <id column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <result column="note" property="note"/> -->

        <!-- 配置映射的用户信息 -->
        <association property="user" javaType="com.danny.mybatis.po.User">
            id:关联查询用户的唯一标识
                 column:指定唯一标识用户信息的列
                 property:映射到user的哪个属性
            <id column="user_id" property="id"/>
            <result column="username" property="username"/>
            <result column="sex" property="sex"/>
            <result column="address" property="address"/>
        </association>

        <!-- 订单明细信息-->
        <collection property="orderDetails" ofType="com.danny.mybatis.po.OrderDetail">
            <id column="orderdetail_id" property="id"/>
            <result column="items_id" property="itemsId"/>
            <result column="items_num" property="itemsNum"/>
            <result column="orders_id" property="ordersId"/>
        </collection>
    </resultMap>

    <select id="findOrdersUserOrderDetailResultMap" resultMap="OrdersUserOrderDetailResultMap" >
        select
            orders.*,
            user.username,
            user.sex,
            user.address,
            orderdetail.id orderdetail_id,
            orderdetail.items_id,
            orderdetail.items_num,
            orderdetail.orders_id
        from orders,user,orderdetail
        where orders.user_id=user.id
        and orders.id=orderdetail.orders_id
    </select>
</mapper>

  在上面resultMap配置中,共有三个部分,配置映射的订单信息、配置映射的用户信息和配置映射的订单明细信息。前两部分与上篇文章中的一致,这里不再多说。

  映射Ordes中的订单集合orderDetails要用<collection></collection>进行映射,它的作用是把关联查询到的多条记录映射到集合对象中,property表示将关联查询到的多条订单明细记录映射到Orders的哪个属性中,与<association></association> 中的javaType不同,这里指定orderDetails的类型要用ofType属性,它表示指定映射到集合属性中的pojo的类型。

  因为这个resultMap的配置大约有2/3的代码都与上篇文章中的resultMap一直,因此也可以跟java类似的,让这个resultMap继承已有的resultMap,如下:

<resultMap type="com.danny.mybatis.po.Orders" id="OrdersUserOrderDetailResultMap" extends="OrdersUserResultMap">
        <!-- 订单明细信息-->
        <collection property="orderDetails" ofType="com.danny.mybatis.po.OrderDetail">
            <id column="orderdetail_id" property="id"/>
            <result column="items_id" property="itemsId"/>
            <result column="items_num" property="itemsNum"/>
            <result column="orders_id" property="ordersId"/>
        </collection>
    </resultMap>

  mapper接口

public interface OrdersMapper{
    List<Orders> findOrdersUserOrderDetailResultMap() throws Exception;
}

  测试

@Test
public void findOrdersUserOrderDetailResultMap(){
    SqlSession sqlSession=sqlSessionFactory.openSession();
    OrdersMapper ordersMapper=sqlSession.getMapper(OrdersMapper.class);
    try {
        List<Orders> ordersList=ordersMapper.findOrdersUserOrderDetailResultMap();
        System.out.println("共查询到"+((ordersList!=null && list.size()>0)?ordersList.size():0)+"个订单");
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println();
}

  上述sql语句查询出的结果为:

  断点查看list中的数据如下:

  虽然sql语句查询出的结果为8条数据,但实际上只有4个订单(通过id字段可以看出来),MyBatis自动把id相同的记录合并成一个订单实体,并根据resultMap中的配置,把属于同一个订单的订单明细分别放到了对应订单的订单明细集合中。

  如果熟悉Hibernate的话,到了这里,您是不是也和小编觉得这跟Hibernate的配置也有些相似呢~~

  如果要问多对一查询的话,实际上你已经不知不觉地实现了~订单和用户啥关系?多个订单可以属于一个用户,所以上面的配置中<association></association> 也可以实现多对一查询,不信你在好好看看上面list中的内容,第一和第二个订单所属的用户其实是同一个人:DannyHoo~


【 转载请注明出处——胡玉洋《【MyBatis框架点滴】——MyBatis一对多查询》】

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【SSH快速进阶】——Hibernate 多对多映射

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • 【MyBatis框架点滴】——MyBatis多对多查询

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • 【MyBatis框架点滴】——MyBatis一对一查询

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

    DannyHoo
  • MySQL外键约束

    外键其实很好理解,简单的说就是两张表建立一个连接关系。这里我们那主表A和副表B举例,我A表中有用户信息,B表中有用户订单信息。要是数据完整对应起来,肯定是需要把...

    卡二条的技术圈子
  • 一道很有意思的Redis面试题,我选出了一些优质评论

    起源于我在一个短视频中分享的一道面试题,当然,这道面试题我确实在工作中用过,只是业务场景不同。

    wujiuye
  • Mybatid关联表查询

    一、一对一关联  1.1、提出需求   根据班级id查询班级信息(带老师的信息) 1.2、创建表和数据   创建一张教师表和班级表,这里我们假设一个老师只负...

    汤高
  • MyBatis学习总结(五)——实现关联表查询

    一枝花算不算浪漫
  • 网络基础 http 会话(session)详解

    会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制

    授客
  • MyBatis 实现关联表查询

    一、一对一关联  1.1、提出需求   根据班级id查询班级信息(带老师的信息) 1.2、创建表和数据   创建一张教师表和班级表,这里我们假设一个老师只负责教...

    庞小明
  • 获取jqGrid中选择的行的数据

    var id=$(‘#gridTable’).jqGrid(‘getGridParam’,'selrow’);

    ydymz

扫码关注云+社区

领取腾讯云代金券