Search code examples
jpadaoentitymanagerthread-local

ThreadLocal JPA EntityManager in DAO


In my DAO classes I have a reference to an EntityManager. I want to make the acces to the EntityManager thread-safe by using ThreadLocal.

So far my attempts have only resulted in NullPointerExceptions, and I can't seem to find a decent example.

Can someone provide me with an example or point me in the right direction?

update: I've tried BalusC's suggestion, but when I acces the DAO through JSF and the JAX-RS webservice at the same time, I'm still getting errors:

 org.hibernate.exception.GenericJDBCException: could not load an entity
 java.sql.SQLException: You can't operate on a closed Connection!!!
 java.lang.NullPointerException
    at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement

I'm using C3P0, so I don't know why a closed connection is a problem.

update2: BalusC's last comment seemed to have solved my problem: At least, you should not have a single instance of the DAO class shared throughout the application. Create a new one on every request.


Solution

  • I want to make the acces to the EntityManager thread-safe by using ThreadLocal.

    Don't do that. Let the container worry about this. I'd make your DAOs a @Stateless EJB and use @PersistenceContext to inject the EntityManager. E.g.

    @Stateless
    public class UserService {
    
        @PersistenceContext
        private EntityManager em;
    
        public User find(Long id) {
            return em.find(User.class, id);
        }
    
        // ...
    }
    

    To inject it in your JSF managed beans or JAX-RS services, just use @EJB:

    @EJB
    private UserService userService;
    

    To control the transaction level, use @TransactionAttribute annotation (which defaults to TransactionAttributeType#REQUIRED).