java – 懒惰加载处理(Hibernate Spring MVC)


Spring MVC应用程序中处理延迟加载对象的最佳解决方案是什么?我已经对这个主题进行了一些搜索,我找到了以下解决方案:

在视图中打开会话:为每个请求打开一个会话,并在视图呈现后关闭它.这个解决方案的问题是我还需要在Spring MVC模型之外的延迟加载对象(例如Junit测试用例).另一个讨论该解决方案的问题是异常处理.如果事务在视图呈现期间抛出异常怎么办?

明确地打开会话:每当我需要延迟加载对象时,明确地打开一个会话.实际上这个解决方案应该可行,但我不认为这是正确的方法.

使用AOP:创建一个在会话中包装延迟加载方法的方面.这可能是一个解决方案,但我不知道在我的应用程序的哪个级别我应该定义poitcuts

创建自定义查询:为延迟加载创建查询并为急切加载创建查询.这个解决方案实际上有效,但在我看来,懒惰负载模式的应用是错误的

最佳答案 在所有情况下都没有总是更好的解决方案,问题是服务层上的@Transactional在渲染阶段开始时不会保持会话打开.

在渲染开始之前刷新会话,提交事务并关闭会话.

解决此问题的一种方法是使用自定义查询,根据正在构建的视图加载每个时刻所需的数据.

另一种方法是在视图中使用开放会话,这会在渲染时保持会话打开,但由于意外使用延迟加载,它可能会在应用程序中引起N 1问题.

此外,在视图中打开会话可能会导致不可重复读取出现问题,其中一些数据由服务层读取并用于提交事务,但是当视图呈现开始时,数据不再可用或已被修改,这对于建立视图.

从JBoss Seam团队看到这个post对OSIV的使用经历了这些问题(Seam是我开发的许多与Hibernate相同的开发人员).

根据项目的优先顺序,不同的方法有不同的优缺点.如果不必编写自定义查询的便利性是有意义的,因为有许多查询要编写,那么OSIV是一个不错的选择.偶然的N 1问题可以逐案处理并与之共存.

如果重点是控制查询,因为应用程序是性能关键的,那么自定义查询是一种选择.

确实没有明确的最佳解决方案.如果您使用在客户端运行的视图技术(类似angular.js)而不是服务器,那么您不会遇到这类问题,因为不涉及服务器端呈现.

点赞