Hibernate学习_018_1+N问题

来源:互联网 发布:英语基础入门软件 编辑:程序博客网 时间:2024/06/05 01:15

1+N问题,也叫做N+1问题,在网上(http://ajava.org/article-134-1.html)看到有如下三种情况会出现这种情况:

1)一对多(one-to-many) ,在1的这方,通过1条sql查找得到了1个对象,由于关联的存在 ,那么又需要将这个对象关联的集合取出,所以合集数量是n还要发出n条sql,于是本来的1条sql查询变成了    1 +n条 。

        2)多对一<many-to-one>  ,在多的这方,通过1条sql查询得到了n个对象,由于关联的存在,也会将这n个对象对应的1 方的对象取出, 于是本来的1条sql查询变成了1 +n条 。

        3)iterator 查询时,一定先去缓存中找(1条sql查集合,只查出ID),在没命中时,会再按ID到库中逐一查找, 产生1+n条SQL。

分别测试了第一种和第二种,测试情况是:

一对多(one-to-many):当我们在一的一端设置多的一端的集合,而且我们设置了fetch = fetchType.EAGER,也不会发出N条语句,而只会发出两条语句,第一条取出一这一端的对象,第二条取出这个对象关联的多的一端的对象集合。(不知道是不是自己理解不到位!!

多对一(many-to-one):首先在多的一端设置对一的一端的fetch属性为fetch=fetchType.EAGER,这样,当我们取出多的一端对象的集合的时候,发出了一条SQL语句,然后由于集合中每个对象又关联着一个一的一端的一个对象,所以此时会发出一条语句取出这个一的一端的对象,假设集合大小为N,这个时候就会发出N条这样的语句,通过测试可以看到1+N现象。

1+N问题解决方法:

1:设置FetchType为lazy,这样就不会立刻发出N条语句去取得关联对象。

2:设置@BatchSize,比如对第二种测试情况,当我们设置在一的一端设置@BatchSize,取值为10的时候,本来取出多的一端的集合时,会依次针对集合中的每个对象去取得一的一端的对象,也就是一条一条取得,这个时候,如果一的一端设置了batchSize=10,每次取一的一端的对象的时候,就不是一条一条的取,而是10条10条的去,可以少发90%的SQL语句。

3:使用连接查询,将关联的对象一起取出来。比如Criteria默认就是这么做的。示例代码如下:

(以下三行代码示例背景:Category 和 Topic 类是一对多的关系,而且在Topic的类中存在所属Category的引用,并且fetchType为EAGER。现在是根据取Topic实例集合来测试1+N问题。)

List<Topic> topics = (List<Topic>)session.createCriteria(Topic.class).list();//不会造成1+N问题

List<Topic> topics = (List<Topic>)session.createQuery("from Topic t left join fetch t.category c").list();  //不会造成1+N问题

List<Topic> topics = (List<Topic>)session.createQuery("from Topic").list(); //会造成1+N问题

0 0
原创粉丝点击