繁体   English   中英

Grails服务交易行为

[英]Grails service transactional behaviour

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

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

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

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

  1. 将另一个调用的方法移动到另一个服务类中,该服务类将通过Spring代理从原始服务类访问。
  2. 将方法保留在原处。 声明服务类中的成员变量与服务类的接口类型相同,并使其成为@Autowired,这将为您提供对服务类的Spring代理对象的引用。 然后,当您想要使用不同的事务行为调用您的方法时,请在该成员变量上而不是直接执行它,并且Spring事务代码将根据您的需要触发。

方法#1非常好,如果这两种方法实际上并不相关,因为它可以解决您的问题,而不会混淆最终维护代码的人,并且无法忘记调用启用事务的方法。

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

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

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

希望这是你正在寻找的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM