在Hibernate中延迟加载WITH SESSION CLOSED

时间:2014-05-11 13:22:15

标签: java hibernate

SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory(); 
        Session session = sessionFactory.openSession(); // create session object
        session.beginTransaction(); // start transaction object
        session.save(user); // save the user to database 
        session.getTransaction().commit(); // commit the transaction
        session.close(); // closing session

         session = sessionFactory.openSession();   
         user = null;
         user = (UserDetails) session.get(UserDetails.class, 1); 
         System.out.println(user.getLisOfAddresses().size());
    }
}

输出:完全注意输出有两个选择查询,一个用于用户,另一个用于地址表,当我们调用getListOfAddresses();

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_DETAIL (USER_NAME) values (?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_DETAIL userdetail0_ where userdetail0_.USER_ID=?
Hibernate: select lisofaddre0_.USER_ID as USER1_0_, lisofaddre0_.CITY_NAME as CITY2_0_, lisofaddre0_.PIN_CODE as PIN3_0_, lisofaddre0_.STATE_NAME as STATE4_0_, lisofaddre0_.STREET_NAME as STREET5_0_ from USER_ADDRESS lisofaddre0_ where lisofaddre0_.USER_ID=?
2

现在,如果您更改此类文件的某些代码行以验证PROXY对象。 在调用getListOfAddresses()方法关闭会话之前,会发生这种情况。

         session = sessionFactory.openSession(); // again create another session object  
         user = null;
         user = (UserDetails) session.get(UserDetails.class, 1); 
          session.close(); // close the session before calling collection getter 
         System.out.println(user.getLisOfAddresses().size());

现在输出:

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_DETAIL (USER_NAME) values (?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_ from USER_DETAIL userdetail0_ where userdetail0_.USER_ID=?
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.sdnext.hibernate.tutorial.dto.UserDetails.lisOfAddresses, no session or session was closed
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException
(AbstractPersistentCollection.java:380)
    at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected
(AbstractPersistentCollection.java:372)
    at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:119)
    at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
    at com.sdnext.hibernate.tutorial.HibernateTestDemo.main(HibernateTestDemo.java:48)

由于上面的代码运行失败,因为当我们使用LAZY Type策略获取对象时,hibernate会话返回代理对象,如果我们正在关闭会话,则会在会话中存在延迟加载没有发生。

渴望获取:

 SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        session.save(user);
        session.getTransaction().commit();
        session.close();

         session = sessionFactory.openSession();
         user = null;
         user = (UserDetails) session.get(UserDetails.class, 1);
         session.close(); //closing the session before calling collection getter
         System.out.println(user.getLisOfAddresses().size());
      }
}

输出:

log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version).
log4j:WARN Please initialize the log4j system properly.
Hibernate: insert into USER_DETAIL (USER_NAME) values (?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: insert into USER_ADDRESS (USER_ID, CITY_NAME, PIN_CODE, STATE_NAME, STREET_NAME) values (?, ?, ?, ?, ?)
Hibernate: select userdetail0_.USER_ID as USER1_0_0_, userdetail0_.USER_NAME as USER2_0_0_, lisofaddre1_.USER_ID as USER1_2_, lisofaddre1_.CITY_NAME as CITY2_2_, lisofaddre1_.PIN_CODE as PIN3_2_, lisofaddre1_.STATE_NAME as STATE4_2_, lisofaddre1_.STREET_NAME as STREET5_2_ from USER_DETAIL userdetail0_ left outer join USER_ADDRESS lisofaddre1_ on userdetail0_.USER_ID=lisofaddre1_.USER_ID where userdetail0_.USER_ID=?

2 ********************************************** ******************************** 看到这段代码运行成功,因为我们正在使用EAGER获取策略,因此在此策略会话中返回原始对象,并在内存加载时初始化所有字段。  在上面的输出字符串中,看起来完全只有一个带有join子句的select语句。

我只是想知道即使在会议结束后也要知道,

 System.out.println(user.getLisOfAddresses().size());

执行罚款。 因此,HIBERNATE正在加载上面的收藏品。是第一级高速缓存。 在EAGER FETCHING中关闭会​​话之后,对象是否仍然存在(我知道相关对象也会被加载)?什么是懒惰的情况?由于收集没有加载,这是非常原因

System.out.println(user.getLisOfAddresses().size()); 

会议结束后是否会在会议结束时收到错误,并在闭幕后收到通知? COULS有人反思这个? 我知道什么是懒惰和EAGER FETCHING?

1 个答案:

答案 0 :(得分:1)

关于一个问题的问题太多了。 好吧,Hibernate正在做你要求它做的事情。 您需要了解getload之间的区别。当你得到,Hibernate从数据库获取并反对。当你做load Hibernate制作和代理对象时,在你真正需要它之前不会加载对象(直到你在它上面调用getter或类似的东西)。

I JUST WISH TO KNOW THAT EVEN AFTER CLOSING THE SESSION EXPLICITLY,

 System.out.println(user.getLisOfAddresses().size());

EXECUTES FINE.

是的,关闭会话不会使您的初始化(从db对象读取)为null,而是使这些对象成为detached。从hibernate文档中查看分离的含义。但是对象本身将一直存在直到GC消失它。

 `SINCE THE COLLECTION IS NOT LOADED, IS IT THIS VERY REASON THAT

System.out.println(user.getLisOfAddresses().size()); 

SHOWS ERROR IN LAZY LOADING AFTER SESSION IS CLOSED AND GETTER IS CALLED AFTER CLOSING THE SESSION

这正是分离对象+延迟加载的原因。您的LisOfAddresses未加载且user对象已分离(这意味着未附加任何休眠会话)。所以它有代理试图命中db假设user对象附加到hibernate会话,这在你的情况下是错误的并且失败是正确的。