Java JPA:如何在HTTP请求中保持会话存活?

时间:2013-01-29 13:17:18

标签: spring caching jpa httprequest

在Web应用程序中,我使用JPA实体将我的域对象持久化(并检索)到底层数据库。 这些JPA实体保持热销&#34;在内存缓存结构中(考虑Map<UniqueID, Entity>),了解Web应用程序的整个运行时间

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

第一个请求已经结束。

我正在对我的网络应用程序执行下一个请求。该请求要求另一个实体。 此实体已经在内存缓存结构中,因此从那里加载。从这个实体,我尝试访问一个应该延迟加载与其他实体的关系的字段。不幸的是,这引起了令人讨厌的org.hibernate.LazyInitializationException: could not initialize proxy - no Session(我使用Hibernate作为我的基础JPA实现)

据我了解,这个例外源于这样的事实:在第一个请求结束后,JPA / Hibernate已经结束了任何JPA会话,但我的内存缓存结构中的实体仍然期望这些会话中的任何一个存在;在下一个请求导致为延迟加载实体启动机制的那一刻,延迟加载机制无法找到任何不再存在的会话。

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

3 个答案:

答案 0 :(得分:2)

  1. 其中一个解决方案是使用Session.update()在第二个请求开始时将实体重新连接到会话。
  2. 另一种解决方案是在Hibernate中使用second level cache而不是您自己的解决方案。它应该比任何本土的缓存机制更可靠。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

session.update(object);

您可以阅读详细信息here