• Mybatis关联(嵌套)查询与延迟加载


    我们在查询业务数据的时候经常会遇到关联查询的情况,比如查询员工就会关联部门(一对一),查询学生成绩就会关联课程(一对一),查询订单就会关联商品(一对多),等等。
    在这里插入图片描述
    映射结果有两个标签,一个是,一个是。
    是select标签的一个属性,适用于返回JDK类型(比如Integer. String等等)和实体类。这种情况下结果集的列和实体类的属性可以直接映射。如果返回的字段无法直接映射,就要用来建立映射关系。
    对于关联查询的这种情况,通常不能用来映射。用映射,要么就是修改dto (Data Transfer Object),在里面增加字段,这个会导致增加很多无关的字段。要么就是引用关联的对象,比如Blog里面包含了一个Author对象(多对一),这种情况下就要用到关联查询(association,或者嵌套查询),MyBatis 可以帮我们自动做结果的映射。

    association和collection的区别:
    association是用于一对一和多对一,而collection是用于一对多的关系。
    一对一的关联查询有两种配置方式:

    嵌套结果

        <!-- 根据文章查询作者,一对一查询的结果,嵌套查询 -->
        <resultMap id="BlogWithAuthorResultMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
            <id column="bid" property="bid" jdbcType="INTEGER"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
            <!-- 联合查询,将author的属性映射到ResultMap -->
            <association property="author" javaType="com.gupaoedu.domain.Author">
                <id column="author_id" property="authorId"/>
                <result column="author_name" property="authorName"/>
            </association>
        </resultMap>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    嵌套查询

        <!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
        <resultMap id="BlogWithAuthorQueryMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
            <id column="bid" property="bid" jdbcType="INTEGER"/>
            <result column="name" property="name" jdbcType="VARCHAR"/>
            <association property="author" javaType="com.gupaoedu.domain.Author"
                         column="author_id" select="selectAuthor"/> <!-- selectAuthor 定义在下面-->
        </resultMap>
    
        <!-- 嵌套查询 -->
        <select id="selectAuthor" parameterType="int" resultType="com.gupaoedu.domain.Author">
            select author_id authorId, author_name authorName
            from author where author_id = #{authorId}
        </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    其中第二种方式:嵌套查询,由于是分两次查询,当我们查询了Blog 信息之后,会再发送一条SQL到数据库查询部门信息。

    我们只执行了一次查询Blog信息的SQL(所谓的1),如果返回了N条记录(比如10条Blog),因为一个Blog就有至少一个Author,就会再发送N条到数据库查询Author信息(所谓的N),这个就是我们所说的N+1的问题。这样会白白地浪费我们的应用和数据库的性能。
    如果我们用了嵌套查询的方式,怎么解决这个问题?能不能等到使用Author 信息的时候再去查询?这个就是我们所说的延迟加载,或者叫懒加载。
    在MyBatis里面可以通过开启延迟加载的开关来解决这个问题。

    延迟加载

    在settings标签里面可以配置:

            <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
            <setting name="aggressiveLazyLoading" value="true"/>
            <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
            <setting name="proxyFactory" value="CGLIB" />
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    lazyLoadingEnabled决定了是否延迟加载(默认false)。
    aggressiveLazyLoading决定了是不是对象的所有方法都会触发查询。

  • 相关阅读:
    Redis-列表
    [C++ 从入门到精通] 12.重载运算符、赋值运算符重载、析构函数
    oracle 迁移PG 博客
    进度条——不仅仅是语言层面上的小程序
    3D数据导出工具HOOPS Publish:3D数据查看、生成标准PDF或HTML文档!
    Java进阶(一) Java高效读取大文件,占内存少
    手写深度学习之优化器(SGD、Momentum、Nesterov、AdaGrad、RMSProp、Adam)
    行情分析——加密货币市场大盘走势(10.27)
    Spring Boot多数据源配置并通过注解实现动态切换数据源
    数据同步工具Sqoop
  • 原文地址:https://blog.csdn.net/weixin_44688973/article/details/125895563