原文传送门:http://www.lifevv.com/tenyo/doc/20080228221516487.html
什么是N+1问题呢?
我们举一个例子来说明这个问题。
还是以 husband vs wife(夫:妻) 模型为例。
他们是一对一(one-to-one)的关系。并假设HUSBAND表为主表,WIFE表为从表。
CreateTables.sql
# # husband TABLE # CREATE TABLE HUSBAND ( ID CHAR(32) NOT NULL, NAME CHAR(32) NOT NULL, PRIMARY KEY(id) ) # # wife TABLE # CREATE TABLE WIFE ( ID CHAR(32) NOT NULL, NAME CHAR(32) NOT NULL, HUSBAND_ID CHAR(32) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(HUSBAND_ID) REFERENCE HUSBAND(ID) )
<one-to-one name="wife" cascade="all" class="mypackage.Wife" property-ref="husbandId" > </one-to-one>
方法一:重新定义表结构,把关联字段放在主表一方。
然后在主表一方用many-to-one关联从表。
这种方法比较直观,也是最容易想到的方法。如下:
表HUSBAND定义:
CREATE TABLE HUSBAND ( ID CHAR(32) NOT NULL, NAME CHAR(32) NOT NULL, WIFE_ID CHAR(32) NOT NULL, PRIMARY KEY(id), FOREIGN KEY(WIFE_ID) REFERENCE WIFE(ID) )
<many-to-one name="wife" column="WIFE_ID" not-null="false" cascade="all" class="mypackage.Wife" > </many-to-one>
<many-to-one name="wife" not-null="false" cascade="all" class="mypackage.Wife" > <formula>(select w.ID from WIFE w where w.HUSBAND_ID = ID)</formula> </many-to-one>
解说:
<formula>(select w.ID from WIFE w where w.HUSBAND_ID = ID)</formula>
该formula告诉HIBERNATE怎么与让Husband与Wife关联。
这样查询时,只会向数据库发送一条数据。
但是,如果需要从Husband对象存取Wife对象 [调用Husband.getWife()方法] 时:
List <Husband> list = query.list();
list.get(0).getWife();
Hibernate会动态向数据库发送一条查询数据。所以第2种方法,若要在页面上同时显示多条主表Husband与从表Wife的混合数据时,显然也会发生N+1问题。
但若只是显示多条Husband数据时,只发送一条SQL语句。