21

我目前将实体 bean 中的集合标记为急于避免在使用 EntityManager 加载 bean 后尝试访问集合属性时出现延迟初始化异常。

如果我将集合保留为延迟加载,如何保持会话打开?我考虑过尝试@Transactional,但即使这有效,我也不想这样做,因为让事务在很长的方法上保持打开状态似乎是不正确的。

4

6 回答 6

9

https://www.hibernate.org/43.html

基本上,你有几个选择。

-您可以使用“在视图中打开会话”模式,其中使用过滤器/拦截器/AOP - 样式逻辑在服务器端逻辑开始时打开会话,并在结束时关闭它。

- 您可以实现跨越多个请求-响应周期的对话。

一个普通的旧 Servlet 过滤器是最简单的。

于 2009-07-16T20:27:02.337 回答
5

最后一个似乎被遗漏的选项是,您可以使用 JOIN 根据您的用例构建对象图。

这将导致对象被初始化,即不会成为代理。

如果您可以控制客户端(即您没有创建发布 API 的开放服务),请使用此方法,因为您需要知道由于事务已关闭而关闭会话时所触及的状态。

于 2009-07-24T15:06:33.890 回答
3

正如其他人所说,您应该阅读“视图中的打开会话”模式,其基本思想是在处理 http 请求的整个过程中打开一个休眠会话。有特定于休眠的解决方案和弹簧解决方案 - 我之前使用过弹簧,它工作正常。

在您提到的问题中,您不想长时间打开交易。对于大多数人来说,这不是问题,因为每个请求的处理速度都相对较快。但是,如果在您的情况下确实不可能这种模式对您不起作用。你能详细说明为什么你不希望交易保持开放吗?

于 2009-07-17T08:14:22.413 回答
1

你在使用 Spring 的 HibernateTemplate 吗?我相信它会为你管理会议。或者,如果您使用的是 Hibernate 3.0.1 或更高版本,Spring 应该仍然能够为您管理会话。

有一个 SpringSource博客条目描述了如何设置它。我在下面包含了一个摘录:

从 Hibernate 3.0.1 开始(以及从它首次发布的那一刻起就在 Java Persistence API 中),Spring 可以管理底层资源,而无需通过任何可用于这些技术的模板。这意味着即使您直接使用 Hibernate API(例如通过 SessionFactory.getCurrentSession()),您仍将使用 Spring 管理的 Hibernate Session。通过 JPA EntityManagerFactory 获得的 EntityManager 也是如此。这是您不必再使用 Spring 的 HibernateTemplate 来获得集成体验的另一个原因。[...]

以下是我们将用于组装应用程序的 XML。如您所见,我们当然仍然使用 Spring 设置 Hibernate 的方式(使用 LocalSessionFactoryBean)。

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <!– the works –&gt;
</bean>
<bean id="accountRepo" class="com.mycompany.HibernateAccountRepository">
  <constructor-arg ref="sessionFactory"/>
</bean>

现在,正如我之前所说,由于 Hibernate 3.0.1 中的一个小改动,Spring 能够为您管理 Hibernate 会话,而无需您通过 Hibernate 会话。缺少的一件事是异常翻译。为了实现这一点,您只需要使用 @Repository 注释(由 Spring 提供)来注释存储库,并使用后处理器打开异常翻译。

@Repository // from org.springframework.stereotype
public class HibernateAccountRepository implements AccountRepository {
    // see above for full impl…
}
于 2009-07-17T06:10:08.937 回答
0

当您打开已读取一些数据的会话时,您将打开该事务。长时间运行的事务并不是什么大问题(尽管这可能取决于您的数据库)真正导致问题的原因是锁持有很长时间,但这些可能只有在您实际更改数据库中的数据时才会创建。同样,这取决于您的数据库。

于 2009-07-16T20:29:10.647 回答
0

现在,我还没有使用过 Spring,但我在几个不同的项目中使用过 Hibernate。我为最近的项目确定的方法源于防御性会话处理模式(与 servlet 过滤器结合使用),我们对此感到满意。您可以在此处找到更多设计模式。

于 2009-07-16T20:32:43.387 回答