Grails服务交易行为

时间:2012-01-23 10:47:47

标签: spring grails groovy transactions spring-transactions

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

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

    void writeSomething() {
    }
}

假设我在MyService中有其他方法,其中一个只读取数据库,另一个不接触数据库,以下注释是否正确?

@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()时没有进行任何事务,则将启动只读事务。如果正在进行读写事务,它将参与此事务。

2 个答案:

答案 0 :(得分:4)

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

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

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

  1. 将另一个调用的方法移动到另一个服务类中,该服务类将通过Spring代理从原始服务类访问。
  2. 将方法保留原样。声明服务类中的成员变量与服务类的接口类型相同,并使其成为@Autowired,这将为您提供对服务类的Spring代理对象的引用。然后,当您想要使用不同的事务行为调用您的方法时,请在该成员变量上而不是直接执行它,并且Spring事务代码将根据您的需要触发。
  3. 方法#1非常棒,如果这两种方法无论如何都不相关,因为它解决了你的问题而不会混淆最终维护代码的人,并且无法忘记调用启用事务的方法。

    方法#2通常是更好的选择,假设您的方法由于某种原因而全部在同一服务中,并且您不想真正将它们拆分出来。但是对于一个不理解Spring事务的皱纹的维护者而言,这是令人困惑的,你必须记住在你调用它的每个地方以这种方式调用它,所以这是有代价的。我通常愿意支付这个价格,不会不自然地分裂我的服务类,但一如既往,这取决于你的情况。

答案 1 :(得分:1)

我认为您正在寻找的是更细粒度的事务管理,使用@Transactional注释是正确的方向。也就是说,有一个Grails Transaction Handling Plugin可以为您提供您正在寻找的行为。需要注意的是,您需要将您的服务方法调用包装在DomainClass.withTransaction闭包中,并提供您正在寻找的非标准行为作为withTransaction()方法的参数映射。

作为一个注释,在后端,通过使用@Transactional注释在运行时更改事务的行为,这正是您正在讨论的内容。插件文档非常好,所以我认为如果没有足够的指导,你会发现自己。

希望这是你正在寻找的。