Se sua aplicação for multi usuário, você vai ter problemas de concorrência no EntityManagerFactory, já que você fecha o mesmo (tornando ele inválido) em diversos métodos do seu DAO. O mesmo poderia ser feito apenas em um ContextListener.
Além disso se o EntityManager for criado pelos seus DAOs, como você vai gerenciar o escopo de uma transação que usa mais de um DAO?
[quote=esmiralha]Se sua aplicação for multi usuário, você vai ter problemas de concorrência no EntityManagerFactory, já que você fecha o mesmo (tornando ele inválido) em diversos métodos do seu DAO. O mesmo poderia ser feito apenas em um ContextListener.
Além disso se o EntityManager for criado pelos seus DAOs, como você vai gerenciar o escopo de uma transação que usa mais de um DAO?[/quote]
Obrigado por responder.
Então como eu disse, sou inexperiente.
Usando o design pattern singleton, para gerenciar a Factory resolveria?
O objeto factory num deveria ser o mesmo para todo o sistema?
onde eu o utilizo para criar e destruir os objetos EntityManager que gerenciariam as transações?
Cara, em primeiro lugar, me desculpa. Eu li seu código muito rápido e falei uma grande bobagem sobre ele. Você está fechando o EntityManager nos seus DAOs e não o EntityManagerFactory… Desculpe por te confundir mais ainda…
Refazendo o meu comentário:
Você pode usar um Singleton para encapsular o EntityManagerFactory. Dessa forma, você poderá demarcar a transação no seu Controller e chamar métodos dos DAOs como parte da mesma transação.
[quote=esmiralha]Cara, em primeiro lugar, me desculpa. Eu li seu código muito rápido e falei uma grande bobagem sobre ele. Você está fechando o EntityManager nos seus DAOs e não o EntityManagerFactory… Desculpe por te confundir mais ainda…
Refazendo o meu comentário:
Você pode usar um Singleton para encapsular o EntityManagerFactory. Dessa forma, você poderá demarcar a transação no seu Controller e chamar métodos dos DAOs como parte da mesma transação.[/quote]
Ah blz…
Mas a minha duvida é a seguinte: da forma que coloquei na minha classe AbstractDAO, um atributo estatico EntityManagerFactory, teria alguma desvantagem com relação ao uso de um singleton?
Imagine que você tem que salvar Turma e seus Alunos. Supondo que você tem dois DAOs: TurmaDao e AlunoDao, como você faria para que TurmaDao e AlunoDao executassem sob uma mesma transação? Você precisa demarcar o início e fim da transação. Se ela tem um escopo que se estende além uma única classe, normalmente isso é feito de forma programática (código Java) ou declarativa (anotações) numa camada de Serviço ou então por um mecanismo ortogonal como um Aspecto.
Para que isso funcione, é preciso que todo mundo referencie o mesmo EntityManagerFactory. Se ele for um atributo private no AbstractDao, ele não poderá ser usado por uma classe de Serviço ou por um Aspecto…
[quote=esmiralha]Imagine que você tem que salvar Turma e seus Alunos. Supondo que você tem dois DAOs: TurmaDao e AlunoDao, como você faria para que TurmaDao e AlunoDao executassem sob uma mesma transação? Você precisa demarcar o início e fim da transação. Se ela tem um escopo que se estende além uma única classe, normalmente isso é feito de forma programática (código Java) ou declarativa (anotações) numa camada de Serviço ou então por um mecanismo ortogonal como um Aspecto.
Para que isso funcione, é preciso que todo mundo referencie o mesmo EntityManagerFactory. Se ele for um atributo private no AbstractDao, ele não poderá ser usado por uma classe de Serviço ou por um Aspecto…[/quote]
Desculpe insistir, mas você reparou que o atributo factory é estático?
Além disso criei um método getEntityManager() na AbstractDAO, esse método retorna um EntityManager criado pela mesma factory que é estática em AbstractDAO.
Pode ser falta de conhecimento da minha parte, mas e se o mesmo método do DAO puder ser usado em diferentes contextos transacionais? Posso inserir uma Turma e querer comitar a transação. Ou inserir uma Turma, 10 Alunos, 1 Professor e aí sim comitar a transação. Como você teria esse controle com o código que você tem até agora?
Não afeta suas transações deixar o EMF como atributo estático, pois qualquer DAO que fizer uma transação, estará se comunicando o mesmo EMF.
PS: Tbm gostaria de saber os benefícios de ter o EMF como Singleton :lol: [/quote]
E como você demarcaria as transações, Jonny?[/quote]
Ex:
Tenho um objeto Session que encapsula um EntityManager (que está ligado ao EMF blábláblá);
Passo esse Session no construtor de PessoaDao e ProdutoDao, por exemplo;
Antes de dar um save em cada dao, inicio a transação, só então salvo nos daos, aí então realizo o commit…
Não afeta suas transações deixar o EMF como atributo estático, pois qualquer DAO que fizer uma transação, estará se comunicando o mesmo EMF.
PS: Tbm gostaria de saber os benefícios de ter o EMF como Singleton :lol: [/quote]
E como você demarcaria as transações, Jonny?[/quote]
Ex:
Tenho um objeto Session que encapsula um EntityManager (que está ligado ao EMF blábláblá);
Passo esse Session no construtor de PessoaDao e ProdutoDao, por exemplo;
Antes de dar um save em cada dao, inicio a transação, só então salvo nos daos, aí então realizo o commit…
DI cara :lol: [/quote]
Quem decide quando a transação começa e quando ela termina nesse exemplo, Jonny?
Não afeta suas transações deixar o EMF como atributo estático, pois qualquer DAO que fizer uma transação, estará se comunicando o mesmo EMF.
PS: Tbm gostaria de saber os benefícios de ter o EMF como Singleton :lol: [/quote]
E como você demarcaria as transações, Jonny?[/quote]
Ex:
Tenho um objeto Session que encapsula um EntityManager (que está ligado ao EMF blábláblá);
Passo esse Session no construtor de PessoaDao e ProdutoDao, por exemplo;
Antes de dar um save em cada dao, inicio a transação, só então salvo nos daos, aí então realizo o commit…
DI cara :lol: [/quote]
Quem decide quando a transação começa e quando ela termina nesse exemplo, Jonny?[/quote]
Não afeta suas transações deixar o EMF como atributo estático, pois qualquer DAO que fizer uma transação, estará se comunicando o mesmo EMF.
PS: Tbm gostaria de saber os benefícios de ter o EMF como Singleton :lol: [/quote]
E como você demarcaria as transações, Jonny?[/quote]
Ex:
Tenho um objeto Session que encapsula um EntityManager (que está ligado ao EMF blábláblá);
Passo esse Session no construtor de PessoaDao e ProdutoDao, por exemplo;
Antes de dar um save em cada dao, inicio a transação, só então salvo nos daos, aí então realizo o commit…
DI cara :lol: [/quote]
Quem decide quando a transação começa e quando ela termina nesse exemplo, Jonny?[/quote]
Depende da sua lógica…[/quote]
E voc6e acha que os DAOs são o melhor lugar para se colocar lógica?
Não afeta suas transações deixar o EMF como atributo estático, pois qualquer DAO que fizer uma transação, estará se comunicando o mesmo EMF.
PS: Tbm gostaria de saber os benefícios de ter o EMF como Singleton :lol: [/quote]
E como você demarcaria as transações, Jonny?[/quote]
Ex:
Tenho um objeto Session que encapsula um EntityManager (que está ligado ao EMF blábláblá);
Passo esse Session no construtor de PessoaDao e ProdutoDao, por exemplo;
Antes de dar um save em cada dao, inicio a transação, só então salvo nos daos, aí então realizo o commit…
DI cara :lol: [/quote]
Quem decide quando a transação começa e quando ela termina nesse exemplo, Jonny?[/quote]
Depende da sua lógica…[/quote]
E voc6e acha que os DAOs são o melhor lugar para se colocar lógica?
[/quote]
Claro que não, é por isso que injeto (DI) minha session nos daos, para em outra classe que cuida da sua lógica, se iniciar a transação, passar esse session para os daos, salvar e então comitar.
O EntityManagerFactory deve ser aberto apenas uma vez em toda a aplicação. Da forma como está seu código, será criado um EntityManagerFactory para cada DAO que você tiver.
Retire a criação do EntityManagerFactory de dentro do DAO. Você pode, por exemplo, criar uma classe JPAUtil da seguinte forma:
[code]public class JPAUtil {
private static EntityManagerFactory emf;
static {
emf = Persistence.createEntityManagerFactory("EleicaoUrnaPU");
}
public static EntityManager createEntityManager() {
return emf.createEntityManager();
}
// Chame esse método quando sua aplicação se encerrar. Se for web, você pode escrever um listener pra fazer isso.
public static void closeEntityManagerFactory() {
emf.close();
}
}[/code]
Sobre as transações, nunca abra e feche transações dentro do DAO. Para isso, escreva seus DAOs de forma que recebam um EntityManager já criado (via construtor por exemplo), pois alguma transação aberta por ele pode já estar em andamento.
O ponto é esse que o Aires descreveu, Jonny. O código original tinha diversos problemas além de “devo usar um Singleton ou não?”. Ao meu ver, introduzir um Singleton para gerenciar o EntityManagerFactory seria um ganho perante o código original.
Não tem nada de mágico em DI. É mais sofisticado que uma AbstractFactory que externaliza os nomes das implementações em um arquivo e usa reflexão para instancia-las, mas não é mágica.