Java Hibernate中会话关闭时的延迟加载
输出:仔细查看输出有两个select查询,一个用于用户,另一个用于调用Java Hibernate中会话关闭时的延迟加载,java,hibernate,Java,Hibernate,输出:仔细查看输出有两个select查询,一个用于用户,另一个用于调用getListOfAddresses()时的地址表 现在,如果您更改为该类文件的一些代码行,以验证代理对象。 在调用getListOfAddresses()方法关闭会话之前,会发生这种情况 log4j:WARN No appenders could be found for logger (org.hibernate.cfg.annotations.Version). log4j:WARN Please initialize
getListOfAddresses()
时的地址表
现在,如果您更改为该类文件的一些代码行,以验证代理对象。 在调用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
现在输出:
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());
如上所述,代码运行失败,因为当我们使用获取对象的惰性类型策略时,hibernate会话返回代理对象,如果我们关闭会话,它存在于会话中,那么惰性加载不会发生 对于即时抓取:
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)
输出:
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());
}
}
二,******************************************************************************
请看,这段代码正在成功运行,因为我们使用的是急切抓取策略,所以在这个策略会话中,返回原始对象,所有字段都在加载到内存时初始化。
在上面的输出字符串中,请仔细查看,只有一个带有join子句的select语句
我只想知道,即使在明确结束会议之后
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=?
执行良好。
因此,HIBERNATE从何处加载上述集合。它来自一级缓存。
即使在即时抓取中关闭会话后,对象是否仍保留在那里(我知道依赖对象也会加载)?延迟加载是什么情况?由于集合未加载,这就是
System.out.println(user.getLisOfAddresses().size());
在会话关闭后显示延迟加载错误,并且在会话关闭后调用GETTER?
有人能反思一下吗?
我知道什么是懒惰和急切的获取?一个问题上的问题太多了。 嗯,Hibernate正在做你要求它做的事情。 您需要知道
get
和load
之间的区别。当您确实获取时,Hibernate从DB获取对象。当您执行加载操作时,Hibernate生成并代理对象,并且在您真正需要它之前不会加载该对象(直到您调用getter或类似的东西)
是的,关闭会话不会使您的初始化(从db对象读取)变为null,而是使这些对象变为null。请参阅hibernate文档中分离的含义。但对象本身将一直保留,直到GC将其销毁
I JUST WISH TO KNOW THAT EVEN AFTER CLOSING THE SESSION EXPLICITLY,
System.out.println(user.getLisOfAddresses().size());
EXECUTES FINE.
这正是分离对象+延迟加载的原因。您的lisofaddress
未加载,并且user
对象已分离(这意味着未附加任何hibernate会话)。因此,它有一个代理,它会在假定user
对象连接到hibernate会话的情况下尝试命中db,这在您的情况下是错误的,但在正确的情况下失败了
System.out.println(user.getLisOfAddresses().size());
I JUST WISH TO KNOW THAT EVEN AFTER CLOSING THE SESSION EXPLICITLY,
System.out.println(user.getLisOfAddresses().size());
EXECUTES FINE.
`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