Jersey, Guice e Hibernate - segurança de threads do EntityManager
Eu usei este tutorial da mesma maneira no meu aplicativo:http://www.benmccann.com/hibernate-with-jpa-annotations-and-guice/
Meu aplicativo é um serviço da web JAX-RS que receberá muitas solicitações simultâneas e fará atualizações no banco de dados.
Implementação de GenericDAOImpl.java:
public class GenericDAOImpl<T> implements GenericDAO<T> {
@Inject
protected EntityManager entityManager;
private Class<T> type;
public GenericDAOImpl(){}
public GenericDAOImpl(Class<T> type) {
this.type = type;
}
@Override
public void save(T entity) {
entityManager.getTransaction().begin();
entityManager.persist(entity);
entityManager.getTransaction().commit();
}
}
Se 2 threads simultâneos tentarem salvar a entidade, eu recebo
java.lang.IllegalStateException: Transaction already active
Salvar funciona bem se eu comentar a transação.
Eu tentei usar
@Inject
protected Provider<EntityManager> entityManagerProvider;
ou
@Inject
protected EntityManagerFactory entityManagerProvider;
e para cada solicitação:
EntityManager entityManager = entityManagerProvider.get()
Mas então eu recebo:
org.hibernate.PersistentObjectException: detached entity passed to persist
Qual é a maneira correta de implementar a classe DAO genérica de injeção / thread-safe do Guice + Hibernate EntityManager?
ATUALIZAR
Andrew Rayner comenta dehttp://www.benmccann.com/hibernate-with-jpa-annotations-and-guice/
"A lógica não está pronta para a produção - pelo menos se usada em um aplicativo da web.
O conjunto de conexões do Hibernates é muito básico e não está pronto para produção - a recomendação é usar um conjunto de fontes de dados como c3p0.
O EntityManager não deve ser reutilizado - ele deve ser criado por transação / solicitação. Há uma boa chance de poluir solicitações subsequentes.
Também não há reversão de transação se algo der errado.
Uma abordagem interessante - mas seria muito mais seguro para os webapps usar o módulo de extensão Persist do Guices para gerenciar o ciclo de vida das instâncias e transações do EntityMananger ".