• [07] 延迟加载



    现在我们有 Author 作者类,其属性中有 List<Book> bookList 用来表示该作者所出版的书籍。我们配置好映射关系之后,希望在获取到一个 Author 类时,其 bookList 的值只有当我们在用到的时候才会去数据库获取,而不是每次都给我们全部的完整数据,这也就是MyBatis延迟加载要解决的问题:即映射集合内存在级联时,我们实际需要的数据少于数据库查出来的数据。这就会造成数据库多查出来的数据派不上用场,同时也加大了数据库负担。

    我们在提到 MyBatis 的内联时,必然会涉及到的就是两个元素 association 和 collection,在之前的阐述中我们也说过,对于内联查询的方式有一种利用到了 select 属性,也即是我们延迟加载的主人公。我们说使用 select 实际上是将SQL语句分成了两部分单独执行,而不是采用联表查询的SQL,也正是这样,能让我们实现延迟加载。

    在MyBatis中实现延迟加载有两种方式,如果你希望全局开启延迟加载,那么你需要在mybatis-config.xml全局配置文件的<settings>中加入下面这两个配置:
    <!--开启全局延迟加载(懒加载)-->
    <setting name="lazyLoadingEnabled" value="true" />
    <!--任何方法调用均加载该对象所有属性-->
    <setting name="aggressiveLazyLoading" value="false"/>

    如果你并不想全局开启,只是针对某个类的某些属性进行延迟加载开启,那么则需要你在 resultMap 中的 association 或 collection 设置属性值 fetchType="lazy",如下示例:
    <association fetchType="lazy" property="author" column="author_id" javaType="dulk.learn.mybatis.pojo.Author" select="findAuthorById"/>

    刚才我们提到了作者和书之间的一对多关系,下面我们就来以此为例看下相关的代码和配置。

    Author类:
    public class Author {
        private long id;
        private String name;
        private int age;
        private List<Book> bookList;
    
        //... getter and setter
    }

    Dao接口:
    public interface AuthorDao {
        Author findAuthorById(long id);
        Book findBookByAuthorId(long authorId);
    }

    mapper.xml:
    <mapper namespace="dulk.learn.mybatis.dao.AuthorDao">
    
        <resultMap id="authorResultMap" type="dulk.learn.mybatis.pojo.Author">
            <id property="id" column="id"/>
            <result property="name" column="name" />
            <result property="age" column="age" />
            <!--采用select形式,设定fetchType延迟加载,column为关联查询的列-->
            <collection fetchType="lazy" property="bookList" column="id" select="findBookByAuthorId" />
        </resultMap>
    
        <select id="findAuthorById" parameterType="long" resultMap="authorResultMap">
            SELECT *
            FROM author
            WHERE id = #{id}
        </select>
    
        <select id="findBookByAuthorId" parameterType="long" resultType="dulk.learn.mybatis.pojo.Book">
            SELECT *
            FROM book
            WHERE author_id = #{authorId}
        </select>
    
    </mapper>
    • 使用select方式加载内联属性的数据(而非联表查询)
    • 设置全局延迟加载,或者局部设置 fetchType="lazy"
    • column列为关联查询的列

    写个单元测试看看:
    public class TestAuthor {
    
        @org.junit.Test
        public void testMyBatis() throws IOException {
            //读取配置文件
            InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
            //获取工厂类
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
            //获取SqlSession数据库会话对象
            SqlSession sqlSession = factory.openSession();
            //获取Dao
            AuthorDao authorDao = sqlSession.getMapper(AuthorDao.class);
    
            Author author = authorDao.findAuthorById(2);
            System.out.println("-------------------------------------");
            List<Book> bookList = author.getBookList();
        }
    
    }

    如下输出日志,可以看到bookList在调用时才执行了SQL语句去查询:
    Opening JDBC Connection
    Created connection 1685232414.
    Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@64729b1e]
    ==>  Preparing: SELECT * FROM author WHERE id = ? 
    ==> Parameters: 2(Long)
    <==    Columns: id, name, age
    <==        Row: 2, 李四, 18
    <==      Total: 1
    -------------------------------------
    ==>  Preparing: SELECT * FROM book WHERE author_id = ? 
    ==> Parameters: 2(Long)
    <==    Columns: id, name, price, author_id
    <==        Row: 1, 小帽子历险记, 23, 2
    <==        Row: 2, 红帽子探险记, 12, 2
    <==      Total: 2


  • 相关阅读:
    html+css
    HTML的矢量图转换文字
    js初级——复习html+css-下拉标志
    js初级——复习html+css
    四方定理(递归) --java
    进制转换模板
    最大值最小化问题 和最小值最大化问题 ---(二分)
    分治法---循环日程表问题
    全排列 ---java
    并查集---java模板
  • 原文地址:https://www.cnblogs.com/deng-cc/p/9341742.html
Copyright © 2020-2023  润新知