美文网首页
Mybatis - 延迟加载

Mybatis - 延迟加载

作者: zbsong | 来源:发表于2020-04-09 21:51 被阅读0次

    前两节说到了一对一、一对多和多层级联操作,当多层级联层数太多时,不建议使用级联,会造成复杂度的增加,不利于他人的理解和维护,同时还存在一些劣势,比如有时候并不需要获取所有的数据,,但是级联会多执行几次SQL,将全部关联信息查询出来,这样就会导致执行SQL较多从而导致性能下降。针对这种问题,我们可以使用延迟加载来解决,本节继续使用前两节的demo来演示延迟加载的功能。

    • 全局配置
    1. 修改application.yml 添加延迟加载全局配置
    mybatis:
      mapper-locations: classpath:mappers/*.xml
      configuration:
        #开启延迟加载,默认即时加载
        lazy-loading-enabled: true
        #Mybatis默认是按层级延迟加载的,为true时按层级加载,否则就按我们调用的要求加载
        aggressive-lazy-loading: false
        #打印日志
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
        #指定哪个对象的方法触发一次延迟加载。默认值:equals,clone,hashCode,toString ,可以阻挡不相干的操作触发,实现懒加载
        lazy-load-trigger-methods: ""
    

    注意:实体类中如果是使用的lombok,则加上@ToString(doNotUseGetters = true)

    1. 修改AuthorService,方便查看效果
    @Service
    public class AuthorService {
    
        @Autowired
        private AuthorMapper authorMapper;
    
        public Author getAuthorById(String id) {
            Author author = authorMapper.getAuthorById(id);
            System.out.println("查询作者信息表数据");
            author.getAuthorInformation();
            System.out.println("查询作者的主题表数据");
            author.getSpecials();
            System.out.println("查询作者的文章表数据");
            for (int i = 0; i < author.getSpecials().size(); i++) {
                author.getSpecials().get(i).getArticles();
            }
            return author;
        }
    
    }
    
    测试
    在第一步打个断点,然后调用AuthorService的getAuthorById方法获取作者信息 image.png image.png

    第一步执行结束后可以看到级联的authorInformation和specials信息没有查询出来,级联的SQL也没有执行。

    在return处再打个断点,继续执行代码到return处。 image.png image.png 从执行的sql日志中可以看到,只有当我们调用级联对象数据时才会去查询对应的数据。从上面的结果中可以看出延迟加载生效了。
    • 局部配置

    也有部分场景,需要一部分级联的对象数据即时加载,一部分不需要,这个时候可以使用局部延迟加载的功能,我们可以在 associationcollection元素中加入 fetchType属性实现局部延迟加载功能。
    fetchType有两个取值,如下:
    eager:即时加载
    lazy:延迟加载

    1. 修改AuthorMapper.xml,为association添加 fetchType="eager"实现即时加载,为collection 添加 fetchType="lazy"实现延迟加载
    <resultMap id="BaseResultMap" type="com.sy.mybatis.pojo.Author" >
        <id column="id" property="id" jdbcType="VARCHAR" />
        <result column="name" property="name" jdbcType="VARCHAR" />
        <result column="login_name" property="loginName" jdbcType="VARCHAR" />
        <result column="pwssword" property="pwssword" jdbcType="VARCHAR" />
        <association fetchType="eager" property="authorInformation" column="id" select="com.sy.mybatis.mapper.AuthorInformationMapper.getAuthorInformationbyAuthorId"></association>
        <collection fetchType="lazy" property="specials" column="id" select="com.sy.mybatis.mapper.SpecialMapper.getSpecialsByAuthorId"></collection>
      </resultMap>
    
    测试

    在第一步打个断点,然后调用AuthorService的getAuthorById方法获取作者信息

    image.png image.png 第一步执行结束后可以看到设置了fetchType="eager"即时加载级联的authorInformation对象数据查询了出来,执行了级联SQL,而设置了fetchType="lazy"延迟加载的specials对象信息没有查询出来,级联的SQL也没有执行。 在return处再打个断点,继续执行代码到return处。 image.png image.png

    从执行的sql日志中可以看到,再次调用即时加载的属性时没有重新执行级联查询,后面的延迟加载对象在我调用时才去查询了对应的数据,这样就实现了局部延迟加载功能。

    相关文章

      网友评论

          本文标题:Mybatis - 延迟加载

          本文链接:https://www.haomeiwen.com/subject/smncmhtx.html