【问题标题】:How does transaction propagation work when using Open Session In View?使用 Open Session In View 时事务传播如何工作?
【发布时间】:2010-12-11 22:24:04
【问题描述】:

我对在 Spring 中使用 Hibernate 进行事务传播感到非常困惑。我在我的服务层方法上使用 Spring @Transactional 注释。有些被标记为“只读=真”。如果我的一个只读服务方法调用了一个非只读的方法,我该如何处理?

我想我可以标记我的所有读写方法以支持REQUIRES_NEW 传播,但这会导致我可能不想要的行为 - 即我只想要一个新事务,以防只读方法称为读写方法。如果一个读写方法调用另一个读写方法,我就不需要新事务了。

考虑到所有这些,我不明白 Open Session In View (OSIV) 的工作原理!当然,在 Spring 中使用 OSIV,OpenSessionInViewFilter 必须在调用服务方法之前启动事务。在这种情况下,它必须定义事务是只读的还是读写的。但是,它怎么会知道呢?它不知道在服务层的掩护下会发生什么。

我对这一切一无所知,希望有人向我解释!

【问题讨论】:

    标签: java hibernate spring transactions


    【解决方案1】:

    Open Session In View 并不要求整个请求发生在单个事务中,这仅意味着 Hibernate Session 绑定到为请求提供服务的线程,并且每次在该请求中请求 Session 时都会重新使用.请记住,Session 就像一个花哨的映射,它维护其范围内映射的所有对象的身份,实际对象可以在一个事务或多个事务中获取。

    Session per Transaction 模式实际上是 OSIV 的一种替代。这种模式并不常见。

    关于你的只读方法调用一个读写方法,我想说你应该重新考虑为什么你要考虑这个只读的,而实际上它可以写入数据。我会争辩说,要么你把只读部分分解出来,让一个读写方法调用一个只读方法,要么你不再认为它是只读的(它不是)。

    仅仅因为一个事务的事务被置于只读模式,并不意味着它将在 Session (OSIV) 的其余范围内保持只读模式。事实上,在打开的 Session 范围内的后续事务甚至可能不会发生在同一个连接上。

    【讨论】:

      【解决方案2】:

      如果您从只读事务方法调用读写事务方法,也会传播只读状态。 IE。整个事务将是只读的。您可能希望将调用方法更改为读写,因为事务实际上应该是读写。

      或者您可以使用 REQUIRES_NEW 传播,但在这种情况下,Spring 会在新事务的生命周期内创建另一个会话。仅在确实需要新事务时使用。

      一个 Hibernate 会话可能包含多个顺序事务。所以 OSIV 过滤器不需要知道它将包含什么样的事务。 OSIV 过滤器使用 FlushMode=MANUAL 创建会话,读写事务方法将临时更改为 FlushMode=AUTO。每个事务将使用只读或读写 JDBC 连接。

      【讨论】:

        【解决方案3】:

        Hibernate 会话的生命周期与事务的生命周期不同。两者可以相互重叠。

        OpenSessionInViewFilter 的情况下,这根本与事务无关,它只是在请求期间管理 Hibernate 会话的生命周期。当调用 Spring 事务方法时,会启动一个新事务,并与休眠会话相关联,然后在方法退出时提交/回滚。当请求完成时,过滤器会关闭会话。无需在会话的同时开始/结束事务。

        至于您的read-only 事务问题(顺便说一句,这完全是一个不同的问题),这实际上只不过是对底层数据库的提示,即不会修改任何数据。我从来没有见过这有什么具体的效果,不过,它作为一个文档工具似乎比其他任何东西都更有用。

        【讨论】:

          猜你喜欢
          • 2011-03-15
          • 1970-01-01
          • 1970-01-01
          • 2011-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-09
          • 2021-10-22
          相关资源
          最近更新 更多