Vita Rara: A Life Uncommon

Getting a Transactional EntityManager in a JpaDaoSupport Derived DAO


Categories: | |

In Quadran my Data Access Objects (DAO) are descendants of JpaDaoSupport. JpaDaoSupport provides nice one liner convenience methods for finding entities and such. Sometimes though I find I need to actually get a handle to a JPA EntityManager. If you do this, and you are using Spring's transaction support it is important that you get the EntityManager in the proper way. Otherwise you will get an EntityManager that is not bound to the transaction, and will not be closed when your transaction completes and commit its changes, or close the session.

When I first tried getting an EntityManager I used the following code:

EntityManager em = getJpaTemplate ().getEntityManagerFactory ().createEntityManager ();

It worked, in that I got a handle to an EntityManager, but it was not bound to the transaction. I realized this when I had an "open session in view", or an "extended persistence context." I was able to traverse lazily initialized relationships in my controller and view layer. I don't normally do this, and was really confused by it. Apparently this means of obtaining an EntityManager just creates a new on using the EntityManagerFactory without looking for one attached to the Thread.

As far as I can tell the correct way to get an EntityManager bound to the transaction is as follows:


import org.springframework.orm.jpa.EntityManagerFactoryUtils;

...

EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager 
  (getJpaTemplate ().getEntityManagerFactory () );

EntityManagerFacotryUtils looks for an EntityManager bound to the thread's transaction. If it doesn't find one, it returns null. You only want to use this in a method that is wrapped in a transaction.

This really tripped me up. It took me about 10 hours to figure it out. Learn from my mistake.

Thanks

I save a lot of time thank's to You :)

Thanks

Thanks for that. I had a tough time finding out the correct way to get the thread's EntityManager too so thanks for clarifying that. It is strange that it is not documented elsewhere...