如何在Grails中的现有事务中创建新事务

时间:2013-07-09 16:09:04

标签: grails transactions

我有机器和零件域类

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

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提交机器的部件而不管"Illegal attempt to associate a collection with two open sessions"。但是grails正在向transaction 2发送错误 如何单独提交transaction 1而不考虑{{1}}?

2 个答案:

答案 0 :(得分:1)

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

注意: -

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

服务类看起来像:

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

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

答案 1 :(得分: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时,你也可以阅读YourDomaineClass)