【发布时间】:2013-01-29 13:17:18
【问题描述】:
在 Web 应用程序中,我使用 JPA 实体将我的域对象持久保存(和检索)到(和从)底层数据库。
在 Web 应用程序的整个运行时间内,这些 JPA 实体在内存缓存结构中保持“热”(想想Map<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 会话,但我的内存缓存结构中的实体仍期望这些会话中的任何一个存在;在下一个请求触发延迟加载实体机制的那一刻,延迟加载机制找不到任何不再存在的会话。
我的问题有什么解决方案?
【问题讨论】:
-
您能否确保在请求结束之前加载您需要的所有内容,或者在缓存之前复制/克隆到新对象?一般来说,从性能的角度来看,最好尽可能缩短数据库事务。
-
@tofarr 在我的域模型中,JPA 实体类指向其他实体。所以基本上,想象我的实体类是
Person,方法aPerson.getFriends()返回Set<Person>;域模型实例成为网络图。我需要在连续的 HTTP 请求中从Person“跳跃”到Person。如果我加载了所有可能的朋友,朋友的朋友和朋友的朋友的朋友和 (...),那么我需要在我的数据库中加载每个Person以确保我可以访问所有数据。
标签: spring caching jpa httprequest