假设有一个类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 阅读(1197)
评论(0) 编辑 收藏 所属分类:
hibernate