首页 > 技术文章 > 五、级联查询

jdy1022 2020-12-23 10:45 原文

一、商品订单数据模型

 

  • 用户表user:记录了购买商品的用户信息

  • 订单表orders:记录了用户所创建的订单(购买商品的订单)

  • 订单明细表orderdetail:记录了订单的详细信息即购买商品的信息

  • 商品表items :记录了商品信息

 二、案例

注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。

  使用association和collection 完成 订单<--->人一对一关联查询和订单<---->订单明细的一对多查询,将关联查询信息映射到pojo对象中。使用resultMap,定义专门的resultMap用于映射一对一查询结果。

/**
 * 订单信息
 */
@Data
@ToString
public class Orders {

    private Integer id;
    private String number;
    private Date createtime;
    private String note;
    private User user;
    private List<OrderDetail> orderDetails;
}
  • 定义Mapper.xml
    需要关联查询映射的是用户信息,使用association将用户信息映射到订单对象的用户属性中。

     <!--一对一级联查询-->
    <resultMap id="userordermap" type="com.jdy.mybatis2020.bean.Orders">
        <result property="number" column="number"/>
        <association property="user" javaType="com.jdy.mybatis2020.bean.User">
            <id property="id" column="user_id"/>
            <result property="username" column="username"/>
        </association>
     <!--一对多查询-->
<collection property="orderDetails" ofType="com.jdy.mybatis2020.bean.OrderDetail"> <association property="items" javaType="com.jdy.mybatis2020.bean.Items"> <result property="name" column="name"/> <result property="detail" column="detail"/> </association> </collection> </resultMap> <select id="findOrdersMap" resultMap="userordermap"> SELECT USER .id, USER .username, orders.number, items.name, items.detail FROM orders, USER, orderdetail, items WHERE orders.user_id = USER .id AND orders.id = orderdetail.orders_id AND orderdetail.items_id = items.id AND user.id = #{id} </select>
  • association:表示进行关联查询单条记录
  • property:表示关联查询的结果存储在Orders的user属性中。
  • javaType表示关联查询的结果类型
  • collection:表示关联查询结果集
  • property="orderDetails":关联查询的结果集存储在com.jdy.mybaties2020.bean.Orders上哪个属性。
  • ofType="com.jdy.mybaties2020.bean.OrderDetail":指定关联查询的结果集中的对象类型即List中的对象类型

测试

public class Test_02 {

    public static final String RESOURCE = "mybatis-config/mybatis-config_01.xml";

    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void createFactory() {
        sqlSessionFactory = SqlSessionFactoryUtil.createFactory(RESOURCE);
    }

    /**
     * association
     */
    @Test
    public void test_Method00() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        SelectMapperDao dao = sqlSession.getMapper(SelectMapperDao.class);
        List<Map<String, Object>> ordersMap = dao.findOrdersMap("3");
        System.out.println("ordersMap = " + JSON.toJSONString(ordersMap));
    }
}

  resultType

    • 作用:将查询结果按照sql列名pojo属性名一致性映射到pojo中。

    • 场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

   resultMap 使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。

     association:

    • 作用:将关联查询信息映射到一个pojo对象中。

    • 场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中。

    collection:

    • 作用:将关联查询信息映射到一个list集合中。

    • 场合:为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中。

三、分段查询&延迟加载&

3.1、分段查询

  • select:调用目标的方法查询当前属性的值
  • column:将指定列的值传入目标方法

  mapper.xml

    <!-- 订单信息resultmap -->
    <resultMap type="com.jdy.mybatis2020.bean.Orders" id="userordermap2">
        <id property="id" column="id"/>
        <result property="number" column="number"/>
        <association property="user" javaType="com.jdy.mybatis2020.bean.User" select="user.findUserById" column="user_id"/>
    </resultMap>

    <select id="findOrdersList3" resultMap="userordermap2">
         SELECT  orders.*  FROM  orders where id = #{id};
    </select>

 

  分步查询的时候通过column指定,将对应的列的数据传递过去,我们有时需要传递多列数据。使用column ="{key1=column1,key2=column2…}"的形式。

3.1、打开延迟加载

  resultMap可以实现高级映射(使用association、collection实现一对一及一对多映射),association、collection具备延迟加载功能。

  在mybatis核心配置文件中配置: lazyLoadingEnabled、aggressiveLazyLoading

设置项描述允许值默认值
lazyLoadingEnabled 全局性设置懒加载。如果设为‘false’,则所有相关联的都会被初始化加载。 true/false false
aggressiveLazyLoading 当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。 true/false false

  mybatis-config_01.xml

   <settings>
        <!-- 打开延迟加载 的开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改为消极加载即按需要加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

3.2、延迟加载

<!-- 订单信息resultmap -->
    <resultMap type="com.jdy.mybatis2020.bean.Orders" id="userordermap2">
        <id property="id" column="id"/>
        <result property="number" column="number"/>
        <association fetchType="lazy" property="user" javaType="com.jdy.mybatis2020.bean.User" select="user.findUserById" column="user_id"/>
    </resultMap>

    <select id="findOrdersList3" resultMap="userordermap2">
         SELECT  orders.*  FROM  orders where id = #{id};
    </select>

  association或者collection标签的 fetchType=eager/lazy可以覆盖全局的延迟加载策略, 指定立即加载(eager)或者延迟加载(lazy)

延迟加载小结

  • 作用:当需要查询关联信息时再去数据库查询,默认不去关联查询,提高数据库性能。 只有使用resultMap支持延迟加载设置。

  • 场合:

    • 当只有部分记录需要关联查询其它信息时,此时可按需延迟加载,需要关联查询时再向数据库发出sql,以提高数据库性能。

    • 当全部需要关联查询信息时,此时不用延迟加载,直接将关联查询信息全部返回即可,可使用resultType或resultMap完成映射。

 

推荐阅读