Mybatis - 延迟加载

2020-04-09  本文已影响0人  zbsong

前两节说到了一对一、一对多和多层级联操作,当多层级联层数太多时,不建议使用级联,会造成复杂度的增加,不利于他人的理解和维护,同时还存在一些劣势,比如有时候并不需要获取所有的数据,,但是级联会多执行几次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日志中可以看到,再次调用即时加载的属性时没有重新执行级联查询,后面的延迟加载对象在我调用时才去查询了对应的数据,这样就实现了局部延迟加载功能。

上一篇下一篇

猜你喜欢

热点阅读