简体   繁体   中英

Is my @produced EntityManager thread safe in a servlet container?

In a project of mine I'm trying to switch management of my persistence from application to container. I'm following these instructions: http://docs.oracle.com/javaee/6/tutorial/doc/gkhrg.html

I've read about EntityManager not being thread safe and just want to make sure that my setup is correct. My concern: http://weblogs.java.net/blog/2005/12/19/dont-use-persistencecontext-web-app .

I have a class that produces a persistence context.

@Singleton
public class JpaResourceProducer {

    //The "pu" unit is defined with transaction-type="JTA"
    @Produces
    @PersistenceUnit(unitName = "pu")
    @Database
    EntityManagerFactory databasePersistenceUnit;

    @Produces
    @PersistenceContext(unitName = "pu")
    @Database
    EntityManager databaseEntityManager;

    /* Alternative
    @PersistenceContext(unitName = "pu")
    private EntityManager em;

    @Produces
    @UserDatabase
    public EntityManager create() {
        return em;
    }

    public void close(@Disposes @Database EntityManager em) {
        em.close();
    } 
    */
}

Then I have a jax-rs resource that injects a DAO.

@RequestScoped
@Path("/endpoint")
public class MyResource {

    @Inject private Dao dao;

    @GET
    @Produces({MediaType.APPLICATION_JSON})
    public Converter get() {

        MyEntity entity = dao.find(1);

        Converter converter = new Converter(entity);
        return converter;
    }

}

And finally a DAO where I inject the EntityManager .

@Singleton
public class JpaDao<T, K extends Serializable> implements Dao<T, K> {

    protected Class<T> entityClass;

    @Inject
    @Database
    EntityManager em;

    public JpaDao() {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
    }

    public T find(K id) {
        return em.find(entityClass, id);
    }

    ....
}

1. Is this a good setup in terms of thread safety and overall performance?


Bonus questions:

In the JpaResourceProducer I have an alternative setup for the EntityManager where I manually close the manager on dispose.

2. Is the container handling close of my EntityManager automatically?

The example from Oracle includes an EntityManagerFactory .

3. Do I really need an EntityManagerFactory when I'm using CMP?

What's your container? From annotations used I presume it is at least Java EE 6 Web Profile compatible, and in that case you're overcomplicating this.

  1. The tutorial presents producting of multiple persistence units. Is this the case in your application? If not, plain injection into EJBs would be more relieable and less magical - I am also unsure about transactional behaviour of a singleton-produced persistence context.

  2. Singleton JpaDAO means, there can be only one database operation at a time in your application, so this is serious performance bottleneck. It should be Stateless instead (and having its persistence context injected by traditional means).

In general, implement your DAOs and Business logic, even your JAX-RS endpoints as session EJBs, and let container handle concurrency and transactions properly. Also use other sources of examples, eg Adam Bien's JavaEE Patterns .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM