簡體   English   中英

grails如何禁用方法的事務

[英]grails how to disable transactional for a method

我有一種服務方法來轉移資金到外部系統。

它應該首先在我們的系統中創建一個事務(所以我們有一個transactionId)然后我們調用外部系統。 如果外部系統出現故障,我們需要回滾事務,然后在我們的付款審核日志表中寫入新記錄,無論呼叫是否失敗或有效。

在這種情況下,我無法弄清楚如何控制交易。

我理解默認情況下服務是事務性的。

我假設我可以創建3個方法(它們現在都是1個方法,這不起作用,因為我無法控制提交的內容和回滾的內容)

  1. createPaymentTransaction()
  2. sendToPaymentSystem()
  3. createPaymentRecord()

如果1失敗,我需要回滾1,並且不做任何其他事情。 如果2失敗,我需要回滾1,但是寫3.如果1和2工作,我需要寫3。

我不知道如何注釋這些,或如何構建第4個請求來管理3。

我會用這樣的東西:

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的調用將發生,因為它位於finally塊中,並且它將在單獨的事務中運行,因此它不會受到回滾的影響。主要交易和失敗不會影響主要交易。

如果您無法使用新的grails.transaction.Transactional注釋,請使用標准的Spring org.springframework.transaction.annotation.Transactional注釋,但您需要進行一些小的更改。 Grails注釋的一個動機是提供與Spring注釋相同的功能,但避免在服務中調用帶注釋的方法的問題。 Spring注釋在運行時觸發創建代理,該代理攔截所有調用,管理方法的事務性,然后調用服務實例中的實際方法。 但是使用當前代碼,對createPaymentRecord的調用將繞過代理(服務實例只是調用自身),並且不會有新的事務。 Grails注釋重寫字節碼以將每個方法包裝在事務模板中,該模板使用適用的注釋設置(顯式或從類范圍注釋推斷),因此它在內部和外部都能正常工作。 如果使用Spring注釋,則需要在代理上調用該方法,該方法只涉及訪問此服務的Spring bean。 GrailsApplication添加依賴注入作為字段:

def grailsApplication

然后通過調用createPaymentRecord

grailsApplication.mainContext.myService.createPaymentRecord()

finally塊中。

默認情況下,服務中的所有方法都是事務性的,但您可以使用注釋逐個方法地更改行為,例如

import grails.transaction.*

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

  @NotTransactional
  def notTransactional() {

  }

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

  }
}

有關事務注釋的更多詳細信息,請參閱Grails手冊

如果您需要以比每個方法更精細的級別管理事務,則可以使用withTransaction域類方法以編程方式管理事務

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM