spring - Grails 服务事务行为

标签 spring grails groovy transactions spring-transactions

在 Grails 应用程序中,服务方法的默认行为是它们是事务性的,如果抛出未经检查的异常,事务会自动回滚。但是,在 Groovy 中,不会强制处理(或重新抛出)受检异常,因此存在如果服务方法抛出受检异常,事务将不会回滚的风险。鉴于此,注释每个 Grails 服务类似乎是可取的

@Transactional(rollbackFor = Throwable.class) 
class MyService {

    void writeSomething() {
    }
}

假设我在 MyService 中有其他方法,其中一个只读取DB,另一个不接触DB,以下注释是否正确?
@Transactional(readOnly = true)
void readSomething() {}

// Maybe this should be propagation = Propagation.NOT_SUPPORTED instead?
@Transactional(propagation = Propagation.SUPPORTS)
void dontReadOrWrite() {}

为了回答这个问题,我想你需要知道我的意图是什么:
  • 如果任何方法抛出异常并且正在进行事务,它将回滚。例如,如果 writeSomething()来电dontReadOrWrite() ,而后者抛出异常,则前者启动的事务将被回滚。我假设 rollbackFor类级属性由各个方法继承,除非它们显式覆盖它。
  • 如果没有正在进行的事务,则不会为 dontReadOrWrite 之类的方法启动事务。
  • 如果 readSomething() 时没有事务在进行被调用时,将启动一个只读事务。如果一个读写事务正在进行,它将参与这个事务。
  • 最佳答案

    就目前而言,您的代码是正确的:您确实想在服务类中的各个方法上使用 Spring @Transactional 注释来获得您正在寻找的粒度,您希望支持 dontReadOrWrite 是对的(NOT_SUPPORTED 将暂停现有交易,根据您所描述的内容不会为您购买任何东西,并且会要求您的软件花费周期,因此没有收获就会有痛苦),并且您想要默认的传播行为是对的(需要) 用于 readSomething。

    但是要记住 Spring 事务行为的重要一点是,Spring 通过将您的类包装在一个代理中来实现事务管理,该代理执行适当的事务设置,调用您的方法,然后在控制返回时执行适当的事务拆除。并且(至关重要),只有在您调用代理上的方法时才会调用此事务管理代码,如果 writeSomething() 直接调用 dontReadOrWrite() 就不会发生这种情况,就像您的第一个项目符号一样。

    如果您需要对另一个方法调用的方法进行不同的事务行为,那么如果您想继续使用 Spring 的 @Transactional 注释进行事务管理,那么您有两个选择:

  • 将另一个正在调用的方法移动到另一个服务类中,该服务类将通过 Spring 代理从您的原始服务类访问。
  • 将方法留在原处。在您的服务类中声明一个成员变量,使其与您的服务类的接口(interface)类型相同,并将其设为@Autowired,这将为您提供对您的服务类的 Spring 代理对象的引用。然后,当您想以不同的事务行为调用您的方法时,请在该成员变量上而不是直接执行此操作,Spring 事务代码将按照您的意愿触发。

  • 如果这两种方法确实不相关,则方法 #1 很棒,因为它可以解决您的问题,而不会混淆最终维护您的代码的人,并且没有办法意外忘记调用启用事务的方法。

    方法#2 通常是更好的选择,假设您的方法出于某种原因都在同一个服务中,并且您真的不想将它们分开。但是对于不了解 Spring 事务的这种皱纹的维护者来说,这会让人感到困惑,并且您必须记住在您调用它的每个地方都以这种方式调用它,因此它是有代价的。我通常愿意为此付出代价,以免不自然地 split 我的服务类(class),但与往常一样,这取决于您的情况。

    关于spring - Grails 服务事务行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8970427/

    相关文章:

    java - 跨Spring-JavaFX服务器-客户端系统的访问控制

    java - 如何在java中将模式dd-MMM-yy的字符串日期值转换为模式dd/MM/yyyy的日期对象

    html - Ajax 和 Grails 傻瓜书

    spring - Grails:使用 config.groovy 中定义的值初始化静态变量

    spring - grails 中特定于环境的 web.xml?

    java - 为什么我们在使用 ContextMapper 时不必为 ldap 用户指定对象类?

    unit-testing - 为什么此模拟 'return'是一个Closure,而不是实际的返回值?

    groovy - 使用 Groovy 的 HTTP Builder 使用 PUT 更新 JSON 数据

    Jenkins 管道 "node inside stage"与 "stage inside node"

    spring - 如何在 Spring Security JDBC 中保留 oauth 访问 token ?