【问题标题】:Inject Session object to DAO bean instead of Session Factory?将会话对象注入DAO bean而不是会话工厂?
【发布时间】:2013-05-31 02:37:12
【问题描述】:

在我们的应用程序中,我们使用 Spring 和 Hibernate。

在所有的 DAO 类中,我们都有 SessionFactory 自动连接,并且每个 DAO 方法都调用 getCurrentSession() 方法。

我的问题是为什么我们不在原型范围内注入 Session 对象而不是 SessionFactory 对象?这将为我们节省对 getCurrentSession 的调用。

我认为第一种方法是正确的,但正在寻找第二种方法会引发错误或性能不佳的具体场景?

【问题讨论】:

  • 一个案例阅读the doc,上面写着If the Session throws an exception, the transaction must be rolled back and the session discarded. The internal state of the Session might not be consistent with the database after the exception occurs.
  • 你最好注入javax.persistence.EntityManager 但为此你必须坚持使用JPA。

标签: spring hibernate


【解决方案1】:

当您将 bean 定义为原型作用域时,会为每个需要注入它的位置创建一个新实例。所以每个 DAO 都会得到一个不同的 Session 实例,但是 DAO 上的所有方法调用最终都会使用同一个 session。由于会话不是线程安全的,因此不应在多个线程之间共享,这将是一个问题。

在大多数情况下,会话应该是事务范围,即在事务开始时打开一个新会话,然后在事务完成后自动关闭。在少数情况下,它可能必须扩展到请求范围。

如果您想避免使用 SessionFactory.currentSession - 那么您需要定义自己的作用域实现来实现。

这是已经使用代理为 JPA 实现的东西。在 JPA 的情况下,注入的是 EntityManager 而不是 EntityManagerFactory。代替 @Autowired 有一个新的 @PersistenceContext 注释。在初始化期间创建并注入代理。当调用任何方法时,代理将获取实际的 EntityManager 实现(使用类似于 SessionFactory.getCurrentSession 的东西)并委托给它。

Hibernate 也可以实现类似的功能,但额外的复杂性是不值得的。在内部调用 SessionFactory.getCurrentSession() 的 BaseDAO 中定义 getSession 方法要简单得多。有了这个,使用会话的代码与注入会话相同。

【讨论】:

    【解决方案2】:

    注入原型会话意味着您的每个 DAO 对象都将根据定义获得自己的会话...另一方面,SessionFactory 使您可以随意使用open 并共享会话。

    事实上,getCurrentSession 不会在每次调用时都打开一个新会话...相反,它会重用绑定到 current session context 的会话(例如,线程、JTA Transacion 或外部托管上下文)。

    所以让我们考虑一下;假设在您的业务层中有一个操作需要读取和更新多个数据库表(这意味着直接或间接地与多个 DAO 交互)......很常见的场景对吧?通常,当这种操作失败时,您会想要回滚当前操作中发生的所有事情,对吧?那么,对于这种“特殊”情况,什么样的策略似乎合适呢?

    1. 跨越多个会话,每个会话管理自己类型的对象并绑定到不同的事务。
    2. 让一个会话管理与此操作相关的对象...根据您的业务需求划分事务。

    简而言之,有效地共享会话和划分事务不仅会提高您的应用程序性能,它还是您的应用程序功能的一部分。

    我强烈建议您阅读Hibernate Core Reference Manual 中的Chapter 2Chapter 13,以更好地了解SessionFactorySessionTransaction 在框架中扮演的角色。它还将教授有关工作单元以及流行的会话模式和反模式的意愿。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多