grails如何禁用方法的事务

时间:2015-02-19 16:18:37

标签: grails transactions

我有一种服务方法可以将资金转入/转出外部系统。

它应首先在我们的系统中创建一个事务(所以我们有一个transactionId) 然后我们称之为外部系统。 如果外部系统出现故障,我们需要回滚事务,然后在支付审计日志表中写入新记录,无论呼叫是否失败或是否正常工作。

在这种情况下,我无法弄清楚如何控制交易。

我理解默认情况下服务是事务性的。

我假设我可以创建3个方法(它们现在都是1个方法,但这不起作用,因为我无法控制提交的内容以及回滚的内容)

  1. createPaymentTransaction()
  2. sendToPaymentSystem()
  3. createPaymentRecord()
  4. 如果1失败,我需要回滚1,并且不做任何其他事情。 如果2失败,我需要回滚1,但写3。 如果1和2有效,我需要写3个。

    我不知道如何注释这些,或者如何构建第4个管理3的请求。

2 个答案:

答案 0 :(得分:9)

我选择这样的事情:

package com.myapp

import grails.transaction.Transactional

import org.springframework.transaction.annotation.Propagation

@Transactional
class MyService {

    def createPaymentTransaction() {}

    def sendToPaymentSystem() {}

    @Transactional(propagation=Propagation.REQUIRES_NEW)
    def createPaymentRecord() {}

    def method4() {
        try {
            def transactionId = createPaymentTransaction()
            sendToPaymentSystem(transactionId)
        }
        finally {
            createPaymentRecord()
        }
    }
}

通过在类级别进行注释,我们为所有方法设置默认值,但可以根据需要进行自定义,例如: createPaymentMethod

所以会发生的是,调用method4将加入现有交易,或者在必要时开始新交易。如果createPaymentTransactionsendToPaymentSystem出现问题,那么该事务将被回滚,但是createPaymentRecord的调用将会发生,因为它在{{1}中阻止,它将在一个单独的事务中运行,因此它不受主事务中的回滚影响,并且失败不会影响主事务。

如果您无法使用新的finally注释,请使用标准的Spring grails.transaction.Transactional注释,但您需要进行一些小的更改。 Grails注释的一个动机是提供与Spring注释相同的功能,但避免在服务中调用带注释的方法的问题。 Spring注释在运行时触发创建代理,该代理拦截所有调用,管理方法的事务性,然后调用服务实例中的实际方法。但是使用当前代码,对org.springframework.transaction.annotation.Transactional的调用将绕过代理(服务实例只是调用自身),并且不会成为新事务。 Grails注释重写字节码以将每个方法包装在事务模板中,该模板使用适用的注释设置(显式或从类范围注释推断),因此它在内部和外部都能正常工作。如果使用Spring注释,则需要在代理上调用该方法,该方法只涉及访问此服务的Spring bean。为createPaymentRecord添加依赖注入作为字段:

GrailsApplication

然后通过

致电def grailsApplication
createPaymentRecord

grailsApplication.mainContext.myService.createPaymentRecord() 区块中。

答案 1 :(得分:8)

默认情况下,服务中的所有方法都是事务性的,但您可以使用注释逐个方法地更改行为,例如

import grails.transaction.*

// By default all methods are transactional
@Transactional
class MyService {

  @NotTransactional
  def notTransactional() {

  }

  // inherits the class-level default
  def transactional() {

  }
}

有关交易注释的更多详细信息,请参阅Grails manual

如果您需要以比每个方法更精细的级别管理事务,则可以使用withTransaction域类方法manage transactions programatically