我有机器和零件域类
在我的服务类中,我正在尝试启动一个事务,在该事务中我想创建一个新事务,并在内部事务发出时提交它。
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}}?
答案 0 :(得分:1)
您可以尝试使用服务类中的@Transactional
注释显式处理事务。
注意: -
@Transactional
注释添加到服务方法后,默认情况下服务类不会被视为事务性。proxied
实例来调用第二个方法,否则您无法为第二个方法创建新事务。因此,在方法1中使用下面的applicationContext
。withTransaction
或withNewTransaction
阻止。服务类看起来像:
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)