1

在 Web 应用程序中,我使用 JPA 实体将我的域对象持久保存(和检索)到(和从)底层数据库。 这些 JPA 实体在 Web 应用程序的整个运行时间内保持“热”在内存中的缓存结构(想想 aMap<UniqueID, Entity> )中。

所以我正在向我的 Web 应用程序发出请求,从存储库中加载了一个实体。该实体被放入内存缓存结构中。在这个请求的整个生命周期中,我可以愉快地访问这个实体的任何字段。在第一个请求期间,延迟加载与其他实体的关系也可以正常工作,即使在我的View: 我成功地使用Open-Session-in-View 模式(通过 Spring 的OpenEntityManagerInViewInterceptor)。

第一个请求已结束。

我正在向我的 Web 应用程序发出下一个请求。此请求要求另一个实体。这个实体已经在内存缓存结构中,所以它是从那里加载的。从这个实体中,我尝试访问一个应该延迟加载与其他实体的关系的字段。不幸的是,这令人讨厌 org.hibernate.LazyInitializationException: could not initialize proxy - no Session(我使用 Hibernate 作为我的底层 JPA 实现)

据我了解,此异常源于这样一个事实,即在第一个请求结束后,JPA/Hibernate 已结束任何 JPA 会话,但我的内存缓存结构中的实体仍然希望这些会话中的任何一个存在;在下一个请求触发延迟加载实体机制的那一刻,延迟加载机制找不到任何不再存在的会话。

我的问题有什么解决方案?

4

3 回答 3

2
  1. 一种解决方案是在第二个请求开始时使用Session.update().
  2. 另一种解决方案是在 Hibernate 中使用二级缓存而不是您自己的解决方案。它应该比任何本地缓存机制更可靠。
于 2013-01-29T13:25:15.187 回答
0

您收到此异常是因为您的对象已与当前会话分离。在评估它之前,您必须将此对象重新附加到当前会话

session.update(object);

您可以在此处阅读详细信息

于 2013-01-29T13:32:45.483 回答
0

基本上,您不能在 HTTP 请求之间保持会话处于活动状态,因为这意味着在请求之间保持事务打开。

我认为唯一的解决方案(除了检测自己加载的内容和未加载的内容)是在将其放入缓存之前获取整个实体。恕我直言,您不应该将部分加载的对象放入缓存中。如果您不想第一次加载整个对象,则可以为对象关系使用单独的缓存。

如果您愿意,您也可以考虑按照@Adam 的建议启用 Hibernate 缓存,但我认为它不适用于女士加载字段。

于 2013-01-29T13:28:41.687 回答