I have a method that has the propagation = Propagation.REQUIRES_NEW
transactional property:
@Transactional(propagation = Propagation.REQUIRES_NEW) public void createUser(final UserBean userBean) { //Some logic here that requires modification in DB }
This method can be called multiple times simultaneously, and for every transaction if an error occurs than it's rolled back (independently from the other transactions).
The problem is that this might force Spring to create multiple transactions, even if another one is available, and may cause some performance problems.
Java doc of propagation = Propagation.REQUIRED
says: Support a current transaction, create a new one if none exists.
This seems to solve the performance problem, doesn't it?
What about the rollback issue ? What if a new method call rolls back while using an existing transaction ? won't that rollback the whole transaction even the previous calls ?
[EDIT] I guess my question wasn't clear enough:
We have hundreds of clients connected to our server.
For each client we naturally need to send a feedback about the transaction (OK or exception -> rollback).
My question is: if I use REQUIRED
, does it mean only one transaction is used, and if the 100th client encounters a problem the 1st client's transaction will rollback as well ?
REQUIRED, spring checks for any existing transaction. If yes, it uses that old transaction otherwise it creates a new one. But, the disadvantage of Propagation. REQUIRES_NEW is that even if the inner method fails to execute (because of some exception), the outer method commits the transaction.
When the propagation is MANDATORY, if there is an active transaction, then it will be used. If there isn't an active transaction, then Spring throws an exception: @Transactional(propagation = Propagation. MANDATORY) public void mandatoryExample(String user) { // ... }
Using REQUIRES_NEW is only relevant when the method is invoked from a transactional context; when the method is invoked from a non-transactional context, it will behave exactly as REQUIRED - it will create a new transaction.
if it's using proxy based configuration to declare and access to DAO layer, the method into DAO class must be annotated with @Transactional too. If you have added @Transactional to your service layer, there is no further requirement to also add @Transactional to the DAO methods being called within that transaction.
Using REQUIRES_NEW
is only relevant when the method is invoked from a transactional context; when the method is invoked from a non-transactional context, it will behave exactly as REQUIRED
- it will create a new transaction.
That does not mean that there will only be one single transaction for all your clients - each client will start from a non-transactional context, and as soon as the the request processing will hit a @Transactional
, it will create a new transaction.
So, with that in mind, if using REQUIRES_NEW
makes sense for the semantics of that operation - than I wouldn't worry about performance - this would textbook premature optimization - I would rather stress correctness and data integrity and worry about performance once performance metrics have been collected, and not before.
On rollback - using REQUIRES_NEW
will force the start of a new transaction, and so an exception will rollback that transaction. If there is also another transaction that was executing as well - that will or will not be rolled back depending on if the exception bubbles up the stack or is caught - your choice, based on the specifics of the operations. Also, for a more in-depth discussion on transactional strategies and rollback, I would recommend: «Transaction strategies: Understanding transaction pitfalls», Mark Richards.
If you really need to do it in separate transaction you need to use REQUIRES_NEW
and live with the performance overhead. Watch out for dead locks.
I'd rather do it the other way:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With