1. java
  2. android
  3. c#
  4. .net
  5. javascript
  6. php
  7. jquery
  8. html
  9. sql

EntityManager em varias threads

Olá,

Em um projeto que estou usando jpa e vraptor 3, em um determinado método, preciso executar várias threads que precisam consultar e salvar no mesmo banco de dados. Comecei passando como parametro pra essas threads, o mesmo entityManager que pego por @autowired com o vraptor, mas isso traz erro de sessão. Então li que o certo deveria ser criar um entityManager para cada thread. Mas estou em dúvida se isso poderia acarretar excesso de conexões na base ou algum outro problema.

Alguém sabe qual a melhor forma de resolver esse problema?

Obrigado.

[EDITADO]

De acordo com as ideias dadas aqui, solucionei meu problema criando um entityManager para cada thread. Criei a classe abaixo para para criar os entityManagers. Para todas as threads, eu passo a mesma factory e inicio a classe EntityManagerThreadSafe com essa factory:

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

public class EntityManagerThreadSafe
{

    private EntityManagerFactory factory;
    private ThreadLocal<EntityManager> threadLocal;

    public EntityManagerThreadSafe(EntityManagerFactory factory)
    {
    this.factory = factory;
    threadLocal = new ThreadLocal<EntityManager>();
    }

    public void beginTransaction()
    {
    getEntityManager().getTransaction().begin();
    }

    public void rollback()
    {
    getEntityManager().getTransaction().rollback();
    }

    public void commit()
    {
    getEntityManager().getTransaction().commit();
    }

    public EntityManager getEntityManager()
    {
    EntityManager em = threadLocal.get();
    if (em == null)
    {
        em = factory.createEntityManager();
        threadLocal.set(em);
    }
    return em;
    }

    public void closeEntityManager()
    {
    if (threadLocal != null)
    {
        EntityManager em = threadLocal.get();
        if (em != null)
        {
        em.close();
        threadLocal.set(null);
        }
    }
    }   

}

Exemplo de uso:


 public void run()
    {
    this.entityManagerThreadSafe = new EntityManagerThreadSafe(this.entityManagerFactory);
    try
    {
        this.entityManagerThreadSafe.beginTransaction();
        action();
        this.entityManagerThreadSafe.commit();
    }
    catch(Exception e)
    {
        this.entityManagerThreadSafe.rollback();
    }
    finally
    {
        this.entityManagerThreadSafe.closeEntityManager();
    }
    }

Está funcionando beleza aqui.

Obrigado.

  • O fato de acarretar excesso de conexões pode ocorrer a menos que você esteja limitando a quantidades de threads a serem executadas, poderia ter um pool de conexões gerenciando isso para facilitar. O fato é que da forma que estou entendendo se cada thread vai executar funções no banco, cada thread teria que ter sua entityManager, acho que uma unica entityManager pode ocasionar em deadlock no banco (não tenho ctz). Mas isso vai depender do que você deseja efetuar em sua aplicação.

    maaarkin   26 de fev de 2015
  • Então, o que vc me indica, é mesmo usar um entityManager para cada thread em conjunto com algo como o c3po, para controlar pool de conexões. É isso mesmo né?

    walter azevedo   26 de fev de 2015
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do GUJ!

1 resposta

Não é a resposta que estava procurando? Procure outras perguntas com as tags vraptor jpa java threads ou faça a sua própria pergunta.