Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA/EclipseLink: Does EntityManager.getTransaction() create a new transaction or return the active one?

I am using EclipseLink 2.3.0. I have a method that I am calling from a unit test (hence outside of a container, no JTA) that looks like this:

EntityManager em = /* get an entity manager */;
em.getTransaction().begin();
// make some changes
em.getTransaction().commit();

The changes were NOT being persisted to the database, and looked at this for a long time and finally realized that EntityManager.getTransaction() is actually returning a NEW EntityTransaction, rather than the same one in both calls. The effect is that the first call creates a new transaction and begins it, and the second call creates ANOTHER transaction and commits it. Because the first transaction was never committed, the changes are not saved. We verified this like this:

log.info(em.getTransaction().toString());
log.info(em.getTransaction().toString());

Which resulted in these log messages:

INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@1e34f445
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@706a4d1a

The two different object ID's verifying that there are two different instances. Changing the code to this:

EntityManager em = /* get an entity manager */;
EntityTransaction tx = em.getTransaction();
tx.begin();
// make some changes
tx.commit();

... remedied the problem. Now when I run the code, I see the SQL statements generated to do the database work, and looking in the database, the data has been changed.

I were a bit surprised by this outcome, since I have seen numerous code examples online (for JPA generally and for EclipseLink specifically) that recommend the code we used for managing transactions. I searched far and wide for information specifically about this but have not found anything. So what's going on?

I looked in the JPA spec for something that specifies exactly what getTransaction() does and it was not specific if the transaction is new or the same. Is there a setting in persistence.xml that controls this? Is the behavior specific to each implementation of the JPA spec?

Thanks so much for any information or guidance.

like image 601
Uncle Long Hair Avatar asked Jun 12 '12 21:06

Uncle Long Hair


1 Answers

Using getTransaction() does work in JPA and in EclipseLink (this is how our own tests work).

My guess is you are doing something else very odd.

Are you using Spring, or another layer? Please include the entire code and persistence.xml for your test. Ensure that you are not using JTA in your persistence.xml.

like image 150
James Avatar answered Oct 17 '22 09:10

James