hibernate的N+1问题
HibernateN+1问题及解决办法
问题出现的原因:
Hibernate中常会用到set,bag等集合表示1对多的关系,在获取实体的时候就能根据关系将关联的对象或者对象集取出,还可以设定cacade进行关联更新和删除。这不得不说hibernate的orm做得很好,很贴近oo的使用习惯了。
但是对数据库访问还是必须考虑性能问题的,在设定了1对多这种关系之后,查询就会出现传说中的n+1问题。
一对多:在一方,查找得到了n个对象,那么又需要将n个对象关联的集合取出,于是本来的一条sql查询变成了n+1条;
多对一:在多方,查询得到了m个对象,那么也会将m个对象对应的1方的对象取出,也变成了m+1;
解决问题的方法:
1、使用fetch抓取,Hibernate抓取策略分为单端代理和集合代理的抓取策略。
Hibernate抓取策略(单端代理的抓取策略):
保持默认也就是如下:
<many-to-onename="clazz"cascade="save-update"fetch="select"/>
fetch="select"就是另外发送一条select语句抓取当前对象关联实体或者集合设置fetch="join"
<many-to-onename="clazz"cascade="save-update"fetch="join"/>
Hibernate会通过select语句使用外连接来加载器关联实体活集合此时lazy会失效
Hibernate抓取策略(集合代理的抓取策略):
保持默认(fetch="select")也就是如下:
<setname="students"inverse="true">
<keycolumn="clazz"/>
<one-to-manyclass="com.june.hibernate.Student"/>
</set>
1)fetch="select"会另外发出一条语句查询集合
2)设置fetch="join"采用外连接集合的lazy失效
3)这只fetch="subselect"另外发出一条select语句抓取前面查询到的所有的实体对象的关联集合fetch只对HQL查询产生影响其他的则不会
2、使用map直接搜索需要的列
如:产品product和产品分类product_category两张表,多对一关系。查询产品列表时
selectnewMap(p.idasid,p.nameasname,p.category.nameascategoryName)fromProductp