springboot整合mybatis使用collection查询 一对多 多对一 多对多查询

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️,满足一下我的虚荣心💖🙏🙏🙏 。

目录

准备测试类

集合的嵌套Select查询

集合的嵌套结果映射

集合的多结果集(ResultSet)

补充


准备测试类

不小心把已经写好的博客误删除,再简单记录一下吧,集合元素collection和关联元素association几乎是一样的,准备下测试类:

@Data
public class Order {
    private int id;
    private int userId;
    private String orderNumber;

}

准备一个UserOrderDto接收查询结果:

@Data
public class UserOrderDto {
    private int id;
    private String userName;
    private List<Order> orderList;
}

mapper文件代码不贴了,直接贴测试类代码:

    @Test
    public void collectionTest1() {
        UserOrderDto userOrderDto = userMapper.selectUserOrdersBySelect(1);
        System.out.println("--- userOrderDto ---" + userOrderDto);
    }

同关联查询一样,集合查询也有嵌套 Select 查询、集合的嵌套结果映射和集合的多结果集(ResultSet)这三种常用写法。

集合的嵌套Select查询

先看下集合的嵌套Select查询:

UserMapper.xml:

<select id="selectUserOrdersBySelect" resultMap="userOrderResultMapBySelect">
        select id,name as username
        from mybatis_user
        where id = #{id}
    </select>
    <resultMap id="userOrderResultMapBySelect" type="com.yjh.learn.mybatislearn.dto.UserOrderDto">
        <collection property="orderList" column="id" select="selectOrdersByUserId"
                    ofType="Order"/>
    </resultMap>
    <select id="selectOrdersByUserId" resultType="Order">
        select *
        from mybatis_order
        where user_id = #{userId}
    </select>

如上:和使用association关联查询时几乎一样,不一样的在于:1.association换成了collection;2.有一个属性叫ofType="Order",这个属性非常重要,它用来将 JavaBean(或字段)属性的类型和集合存储的类型区分开来。 所以你可以按照下面这样来阅读映射:
<collection property="orderList" javaType="ArrayList" column="id" ofType="Order" select="selectOrdersByUserId"/>
读作: “orderList 是一个存储 Order 的 ArrayList 集合”
在一般情况下,MyBatis 可以推断 javaType 属性,因此并不需要填写。所以很多时候你可以简略成:

<collection property="orderList" column="id" ofType="Order" select="selectOrdersByUserId"/>

集合的嵌套结果映射

    @Test
    public void collectionTest2(){
        UserOrderDto userOrderDto = userMapper.selectUserOrders(1);
        System.out.println("--- userOrderDto ---" + userOrderDto);
    }
<select id="selectUserOrders" resultMap="userOrderResultMap">
        select u.id,u.name, o.*
        from mybatis_user u
                     left join mybatis_order o on u.id = o.user_id
        where u.id = #{id}
    </select>
    <resultMap id="userOrderResultMap" type="com.yjh.learn.mybatislearn.dto.UserOrderDto">
        <id property="id" column="id"/>
        <result property="userName" column="name"/>
        <collection property="orderList" column="id" ofType="Order"
                    resultMap="orderResultMap"/>
    </resultMap>
    <resultMap id="orderResultMap" type="Order">
        <id property="id" column="id"/>
        <result property="userId" column="user_id"/>
        <result property="orderNumber" column="order_number"/>
    </resultMap>

  

 

如上查询本意是想查询用户张三的所有订单,并且从控制台打印的sql可以看出查询到了两个订单,但是实际映射完的结果却只有一个,原因就是用户表和订单表的id名称一样,这时候为了能正确映射两个订单,可以不映射订单的id,如下:

 <resultMap id="orderResultMap" type="Order">
<!--        <id property="id" column="id"/>-->
        <result property="userId" column="user_id"/>
        <result property="orderNumber" column="order_number"/>
    </resultMap> 

如上,虽说查询到了两个订单,但是每个订单的id就获取不到了,在使用association和collection映射时都有这个问题,最简单的解决方式就是在表结构上将各id区分开,比如用户表的id为user_id,订单表的id为order_id,这里只改下订单表的id即可,如下:

<select id="selectUserOrders" resultMap="userOrderResultMap">
        select u.id,u.name, o.*
        from mybatis_user u
                     left join mybatis_order o on u.id = o.user_id
        where u.id = #{id}
    </select>
    <resultMap id="userOrderResultMap" type="com.yjh.learn.mybatislearn.dto.UserOrderDto">
        <id property="id" column="id"/>
        <result property="userName" column="name"/>
        <collection property="orderList" column="id" ofType="Order"
                    resultMap="orderResultMap"/>
    </resultMap>
    <resultMap id="orderResultMap" type="Order">
        <id property="orderId" column="order_id"/>
        <result property="userId" column="user_id"/>
        <result property="orderNumber" column="order_number"/>
    </resultMap>

再次查询的时候数据就完整了,如下:

同association一样嵌套结果映射也有简写方式,如下:

<resultMap id="userOrderResultMapSimple" type="com.yjh.learn.mybatislearn.dto.UserOrderDto">
        <id property="id" column="id"/>
        <result property="userName" column="name"/>
        <collection property="orderList" column="id" ofType="Order">
            <id property="orderId" column="order_id"/>
            <result property="userId" column="user_id"/>
            <result property="orderNumber" column="order_number"/>
        </collection>
    </resultMap>

集合的多结果集(ResultSet)

同association一样先建一个存储过程:

DELIMITER $$
CREATE PROCEDURE `uorders`(IN `userId` INTEGER)
BEGIN
	SELECT * FROM mybatis_user WHERE id = userId;
	SELECT * FROM mybatis_order WHERE user_id = userId;
END $$

在映射语句中,必须通过 resultSets 属性为每个结果集指定一个名字,多个名字使用逗号隔开,如下:

<select id="selectUserOrdersByResultSet" resultSets="uresult,oresult" resultMap="userResultMap1" statementType="CALLABLE">
        {call uorders(#{userId,jdbcType=INTEGER,mode=IN})}
    </select>

我们指定 “orderList” 集合将会使用存储在 “oresult” 结果集中的数据进行填充:

<resultMap id="userResultMap1" type="com.yjh.learn.mybatislearn.dto.UserOrderDto">
        <id property="id" column="id"/>
        <result property="userName" column="name"/>
        <collection property="orderList" ofType="Order" resultSet="oresult" column="id" foreignColumn="user_id">
            <id property="orderId" column="order_id"/>
            <result property="userId" column="user_id"/>
            <result property="orderNumber" column="order_number"/>
        </collection>
    </resultMap>

测试下:

    @Test
    public void test9() {
        UserOrderDto userOrderDto = userMapper.selectUserOrdersByResultSet(1);
        System.out.println("--- userOrderDto ---" + userOrderDto);
    }

完成!

补充

返回对象中包含List属性,如List<Integer>这种怎么关联映射呢,直接贴代码了:

用户实体中增加一个roles属性,表示用户的角色集合

private List<Integer> roles;

xml中:

    <resultMap id="userResultMap" type="User">
        <id property="userId" column="user_id" />
        <result property="userName" column="user_name" />
        <collection property="orderList" ofType="Order">
            <id property="orderId" column="order_id" />
            <result property="userId" column="user_id" />
            <result property="number" column="number" />
        </collection>
        <collection property="roles" ofType="integer">
            <constructor>
                <arg column="roles" />
            </constructor>
        </collection>
    </resultMap>

    <select id="selectUserOrdersAndRoles" resultMap="userResultMap">
        select u.*,o.*,ur.role_id as roles from t_user u
            left join t_orders o on u.user_id = o.user_id
            left join t_user_role ur on u.user_id = ur.user_id
        where u.user_id = #{userId}
    </select>

如果我的博客对你有帮助,欢迎进行评论✏️✏️、点赞👍👍、收藏⭐️⭐️,满足一下我的虚荣心💖🙏🙏🙏 。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值