5

我有机器和零件域类

在我的服务类中,我试图启动一个事务,在该事务中我想创建一个新事务并在它从内部事务中出来时提交它。

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提交机器的零件,不管transaction 1。但是 grails 抛出一个错误,因为"Illegal attempt to associate a collection with two open sessions" 如何在transaction 2不考虑单独提交的情况下单独提交transaction 1

4

2 回答 2

1

您可以尝试使用@Transactional服务类中的注释显式处理事务。

笔记:-

  • 向服务方法添加@Transactional注释后,默认情况下服务类不会被视为事务性的。
  • 由于您将功能拆分为两个方法,因此您必须使用proxied服务类的实例来调用第二种方法,否则您无法为第二种方法创建新事务。因此,applicationContext在方法 1 中使用以下。
  • 您将不再需要withTransactionwithNewTransaction阻止。

服务类看起来像:

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

   @Transactional(propagation = TransactionDefinition.PROPAGATION_REQUIRES_NEW)
   def someMethodToRemoveParts(){
     .......
   }
}
于 2013-07-09T21:15:31.023 回答
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.
}

就我而言,通过新事务中的合并,我解决了错误消息“具有相同标识符值的不同对象已与会话关联:[yourPackage.YourEntity]”(当我谈论 YourEntity 时,您还可以阅读你的域类)

于 2016-11-22T17:35:43.057 回答