假設(shè)有一個(gè)類(lèi)A,它有兩個(gè)屬性property1和property2,則HQL語(yǔ)句"from A as a left outer join a.property1"有一個(gè)原則--HQL語(yǔ)句忽略配置文件的預(yù)先抓取策略,這句話有兩個(gè)意思:
1.不管A類(lèi)對(duì)property1在配置文件里是什么策略(可能是預(yù)先抓取,立即或延遲檢索,它們都失效),這時(shí)都采用HQL指定的左外連接;左外連接必定會(huì)初始化property1屬性(或?qū)ο?,但是如果配置文件里對(duì)property1的檢索策略是延遲加載,A類(lèi)得 到對(duì)properyt1的引用,為了得到這個(gè)引用,需要再次發(fā)送一條SQL語(yǔ)句來(lái)確立這種引用關(guān)系,這種情況在property1為集合時(shí)經(jīng)常出現(xiàn).
2.A類(lèi)在配置文件中設(shè)置的對(duì)property2的預(yù)先抓取策略將被忽略(不管這個(gè)策略是fetch或是select),對(duì)property2有影響的設(shè)置是立即和延遲加載,hibernate只看得到這兩種策略,所以在使用語(yǔ)句"from A as a left outer join a.property1"時(shí),property2的加載策略將僅由lazy="true"或者是lazy="false"來(lái)決定
Team.hbm.xml
... ...
<set name="students" inverse="true" cascade="all" lazy="true" fetch="join"><!-- 一對(duì)多的延遲加載設(shè)置 -->
<key>
<column name="TEAMID" length="32" not-null="true" />
</key>
<one-to-many class="edu.dgut.ke.model.Student" />
</set>
... ...
Student.hbm.xml
... ...
<many-to-one name="certificate"
class="edu.dgut.ke.model.Certificate"
unique="true"
column="cardId"
cascade="all"
lazy="false"
fetch="join">
</many-to-one>
<many-to-one name="team" class="edu.dgut.ke.model.Team" fetch="join">
<column name="TEAMID" length="32" not-null="true" />
</many-to-one>
... ...
測(cè)試代碼
Session session = HibernateSessionFactory.getSession();
List list = session.createQuery("from Student as s left join s.team").list();
HibernateSessionFactory.closeSession();
//list 包括兩個(gè)長(zhǎng)度為2的數(shù)組,每一個(gè)數(shù)組中包括一個(gè)學(xué)生對(duì)象和一個(gè)班級(jí)對(duì)象
Object[] stuAndTeam1 = (Object[]) list.get(0);
Student stu = (Student) stuAndTeam1[0];
System.out.println(stu.getStudentname());
System.out.println(stu.getTeam().getTeamname());
System.out.println(stu.getTeam().getStudents().size());
Hibernate: select student0_.ID as ID0_0_, team1_.ID as ID2_1_, student0_.cardId as cardId0_0_, student0_.TEAMID as TEAMID0_0_, student0_.STUDENTNAME as STUDENTN4_0_0_, team1_.TEAMNAME as TEAMNAME2_1_ from STUDENT student0_ left outer join TEAM team1_ on student0_.TEAMID=team1_.ID
Hibernate: select certificat0_.ID as ID1_0_, certificat0_.`DESCRIBE` as DESCRIBE2_1_0_ from CERTIFICATE certificat0_ where certificat0_.ID=?
Hibernate: select certificat0_.ID as ID1_0_, certificat0_.`DESCRIBE` as DESCRIBE2_1_0_ from CERTIFICATE certificat0_ where certificat0_.ID=?
張三
05計(jì)算機(jī)應(yīng)用技術(shù)(1)班
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: edu.dgut.ke.model.Team.students, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)
at org.hibernate.collection.PersistentSet.size(PersistentSet.java:114)
at edu.dgut.ke.test.chapter3.Query.main(Query.java:44)

注意:在配置文件中設(shè)置的檢索策略只能影響到session.get()或者session.load()方法,對(duì)于直接使用
session.createQuery("from Student as s left join s.team")這種指明HQL的方式,將忽略配置文件的預(yù)先抓取檢索策略(學(xué)生對(duì)班級(jí)的預(yù)先檢索策略被忽略),這語(yǔ)句指明了學(xué)生和班級(jí)之間使用左外連接策略,因此控制臺(tái)輸出的第一條語(yǔ)句,即使用了左外連接得到了3個(gè)對(duì)象:2個(gè)學(xué)生和1個(gè)班級(jí)。
得到了學(xué)生對(duì)象之后,學(xué)生以身份證的預(yù)先抓取策略失效,所以會(huì)有第二條和第三條語(yǔ)句,即使用了立即加載
得到班級(jí)對(duì)象后,由于班級(jí)對(duì)學(xué)生采用延遲加載(這個(gè)策略不會(huì)被忽略),于是班級(jí)的學(xué)生集合并未得到初始化,所以當(dāng)輸出學(xué)生的人數(shù),就拋出了例外。