假設有一個類A,它有兩個屬性property1和property2,則HQL語句"from A as a left outer join a.property1"有一個原則--HQL語句忽略配置文件的預先抓取策略,這句話有兩個意思:
1.不管A類對property1在配置文件里是什么策略(可能是預先抓取,立即或延遲檢索,它們都失效),這時都采用HQL指定的左外連接;左外連接必定會初始化property1屬性(或對象),但是如果配置文件里對property1的檢索策略是延遲加載,A類得 到對properyt1的引用,為了得到這個引用,需要再次發送一條SQL語句來確立這種引用關系,這種情況在property1為集合時經常出現.
2.A類在配置文件中設置的對property2的預先抓取策略將被忽略(不管這個策略是fetch或是select),對property2有影響的設置是立即和延遲加載,hibernate只看得到這兩種策略,所以在使用語句"from A as a left outer join a.property1"時,property2的加載策略將僅由lazy="true"或者是lazy="false"來決定

Team.hbm.xml
... ...
<set name="students" inverse="true" cascade="all" lazy="true" fetch="join"><!-- 一對多的延遲加載設置 -->
<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>
... ...
測試代碼
Session session = HibernateSessionFactory.getSession();
List list = session.createQuery("from Student as s left join s.team").list();
HibernateSessionFactory.closeSession();
//list 包括兩個長度為2的數組,每一個數組中包括一個學生對象和一個班級對象
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計算機應用技術(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)
注意:在配置文件中設置的檢索策略只能影響到session.get()或者session.load()方法,對于直接使用
session.createQuery("from Student as s left join s.team")這種指明HQL的方式,將忽略配置文件的預先抓取檢索策略(學生對班級的預先檢索策略被忽略),這語句指明了學生和班級之間使用左外連接策略,因此控制臺輸出的第一條語句,即使用了左外連接得到了3個對象:2個學生和1個班級。
得到了學生對象之后,學生以身份證的預先抓取策略失效,所以會有第二條和第三條語句,即使用了立即加載
得到班級對象后,由于班級對學生采用延遲加載(這個策略不會被忽略),于是班級的學生集合并未得到初始化,所以當輸出學生的人數,就拋出了例外。
posted on 2007-11-06 15:08
Ke 閱讀(1202)
評論(0) 編輯 收藏 所屬分類:
hibernate