Does Guice Persist provide transaction scoped or application managed EntityManager?

entitymanager, guice, guice-persist, jpa

Solution

I did some research of the source code of Guice-persist and read through comments under Guice-persist wiki pages and these are the answers that I needed:

1 . Lifecycle management of EntityManager is kind of broken if it's injected via @Inject EntityManager. As stated in one of the comments on the Wiki:

I confirm that inject directly an EntityManager instead of a provider can be dangerous. If you're not inside a UnitOfWork or a method annotated with @Transaction, the first injection of an EntityManager in a thread will create a new EntityManager, never destroy it, and always use this specific EntityManager for this thread (EM are stored thread-local). This can lead to terrible issues, like injection of dead entityManager (connection closed, etc) So my recommendation if to always inject a Provider, or at least to inject directly an EntityManager only inside an opened UnitOfWork.

So example in my question isn't the most correct usage. It creates singleton instance of EntityManager (per-thread) and will inject this instance everywhere :-(.

However if I've injected Provider and used it inside @Transactional method then the instance of EntityManager would be per-transaction. So the answer to this question is: if injected and used correctly, the entity manager is transaction-scoped.

2 . If injected and used correctly then I don't need to manualy close entity manager (guice-persist will handle that for me). If used incorrectly, closing manually would be very bad idea (closed instance of EntityManager would be injected in every place when I @Inject EntityManager )

3 . If injected and used correctly then the scope of L1 cache is single transaction. If used incorrectly, the scope of the L1 cache is the lifetime of application (EntityManager is singleton)

Problem

We use Guice Persist to inject EntityManager in our project. E.g. ``` public class MyDao{ @Inject EntityManager em; public void someMethod(){ //uses em instance } } ``` But it is unclear for us how injected instance of `EntityManager` is about to be used. - What type of EntityManager is this? (see e.g.: types of entity managers) Under the hood Guice Persist instantiates it via `EntityManagerFactory.createEntityManager()` so I'd say it's application-managed entity manager. But in official Wiki they write about seesion-per-transaction strategy, which suggests that EntityManager is (pseudo) transaction-scoped. - Should we invoke close() on it manually? Or Guice will take care of it? - What is the scope of first level cache? Only single transaction (like in transaction-scoped entity managers) or as long as I use the same injected instance of `EntityManager` (like in application managed entity managers)?

Original source