How to create a new transaction as part of an existing transaction in Grails

I have a domain class of machines and parts

In my service class I am trying to start a transaction, inside this transaction I want to create a new transaction and commit it when it exits the internal transaction.

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 

When it exits transaction 2 , I want transaction 2 execute parts for the machine regardless of transaction 1 . But grails returns an error like "Illegal attempt to associate a collection with two open sessions" How to fix transaction 2 separately separately, not considering transaction 1 ?

+4
source share
2 answers

You can try to process the transaction explicitly using the @Transactional annotation inside the service class.

Notes: -

  • After adding the @Transactional annotation method to a service, the service class is not considered transactional by default.
  • Since you split the functionality into two methods, you must use the proxied instance of the service class to call the second method, otherwise you cannot create a new transaction for the second method. Therefore, the use of applicationContext lower in method 1.
  • You will no longer need withTransaction or withNewTransaction .

The class of service will look like this:

 class MachineService{ @Transactional def someMethodToAddParts(){ ...... grailsApplication.mainContext.machineService.someMethodToRemoveParts() ...... } @Transactional(propagation = TransactionDefinition.PROPAGATION_REQUIRES_NEW) def someMethodToRemoveParts(){ ....... } } 
+1
source

I ran into a slightly different problem, maybe it can help someone, and maybe it can help in solving this problem.

I think the above problem could be avoided by combining the objects in a new transaction, and then apply the .merge () method to the collection, causing the problem.

At first, I think the code above looks like this (I added comments to explain):

 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. } 

Then the solution is to combine the collection with a new transaction, it gives us something like this:

 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. } 

In my case, when merging a new transaction, I solved the error message "Another object with the same identifier value was already associated with the session: [yourPackage.YourEntity]" (when I talk about YourEntity, you can also read YourDomaineClass)

0
source

Source: https://habr.com/ru/post/1490526/


All Articles