EntityManagerFactory

[quote=esmiralha]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.[/quote]

Em nenhum momento falei que DI resolveria o problema dele, apenas dei essa sugestão, e eu mesmo falei que o EMF só se cria uma vez, talvez numa classe util que o tnaires sugeriu (assim que eu faço). Por favor, não misture as coisas.

A classe JPAUtil que o Aires apresentou não é um Singleton?

Não…

A classe JPAUtil garante que eu só instanciarei EntityManagerFactory uma única vez e que o sistema inteiro terá acesso a essa mesma instância. A implementação de EntityManagerFactory não pode ser facilmente substituida por outra para fins de teste.

Qual a diferença prática entre isso e um Singleton imutável?

[quote=esmiralha]A classe JPAUtil garante que eu só instanciarei EntityManagerFactory uma única vez e que o sistema inteiro terá acesso a essa mesma instância. A implementação de EntityManagerFactory não pode ser facilmente substituida por outra para fins de teste.

Qual a diferença prática entre isso e um Singleton imutável?[/quote]

Nesse caso, não haveria diferença, mas ele continua não sendo um Singleton.

Se não há diferença, por que uma classe forrada de métodos estáticos e variáveis estáticas é legal e Singleton não é?

E quem falou isso?

Bom, deixa pra lá, essa conversa não tem futuro…

JPAUtil não é um singleton, é apenas uma classe utilitária com métodos estáticos. Poderíamos até tornar o construtor privado pra evitar sua instanciação.

E não é possível acessar o EntityManagerFactory diretamente. Além disso, pra que escrever testes para o EntityManagerFactory?

Sim, mas ela é uma classe utilitária que tem estado global mutável e ainda contém uma dependência que poderia ser muito interessante substituir por um mock na hora de testar.

O que faltava naquele código é uma camada de Serviço para gerenciar transações de forma adequada e uma forma de referenciar o mesmo EMF tanto do Serviço quanto do DAO. Um Singleton daria essa oportunidade. Uma Factory ou DI daria ainda a oportunidade de trocar a implementação na hora de testar.

Fui!

[quote=esmiralha]Sim, mas ela é uma classe utilitária que tem estado global mutável e ainda contém uma dependência que poderia ser muito interessante substituir por um mock na hora de testar.

O que faltava naquele código é uma camada de Serviço para gerenciar transações de forma adequada e uma forma de referenciar o mesmo EMF tanto do Serviço quanto do DAO. Um Singleton daria essa oportunidade. Uma Factory ou DI daria ainda a oportunidade de trocar a implementação na hora de testar.

Fui![/quote]

Cara, ninguém além do seu EntityManager precisa conhecer o EMF, por isso que passamos por DI um objeto que contém apenas o EntityManager, pois o EMF é criado uma só vez, e sempre será o mesmo…

Pessoal, estive ausente, me desculpem a demora, vou tentar explicar como procedi nesse projeto.

Ao invés de utilizar uma classe utilitária JPAUtil como voces sugeriram, eu pensei, e decidi fazer o seguinte.

Criei uma classe AbstractDAO, que teria os métodos DAO básicos, e já que os DAOs seriam os unicos que precisariam de um EMF, achei por bem que seria melhor embutir esse EMF na minha AbstractDAO.

Porém, tomando o cuidado para que não fossem criadas várias EMFs…

Então coloquei sim um atributo do tipo EntityManagerFactory, porém esse atributo é privado e estático, sua atribuição ocorreria dentro de um bloco static.

e criei um método protected getEntityManager() para que todos os DAOs herdados dessa classe abstrata pudessem ter um EntityManager originado pelo mesmo EMF estatico da AbstractDAO.

Tem algo errado? meu código seria perderia em algo para um singleton ou uma JPAUtil???

public abstract class AbstractDAO<T> {

    protected final Class<T> entityClass;
    private final EntityManagerFactory EMF;
    
    static {
        EMF = Persistence.createEntityManagerFactory("PersistenceUnit");
    }
    
public AbstractDAO(Class<T> entityClass) {
        this.entityClass = entityClass;
    }

    protected final EntityManager getEntityManager() {
        return EMF.createEntityManager();
    }

}