I am working on a spring project. We use JPA and hibernate in the project.I have 3 transactions in different methods which writes to db(2nd transaction needs id of first transaction and 1st transaction using save method) and I am calling these 3 methods in a single method(in business logic).How can i rollback other 2 methods if any one of these fails.I searched a lot but the answer does not meet my requirements(I don't want to write transaction manager on my own).Can I use #transactional annotation here? what are the disadvantages of using #transactional annotation?I heard it causes db lock.If it causes DB lock, in what condition it will cause db lock?.Thanks in advance
Related
I have a Spring Boot application with persistence using Hibernate/JPA.
I am using transactions to manage my database persistence, and I am using the #Transactional annotation to define the methods that should execute transactionally.
I have three main levels of transaction granularity when persisting:
Batches of entities to be persisted
Single entities to be persisted
Single database operations that persist an entity
Therefore, you can imagine that I have three levels of nested transactions when thinking about the whole persistence flux.
The interaction between between levels 2 and 3 works transparently as I desire because without specifying any Propagation behaviour for the transaction, the default is the REQUIRED behaviour, and so the entire entity (level 2) is rolled back because level 3 will support the transaction defined in level 2.
However, the problem is that I need an interaction between 1 and 2 that is slightly different. I need an entity to be rolled back individually if an error were to occur, but I wouldn't like the entire batch to be rolled back. That being said, I need to specify a propagation behavior in the level 2 annotation #Transactional(propagation = X) that follows these requirements.
I've tried REQUIRES_NEW but that doesn't work because it commits some of the entities from level 2 even if the whole batch had to be rolled back, which can also happen.
The behaviour that seems to fit the description better is NESTED, but that is not accepted when using Spring and Hibernate JPA, see here for more information.
This last link offers alternatives for the NESTED type, but I would like to know if NESTED would've really solved my problem, or if there was another behaviour that suited the job better.
I guess NESTED would roughly do what you want but I would question if this really is necessary. I don't know what you are trying to do or what the error condition is, but maybe you can get rid of the error condition by using some kind of WHERE clause or an UPSERT statement: Hibernate Transactions and Concurrency Using attachDirty (saveOrUpdate)
First to explain the context. I have backend Java (Spring/Hibernate) application that is accessible via Rest client.
Problem: Since API is exposed as RestApi, I get the DTO object from the client with ID of the entity which needs to be updated.
Current approach: I am getting the entity from DB based on the ID, and detaching it from persistent context, converting DTO object to entity object,
then sending it to DAO, where again I am fetching the entity from DB (as DAO can be called directly by other internal classes) then again detaching it and later merge operations get called.
So for every update call hibernate will fire 3 select statement and 1 update statement. Is there any way I can reduce the number of the select calls.
if all your queries are done in the same session, hibernate shouldn't load the entities again for every request to the repository, just use the #Transactional annotation on your service classes
https://docs.spring.io/spring/docs/current/spring-framework-reference/data-access.html#transaction-declarative-annotations
another aproach is to use hibernates second level cache:
https://docs.jboss.org/hibernate/orm/5.3/userguide/html_single/chapters/caching/Caching.html
http://www.baeldung.com/hibernate-second-level-cache
I'm migrating the code from EJB to Spring-Hibernate. How do I join the transaction and rollback if failure occurs?
Below is the code in EJB :
entityManager.joinTransaction();
entityManager.persist(xyz);
entityManager.flush();
UPDATE 1:
How do we join two transactions happening on different databases?
There are 2 transactions which needs to performed atomically. If the second transaction fails, 1st transaction must be rollbacked. How to implement this?
The purpose of entityManager.joinTransaction(); is to notify the persistence context to synchronize itself with the current transaction (reference)
Since the code is being migrated to the Spring consider leveraging the out-of-box transaction abstraction available via #Transactional. This will make the call to joinTransaction() redundant and the rollback / commit will be taken care by Spring.
Note - Ensure that the transaction settings are chosen appropriately so as to be inline with current implementation.
I have the following problem: I am working on a spring-boot application which offers REST services and use a relational (SQL) database using spring-data-jpa.
I have two REST services:
- a entity-creation service, which create the child-entity, the parent-entity and associate them in a same transaction. When this service ends, the data are committed into the database.
- an entity consultation service, which get back the parent-entity with its children
These two services are annotated with the #Transactional annotation. It production case, it works well: I can create an parent-entity with its children in one transaction (which is commited/ended), and get it in another transaction latter.
The problem is when I want to create integration-tests. My idea was to annotate each test with the #Transactional annotation, and do a rollback after each test. This way I keep my database clean between each test, and I don't have a generate the schema again or clean all the records in the database.
The integration test consists in creating a parent and its children and then reading it, everything in one transaction (as the test is annotated with #Transaction). When reading the entity previously created in the same transaction, I can get the parent entity, but the children are not fetched (null value). I am not sure to understand very well the transaction mechanism: I was thinking that using the #Transactional on the test method, the services (annotated with "#Transactional") invoked by this test should detect and use the same transaction opened by the test method (the propagation is configured to "REQUIRED"). Hence as the transaction uses the same EntityManager, this one should be able to return the relation between the parent entity and its children created previously in the same transaction, even if the data has not been committed to the database. The strange thing is that it retrieve the parent entity (which has not been yet committed into the database), but not its children. Is my understanding of the transaction concept correct? If not, could someone explains me what am I missing?
Also, if someone did something similar, could he explain me how he did it please?
My code is quite complex. I first want to know if I understand well how are transaction managed and if someone already did something similar. If really it is required, I can send more information about my implementation (how the transaction-manager and the entity-manager are initialized, the JPA entities, the services etc...)
Binding the Entity-manager in my test and calling its flush method from my test,between the creation and the reading, the reading operation works well: I get the parent entity with its children. But the data are written into the database during the creation to read it latter during the read operation. And I don't want the transaction to be committed as I need my test to work on an empty database. My misunderstanding is not so much about the Transaction mechanism, but more about the entity-manager: it does not keep as a cache the entities created and theirs relations...
This post help me.
Issue with #Transactional annotations in Spring JPA
As a final word, I am thinking about calling an SQL script before each test to empty my database.
First let me explain you what I mean by a nested transaction.
Example: say in the main class we call method1 and create the customer using jdbc[Transaction1]. It is not commited yet. Now we call method2 in the main class and create the account for the just created customer[Transaction2]. Now commit it. As per your explanation both these transactions will be treated as part of one transaction (as there can be a maximum of one transaction with a connection). Till here, if we compare the above scenario, it will be like propagation_required in Spring. Is that correct?
Now if we want to commit transaction2 only not the one. Then this scenario will be like propagation_Nested in Spring. Is that correct?
How can we implement a nested transaction in JDBC if both my assumptions stated above are correct?
This not exactly how nested transactions work. If you roll back transaction 1, transaction 2 also rolls back. With the nested transactions you can rollback transaction 2 and still commit transaction 1.
In the JDBC you can achieve this effect using savepoints. You can call Connection.setSavepoint() before creating account and if you want to rollback that action but still commit creation of the customer, you can rollback to that savepoint.
If you want to be able to commit/rollback two transactions completely independently, like Spring REQUIRES_NEW, in JDBC you should use two connections and manage transactions on them independently.