mybatis注解方式懒加载失效分析

本人在使用spring mvc + mybatis的后台结构的项目的时候,在使用mybatis的懒加载出现了一些问题:

明明懒加载的配置都正确了,但就是用debug断点调试的时候懒加载的属性总是提前加载,在经过几天的不断努力之后,终于发现了原因:

mybatis懒加载配置:

<!-- 查询时,关闭关联对象即时加载以提高性能 -->
<setting name="lazyLoadingEnabled" value="true" />
<!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能 -->
<setting name="aggressiveLazyLoading" value="false" />


懒加载查询语句:

@Select("select * from user_main where username=#{username}")
	@Results({
	      @Result(property = "roleNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getRoleNamesByUserId")),
	      @Result(property = "permissionNames", column = "id", many = @Many(fetchType=FetchType.LAZY,select = "getPermissionsByUserId"))
	  })
public UserPO getUserByUsername(@Param("username")String username);

测试用例:

	@Test
	  public void testGetUserByUsername() throws Exception {
	    SqlSession session = sqlSessionFactory.openSession();
	    try {
	      UserMapper userMapper = session.getMapper(UserMapper.class);
	      UserPO userPo = userMapper.getUserByUsername("zhangsan");
	      System.out.println(userPo);
	      System.out.println(userPo.getPermissionNames());
//	      List<String> map = userMapper.getRoleMain();
//	      System.out.println(map);
	      session.close();
	    } finally {
	      session.close();
	    }
	  }

结果调试测试用例的时候,使用debug却发现懒加载并没有生效,后来看了mybatis懒加载的源码,依然没有发现原因,感觉就是roleNames和permissionNames就是突然的加载了,断点也捕捉不到,也没有博捉到触发的事件,这时楼主我就很奇怪了,最后经过几天的努力终于发现了原因:

mybatis源码:configuration

protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] { "equals", "clone", "hashCode", "toString" }));

默认这四个方法或触发懒加载,当然,触发懒加载的方法还有getRoleNames 和 getPermissions ,这两个(只针对当前实例)

然后通过sysout输出的时候,发现hashcode和equals方法被莫名的触发了,而且debug断点还捕捉不到,然后roleNames和permissionNames就被莫名的加载了

最后发现,这个问题和debug的原理有一定的关系,



原来,在显示debug的黄色框框时,debug会另起一个线程,然后重新调用一遍代码,然后显示userpo信息的时候,又会调用userpo的hashcode方法和tostring方法,

这样的话,就会导致这两个方法会在debug线程内触发懒加载,造成的效果就是懒加载失效,但是实际上懒加载是生效了的,只是在debug模式上被触发了,而且用断点还捕捉不到,就会形成一个奇怪的问题,如果想用debug来查看效果,也是很简单:

通过将触发默认的四个方法屏蔽来查看效果,但是不支持,因为这样的话,可能会影响实体的hash排序等问题,即使是用了这个方法,也是建议看完效果以后改成默认的

这种事代码方式的,还有一种是配置文件方式的(自己从网上找)

configuration.setLazyLoadTriggerMethods(new HashSet<String>());


还有一种更好的方式来查看懒加载的效果,那就是mybatis的默认日志,建议将日志级别调成debug(这个debug级别和debug模式不一样),然后执行的时候就可以通过sql语句的打印来判断懒加载是否生效。


其实这个问题的分析最后,还是在说debug断点调试的问题,它的这种原理需要注意,特别是会在另一个线程调用hashcode和tostring方法,相信在很多方面会影响到我们,希望大家能够注意





 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值