grails如何禁用方法的事务性

grails如何禁用方法的事务性,grails,transactions,Grails,Transactions,我有一种向外部系统转账或从外部系统转账的服务方法 它应该首先在我们的系统中创建一个事务(因此我们有一个transactionId) 然后我们称之为外部系统。 如果外部系统失败,我们需要回滚事务,然后在付款审核日志表中写入一条新记录,不管调用是否失败或有效 在这种情况下,我不知道如何控制交易 我理解默认情况下服务是事务性的 我假设我可以创建3个方法(它们现在都是1个方法,这不起作用,因为我无法控制提交什么和回滚什么) createPaymentTransaction() sendToPayment

我有一种向外部系统转账或从外部系统转账的服务方法

它应该首先在我们的系统中创建一个事务(因此我们有一个transactionId) 然后我们称之为外部系统。 如果外部系统失败,我们需要回滚事务,然后在付款审核日志表中写入一条新记录,不管调用是否失败或有效

在这种情况下,我不知道如何控制交易

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

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

  • createPaymentTransaction()
  • sendToPaymentSystem()
  • createPaymentRecord()
  • 如果1失败,我需要回滚1,并且不再执行任何操作。 如果2失败,我需要回滚1,但写3。 如果1和2有效,我需要写3


    我不知道如何对这些方法进行注释,也不知道如何构造第四个请求来管理第三个方法。

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

    import grails.transaction.*
    
    // By default all methods are transactional
    @Transactional
    class MyService {
    
      @NotTransactional
      def notTransactional() {
    
      }
    
      // inherits the class-level default
      def transactional() {
    
      }
    }
    
    有关事务注释的更多详细信息,请参阅


    如果您需要在比per方法更细粒度的级别上管理事务,您可以使用域类方法来管理事务。

    我会选择以下方法:

    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
    将加入现有事务,或者在必要时启动新事务。如果
    createPaymentTransaction
    sendToPaymentSystem
    中出现问题,则事务将回滚,但调用
    createPaymentRecord
    将发生,因为它位于
    finally
    块中,它将在一个单独的事务中运行,因此它不会受到主事务回滚的影响,并且主事务中的故障也不会受到影响

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

    def grailsApplication
    
    然后通过调用
    createPaymentRecord

    grailsApplication.mainContext.myService.createPaymentRecord()
    

    finally
    块中。

    如果大多数方法都是事务性的,我会使用
    NotTransactional
    ,并对那些不是事务性的方法进行注释。如果大多数都没有,那么就在类级别删除注释,并用
    @transactional
    @NotTransactional注释事务方法。这是我一直在寻找的,但在grails文档中找不到,我应该尝试一下!然而,支撑的事情看起来是一个更好的解决方案谢谢伯特,这正是我需要的。