Spring - 事务只读

24

我想听听您对Spring声明式事务管理的专业意见。这是我的设置:

  1. DAO层是使用Spring JdbcTemplate的普通旧JDBC(没有Hibernate等)
  2. 服务层是一个POJO,具有如下的声明性事务 - save*,readonly=false,rollback for Throwable

在上述设置下工作得很好。然而,当我说get*,readonly=true时,我在日志文件中看到错误,说数据库连接无法标记为只读。这发生在服务层的所有get*方法中。

现在我的问题是:

A. 我必须把get*设置为只读吗?我所有的get*方法都是纯读取数据库操作。我不希望在任何事务上下文中运行它们。上述错误有多严重?

B. 当我删除get*配置时,我就不会看到错误了。此外,我所有简单的get*操作都是在没有事务的情况下执行的。这是正确的方式吗?

C. 为什么有人要有readonly=true的事务方法?这种配置有什么实际意义吗?

谢谢!一如既往,非常感谢您的回复!

2个回答

24

这篇文章 提到 readOnly 标志的行为取决于持久化机制。

C. 是的,在使用 Hibernate 时,将 flush 模式设置为 FLUSH_NEVER(如链接的文章所述)可以提高性能。

B. 是的,JDBC 调用不需要事务(Hibernate 需要),因此去掉 @Transactional 配置可以去除所有的事务管理。

A. 我猜想 Spring 会调用 connection.setReadOnly(true),但是你的 JDBC 驱动程序不支持这个方法。

底线是:不要在纯 JDBC 中使用只读事务。

还有一件事情——事务应该跨越多个查询。不要让事务过于细粒度,要让它们成为一个工作单元


谢谢Bozho!一清二楚。我想我会删除get*配置,因为我正在使用普通的JDBC。 - AAK
1
如果没有只读事务,您也会遇到可怕的 org.hibernate.LazyInitializationException 异常。 - Dave
我该如何避免在使用Waffle身份验证管理器时出现org.hibernate.LazyInitializationException异常? - Pablo Jomer
链接已失效 link - G 1

5
A. 我必须将所有的get*方法标记为只读吗?我的所有get*方法都是纯读取数据库操作,我不希望在任何事务上下文中运行它们。上述错误有多严重?
实际上,您可能仍然希望在事务上下文中运行所有的get()方法,以确保您获得一致的读取结果。如果您不关心这个问题,您可以相应地设置事务级别。
C. 为什么有人想要将只读=true的事务性方法?这种配置有什么实际意义吗?
1. 在get()方法中帮助防止写操作异常 2. 出于优化目的。Hibernate不仅可以利用此信息,如Bozho所提到的,而且某些数据库/JDBC驱动程序也可以利用此信息。

谢谢Matt!我想我的get*方法基本上是简单的独立SQL选择查询,我没有使用Hibernate,所以我会关闭这个设置。 - AAK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接