hibernate的fetch=“subselect"碰上SQLQuery

探讨了Hibernate中使用子查询fetch模式的局限性和注意事项,包括如何避免批量加载时的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

会变成fetch="select"

 

List<User> users = sesson.createSQLQuery("select {u.*} from user_table u where ...")
                                          .addEntity("u", User.class).list();
for(User u : users){
  Hibernate.initialize(u.getAddresses());
  //just initialize the first entity's collection property,
  // subselect fetch mode will fetch 
  //collection property for all entities in current session.
  break;
}

 观察打印出来的sql:
1.normal sql: select ... from user_table u where ...
2.fetch sql: select ... from address_table a where a.user_id in (?,?,?,...)

fetch sql并非预想中的:select ... from address_table a where a.user_id in (select u.id from user_table u where ...)

 

关于subselect的局限性,GK语焉不详的回答在这里:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-304

结论:
谨慎使用subselect fetch mode,该模式主要是为了防止batch fetch(fetch="select"并设置了相应的batch size)的碎片化,但是使用in语法,值得改进,且某些情况下自动转变成batch fetch。
尽可能使用默认的select fetch mode并合理设置batch fetch size。在主sql已经是分页查询的情况下,subselect fetch mode是没有必要的。在主sql不是分页查询的情况下,估计结果集大小,结果集非常大的情况下,考虑使用subselect fetch。

 

上面这个例子如果非得保持subselect fetch设置,那就按照batch fetch 的方式老老实实的初始化:

 

for(User u : users){
  Hibernate.initialize(u.getAddresses());
}
 



以上仅根据调试结果和hibernate手册,并未研究hibernate源码的具体实现。欢迎指正。

 

另,今天看源码发现是由于CommonLoader出于某种考虑并未覆盖父类的isSubselectLoadingEnabled()所致。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值