4.mybatis 高级结果查询

本文详细介绍了MyBatis中的一对一、一对多和多对多关联查询。从resultType和resultMap的使用,到具体的查询细节,如避免超过三个表的join,禁止外键与级联,以及字段冗余的考虑。文中通过订单和用户、订单详情等关系模型,展示了不同关联查询的实现方式和映射配置,提供了具体的Mapper文件和接口方法示例。
摘要由CSDN通过智能技术生成

商品订单模型

一个用户可以下n个订单,一个订单只能属于一个用户。

一个订单可以有多个订单详情,订单和订单详情是一对多的关系。

一个订单中可以有多个商品,一个商品也可以属于多个订单,订单和商品多对多的关系

关联查询几个需要注意的细节

1.超过三个表禁止 join。需要 join 的字段,数据类型必须绝对一致;多表关联查询时,保证被关联的字段需要有索引

2.不得使用外键与级联,一切外键概念必须在应用层解决

3.字段允许适当冗余,以提高查询性能,但必须考虑数据一致

关联方式

关联元素:association用于表示一对一关系,collection用于表示一对多关系;

  • 嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
  • 嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型

4.1 一对一查询

查询所有订单信息,关联查询下单用户信息。

SELECT
            o.id,
            o.user_id,
            o.status,
            o.amount,
            o.create_time,
            u.user_name,
            u.address,
            u.sex,
            u.birthday
        FROM
            t_order o
                JOIN t_user u ON u.id = o.user_id

主信息:订单信息 t_order

从信息:用户信息 t_user

4.1.1 使用 resultType

使用resultType进行结果映射。

1.分析

1、如果使用resultType进行结果映射,则查询的列名和映射pojo的属性名称要一致。

2、关联查询的结果集,既包含订单信息,又包含用户信息。使用订单po或者用户po类都无法完成结果映射。

3、需要定义扩展po类,此类继承订单信息po类,同时还要包括用户信息:

2.定义pojo 扩展类

扩展Po类中应该包括上边sql查询出来的所有字段,如下:

package com.xa02.domain;

import java.util.Date;

public class OrderExtend extends OrderInfo{
   private String userName;
   private String sex;
   private Date birthday;
   private String address;
  ......
}

OrdersExt类继承OrderInfo类后,便会继承OrderInfo类的所有字段,除此之外只需要定义用户信息字段即可。

3.Mapper文件

在OrderMapper.xml中,添加以下代码:

<select id="selectList"   resultType="OrderExtend">
        SELECT
            o.id,
            o.user_id,
            o.status,
            o.amount,
            o.create_time,
            u.user_name,
            u.address,
            u.sex,
            u.birthday
        FROM
            t_order o
                JOIN t_user u ON u.id = o.user_id
    </select>

4.Mapper接口

在OrderMapper接口中,添加以下接口方法:

public interface OrderMapper {
    List<OrderExtend>  selectList();
}

5.测试代码

在UserMapperTest测试类中,添加测试代码:

@Test
   public void selectList(){
       SqlSession sqlSession = sqlSessionFactory.openSession();
       try{
           OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
           List<OrderExtend> OrderExtendList = orderMapper.selectList();
           System.out.println("selectList....."+OrderExtendList);
       }finally{
           sqlSession.close();
       }
   }

6.小结

1、一对一关联查询时,可以定义专门的扩展po类作为输出结果类型。

2、该扩展po类中定义了sql查询结果集所有的字段对应的属性。

3、此方法较为简单,企业中使用普遍。

4.1.2 使用resultMap

使用resultMap进行结果映射,定义专门的resultMap用于映射一对一查询结果。

1.修改pojo类

在 OrderExtend 类中加入 User 属性,user 属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查

询的用户信息。

public class OrderExtend extends OrderInfo{
    private UserInfo user;

    public UserInfo getUser() {
        return user;
    }

    public void setUser(UserInfo user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "OrderExtend{" +
                "user=" + user +
                '}';
    }
}

2.Mapper映射文件

在OrderMapper.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.xa02.mapper.OrderMapper">
    <!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
    <!--
        1.id 指定 resultMap的唯一表示。
        2.type:指定查询结果要映射的pojo类型。
    -->
    <resultMap id="orderResultMap" type="OrderExtend">
        <!--
		    id标签:映射查询结果的唯一列(主键列)
			column:查询sql的列名
			property:映射结果的属性名
		-->
        <id column="id" property="id"/>
        <!-- result标签:映射查询结果pojo的普通列 -->
        <result column="user_id" property="userId"/>
        <result column="status" property="status"/>
        <result column="amount" property="amount"/>
        <result column="create_time" property="createTime"/>

        <!-- 一对一 映射 -->
        <association property="user" javaType="UserInfo">
            <id column="id" property="id"/>
            <result column="user_name" property="userName"/>
            <result column="sex" property="sex"/>
            <result column="birthday" property="birthday"/>
            <result column="address" property="address"/>
        </association>
    </resultMap>
    <!-- 模糊查询 -->

    <select id="selectList"   resultMap="orderResultMap">
        SELECT
            o.id,
            o.user_id,
            o.status,
            o.amount,
            o.create_time,
            u.user_name,
            u.address,
            u.sex,
            u.birthday
        FROM
            t_order o
                JOIN t_user u ON u.id = o.user_id
    </select>
</mapper>

association:表示进行一对一关联查询映射

property:表示关联查询的结果存储在OrderExtend的user属性中

javaType:表示关联查询的映射结果类型

columnPrefix :查询列的前缀,配置前缀后,在子标签配置 result 的 column 时可以省略前缀

使用resultMap进行结果映射时,具体是使用association完成关联查询的映射,将关联查询信息映射到pojo对象中。

开发小技巧

1.resultMap可以通过使用extends实现继承关系,简化很多配置工作量;

2.关联的表查询的类添加前缀是编程的好习惯;

3.通过添加完整的命名空间,可以引用其他xml文件的resultMap;

4.2 一对多查询

查询所有用户信息及用户关联的订单信息。

  SELECT
            u.id,
            u.user_id,
            u.status,
            u.amount,
            u.create_time,

            o.id,
            o.user_name,
            o.address,
            o.sex,
            o.birthday
        FROM
            t_user  o
                left join  t_order u ON o.id = u.user_id

主信息:用户信息 t_user

从信息:订单信息 t_order

在一对多关联查询时,只能使用resultMap进行结果映射。

1、一对多关联查询时,sql查询结果有多条,而映射对象是一个。

2、resultType完成结果映射的方式的一条记录映射一个对象。

3、resultMap完成结果映射的方式是以[主信息]为主对象,[从信息]映射为集合或者对象,然后封装到主对象中。

在User类中加入List orders属性

public class UserInfo {
    private Long id;
    private String userName;
    private String sex;
    private Date birthday;
    private String address;

    private List<OrderInfo> orderInfoList;

1.Mapper映射文件

<?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.xa02.mapper.UserMapper">
    <!-- 定义resultMap:将查询的列名和映射的pojo的属性名做一个对应关系 -->
    <!--
        1.id 指定 resultMap的唯一表示。
        2.type:指定查询结果要映射的pojo类型。
    -->
    <resultMap id="userResultMap" type="UserInfo">
        <!--
		    id标签:映射查询结果的唯一列(主键列)
			column:查询sql的列名
			property:映射结果的属性名
		-->
        <id column="id" property="id"/>
        <!-- result标签:映射查询结果pojo的普通列 -->
        <result column="user_name" property="userName"/>
        <result column="sex" property="sex"/>
        <result column="birthday" property="birthday"/>
        <result column="address" property="address"/>

        <!-- 一对多关联映射 -->
        <collection property="orderInfoList" ofType="OrderInfo">
            <id column="id" property="id"/>
            <!-- result标签:映射查询结果pojo的普通列 -->
            <result column="user_id" property="userId"/>
            <result column="status" property="status"/>
            <result column="amount" property="amount"/>
            <result column="create_time" property="createTime"/>
        </collection>
    </resultMap>
    <!-- 模糊查询 -->

    <select id="selectList"  resultMap="userResultMap">
        SELECT
            u.id,
            u.user_id,
            u.status,
            u.amount,
            u.create_time,

            o.id,
            o.user_name,
            o.address,
            o.sex,
            o.birthday
        FROM
            t_user  o
                left join  t_order u ON o.id = u.user_id
    </select>

</mapper>

Collection标签:定义了一对多关联的结果映射。

property=*"orderInfoList:*关联查询的结果集存储在User对象的上的属性。

ofType=*“OrderInfo”:*指定关联查询的结果集中的对象类型即List中的对象类型。此处可以使用别名,也可以使用全限定名。

4.3 多对多关联

要实现多对多的关联,需要满足如下两个条件

先决条件一:多对多需要一种中间表建立连接关系

先决条件二:多对多关系是由两个一对多关系组成的,一对多可以也可以用两种方式实现;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏_2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值