2013-07-09 49 views
4

創建現有事務中新的事務我有整機和零部件領域類如何在Grails的

在我的服務類我試圖啓動一個事務,該事務裏面我想創建一個新的事務,並在其提交它來自內部交易。

Machine.withTransaction { // transaction 1 
    // some code to add Parts 

    // some code to remove Parts 
    Machine.withNewTrasaction { // transaction 2 
     // some code to remove Parts. 
    } // end of transaction 2 

// some code to update couple of columns in machine table. 
}// end of transaction 1 

當它出來的transaction 2我想transaction 2不考慮COMMITED了機器的零件到transaction 1 Grails的。但不考慮transaction 1拋出一個錯誤追溯到"Illegal attempt to associate a collection with two open sessions" 如何單獨提交transaction 2分開?

+0

你可以嘗試使用'Machine.withNewTransaction(傳播:TransactionDefinition.PROPAGATION_REQUIRES_NEW){...}'? – dmahapatro

+0

@dmahapatro我回來錯誤爲'沒有方法的簽名:Machine.withNewTransaction'我覺得語法或錯誤的東西。我無法找到良好的文檔也爲這個 – user2001627

回答

1

您可以嘗試在服務類中使用@Transactional批註明確處理事務。

注: -

  • 一旦你添加@Transactional註釋服務方法,服務類默認情況下不被視爲交易。
  • 由於您將功能拆分爲兩種方法,因此您必須使用服務類的proxied實例調用第二種方法,否則您無法爲第二種方法創建新的事務。因此,在方法1中使用以下applicationContext
  • 您將不需要0​​或withNewTransaction阻止更多。

服務類會是什麼樣子:

class MachineService{ 
    @Transactional 
    def someMethodToAddParts(){ 
     ...... 
     grailsApplication.mainContext.machineService.someMethodToRemoveParts() 
     ...... 
    } 

    @Transactional(propagation = TransactionDefinition.PROPAGATION_REQUIRES_NEW) 
    def someMethodToRemoveParts(){ 
    ....... 
    } 
} 
+0

我想用這種方式'公共布爾someMethodToAddParts(){ \t withTransaction { \t ... \t grailsApplication.mainContext.machineService的代碼。someMethodToRemoveParts() \t ... \t} } @Transactional(傳播= TransactionDefinition.PROPAGATION_REQUIRES_NEW) 保護布爾someMethodToRemoveParts(){ \t ... \t parts.save() \t }' – user2001627

+0

在我的第一種方法,如果設置事務回滾或任何其他錯誤,它應該通過someMethodToRemoveParts持久部分表。但是,當響應從someMethodToAddParts()出來的錯誤,它沒有堅持數據庫中的部分。我錯過了什麼? – user2001627

+0

@ user2001627是不是'someMethodToRemoveParts()'意味着刪除零件而不是堅持它?如果您使用註釋,則不需要提供'withTransaction'。 – dmahapatro

0

我遇到一個稍微不同的問題,也許它可以幫助別人,也許它可以幫助上述問題。

我認爲上述問題可以通過合併實體到新事務來避免,然後在導致問題的集合上使用.merge()方法。

首先,我覺得上面的代碼看起來像這樣(我已經添加註釋來解釋):

Machine.withTransaction { // transaction 1 
    // some code to add Parts 

    yourEntity.addToParts(...) 

    // some code to remove Parts 
    Machine.withNewTrasaction { // transaction 2 
     // some code to remove Parts. 

     yourEntity.removeFromParts(...) 


    } // end of transaction 2 -> the session is flushed, and the transaction is committed 
     // during the flush, hibernate detect that "parts" collection is already attached 
     // to another session, in another transaction then throw "Illegal 
     // attempt to associate a collection with two open sessions" 

// some code to update couple of columns in machine table. 
} 

那麼解決的辦法是收集合併到新的事務,它給了我們這樣的:

Machine.withTransaction { // transaction 1 
    // some code to add Parts 

    yourEntity.addToParts(...) 

    // some code to remove Parts 
    Machine.withNewTrasaction { // transaction 2 
     // some code to remove Parts. 

     yourEntity.removeFromParts(...) 
     // Merging the collection to the session 
     yourEntity.merge() // I haven't tried but maybe you need ensure 
          // there is a merge cascade on "parts" collection 

    } // end of transaction 2 -> the session is flushed, and the transaction is committed 

// some code to update couple of columns in machine table. 
} 

在我的情況,與所述新事務的合併,我解決了錯誤消息「A不同的對象使用相同的標識符值已經與會話相關聯:[yourPackage.YourEntity]」(當我跟關於YourEntity,你也可以閱讀YourDomaineClass)