如此一来,就有了一个比较尴尬的事了
不管我在一的那一方设不设立fetch=FetchType.eager,我在session里面获得多的那一方的时候,都是可以的。
此时,还不如不设置fetch=FetchType.eager呢,因为有的时候,我确实不需要获得多的那一方,如果一的那一方设置成eager,岂不是要多查询很多无用的数据。
再看一个例子:
//代码8
public void testGetPerson() {
testSavePerson();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
s.getTransaction().commit();
System.out.println(p.getDreams().size());
} 就是把获得多的那一方数据的代码放到了session的外面。
如果此时person那边还有fetch=FetchType.eager,那么一切OK
屏幕上输出:
Hibernate:
select
person0_.id as id1_1_,
person0_.myname as myname1_1_,
dreams1_.personId as personId3_,
dreams1_.id as id3_,
dreams1_.id as id0_0_,
dreams1_.description as descript2_0_0_,
dreams1_.personId as personId0_0_
from
Person person0_
left outer join
Dream dreams1_
on person0_.id=dreams1_.personId
where
person0_.id=?
2 //dream的size是2 可是如果我把fetch=FetchType.eager去掉,在运行代码8,就会报错:
failed to lazily initialize a collection of role: com.bjsxt.hibernate.Person.dreams, no session or session was closed 说的很清楚,session已经关闭了。
为什么呢?
我们知道,从person到dream,是一对多,而默认情况下,一对多的fetch是lazy的。
也就是说,正常情况下,取了pseron是不会再取dream。
我们注意代码7发出的sql,是两个。
现在我要获得多的那方的命令,跑到了sesssion的外面,也就是说在session关闭后再去 数据库里运行sql,那铁定会报错喽。
我们再试试:
//代码9
public void testGetPerson() {
testSavePerson();
Session s = sessionFactory.getCurrentSession();
s.beginTransaction();
Person p = (Person)s.get(Person.class, 2);
s.getTransaction().commit();
System.out.println(p.getDreams().size());
s.getTransaction().commit();
} 此时的person的fetch还是默认的lazy。
是否会报错呢?自己试试吧。
?
关于取对象这部分,hibernate还是比较麻烦的,我认为最好的方法就是保持默认的情况,一旦有了问题再查api文档,或其他的资料。
那既然这样,我为什么还要写这篇博客呢?反正最好的方法就是保持默认情况嘛。
因为:
世之奇伟、瑰怪、非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。