Qual o preço da herança em um projeto que a utilize?

Ola pessoal!

descobri hj que meus Daos estão super pesados e estão congestionando toda minha aplicação.

trabalhei com um esquema de herança do tipo

criei uma classe abstrata chamada SuperDao

[code]
public abstract class SuperDao {

protected static final EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("DeskClinPersistence");  
      
private EntityManager em = null;


public abstract List listaTodos(String query);

public abstract Object buscarPorId(Long id);

public abstract List listarPorString(String str);

  
    
protected void criaEm(){
    setEm(emf.createEntityManager());
    
}

protected void fechaEm(){
    getEm().clear();
    getEm().close();
}

public void remove(Object object) {
    //emf = javax.persistence.Persistence.createEntityManagerFactory("DeskClinPersistence");
    setEm(emf.createEntityManager());
    getEm().getTransaction().begin();
    try {
        getEm().remove(object);
        getEm().getTransaction().commit();
    } catch (Exception e) {
        e.printStackTrace();
        getEm().getTransaction().rollback();
    } finally {
        getEm().close();
    }

}

public void persiste(Object object) {
    //emf1 = javax.persistence.Persistence.createEntityManagerFactory("DeskClinPersistence");
    setEm(emf.createEntityManager());
    getEm().getTransaction().begin();
    try {
        getEm().persist(object);
        getEm().getTransaction().commit();
    } catch (Exception e) {
        System.out.print(e.getMessage());
        e.printStackTrace();
        getEm().getTransaction().rollback();
    } finally {
        getEm().close();
    }
}

protected EntityManager getEm() {
    return em;
}

protected void setEm(EntityManager em) {
    this.em = em;
}[/code]

e todas os meus subdao a herdam está classe.

estou utilizando a herança de uma forma errada ou a lentidão é um preço que eu devo pagar por esse tipo de arquitetura?

quais soluções vcs costumam utilizar para os DAO´s?

fazer de cada Dao que herde SuperDao um singleton? dessa forma eu poderia escolher lugares estratégicos para carregar cada instancia uma vez só… o que acham?

obrigado!

Boa leitura.

[quote=abstract]http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html

Boa leitura.[/quote]

Alguem ai tem um solução mais pratica??? tmb estou interesado neste assunto

galera tbem toh a procura por uma solucao, alguem ai jah fez algo parecido, ou jah passou por uma experiencia parecida?

vwls

Teve uma thread que caiu até para o xiistimo com os “Why extends is evil”. Usar extends para tudo é ruim? É. Mas não pense que ele é desnecessário ou que não há situações onde ele é requerido.

Até!

Duvido muito que seu problema de performance seja por causa desta herança. A herança costuma gerar um problema de design, que vai te dar dor de cabeça para mexer no código e dar manutencao:

Li alguns posts que me deixaram um bocado confuso. A herança nao influencia a perfomance do codigo.Isso ja me foi provado…
“Why extends Evil” ? essa foi forte…pk meus profs estao sempre a me obrigar a usar herançao pois é batante util tornado o codigo extensivel de maneira que amnha quem queira trabalhar nele, da uma olhadinha e lê o Javadoc e ja tah.
Sinceramente quando dizem que no futuro vai ser dificil mexer no codigo nao sei. :oops: :oops:

Definitivamente o seu problema de performance não é herança. A ordem que você deve começar a procurar um problema assim é a seguinte:

  1. I/O: As operações com os seus arquivos e bancos de dados tem performance? Não tem nenhuma consulta demorando?
  2. Bugs do código: Está rodando uma consulta simples vezes demais? Existe algum bug causando problemas de performance?
  3. Mau uso de algoritmos: Você usou algoritmos eficientes? Pode substitui-los por algoritmos melhores?

Se sua aplicação roda num loop extremamente intenso e tudo isso já foi coberto, aí sim, você pode desconfiar da linguagem. Mas não espere ganhar algo significativo em termos de velocidade só desfazendo uma cadeia de herança.

E, finalmente, não chute. Chutar só faz você perder tempo imaginando problemas onde eles não existem.
Use um profiler e meça com precisão onde está o problema. O Netbeans já vem com um profiler integrado e o Eclipse possui o projeto TPTP.
Ambos excelentes. Identifique o gargalo e otimize o código por lá.

tenho um JDialog e esse objeto é uma variavel de instancia do JDialog. Assim, quando eu crio o JDialog eu automaticamente crio o PacienteDao (uma sub… do SuperDao). posso ver a lentidão disto a partir do tempo de uns 2 segundos que demora para o JDialog aparecer na tela.

Então fui por eliminátoria no sentido de encontrar o que poderia estar pesando e descobri que o PacienteDao é o que está fazendo pesas, porque quando eu deixo este objeto em comentário ou o coloco em outro lugar a janela abre quase que instantaneamente.

estou em serviço agora e nao tenho como postar a sub PacienteDao. Ela é basicamente uma classe final que implementa todos os métodos abstratos e utiliza os concretos tbm com mto polimorfismo.

mas acredito que a estrutura do projeto esteja bem definida e que não a problemas de POG.

[quote]Paulo Silveira, obrigado pelo link. È interessante, mas fiquei um tanto intrigado! Até que ponto posso considerar que não valeu a pena utilizar um SuperDao igual ao meu?
[/quote]

valeu

[quote=Zakim]Ola pessoal!

descobri hj que meus Daos estão super pesados e estão congestionando toda minha aplicação.

trabalhei com um esquema de herança do tipo

criei uma classe abstrata chamada SuperDao
[/quote]

Um dos problemas que vejo no seu codigo é estar constantemente obtendo o EntityManager
Ou vc pega uma unica vez e usa até ao fim, ou vc não coloca ele como atributo, pegando ele quando necessário.
Esse set/getEm é um atrazo de vida e pode ser a causa dos seus problemas.
Outra causa podem ser os algoritmos usados nas classes filhas.

Outra coisa: Normalmente DAO é uma interface. Uma classe que implemente algumas coisas da interface é um AbstractDAO e um dao particular é um ClientDAO ou um InvoiceDAO. Dada uma interface X sua implementação abstract segue o nome AbstractX e suas implementações particulares seguem o padrão YX onde Y pode ser uma dica do algoritmo interior ou uma especificação do dominio. (Compara com List, AbstractList , ArrayList e LinkedList)

apliquei o profile assim como me indicaram e acreditem ou não 62% do processamento está se derretendo no meu SuperDao.

isso apenas na instanciação.

aqui vou postar a subclasse que herda o meu superDao

public final class PacienteDao extends SuperDao {
    
    //public static final String selectTabela1 = "Select pac.idPaciente, pac.nome, pac.dataNasc, pac.urlFoto from Paciente pac ";
    //private static final String selectAll = "Select pac from Paciente pac";
    //public static final String selectTabela = "Select pac.nome from Paciente pac where pac.nome like ? ";
    public static final String listaporId = "Select pac.idPaciente from Paciente pac";
    
    private List<Paciente> listaPaciente = null;
    
    private Paciente paciente=null;
    private ArrayList Alist = null;
    

    @Override
    public List<Paciente> listaTodos(String query) {
        criaEm();
        listaPaciente = getEm().createQuery(query).getResultList(); 
        fechaEm();
        return listaPaciente;  
    }
    
    private List<Paciente> listaTodos(){
        criaEm();
        listaPaciente = getEm().createQuery(listaporId).getResultList();
        fechaEm();
        return listaPaciente;
    }
    
    public ArrayList<Paciente> iterarElementos(){
        List listaPac = listaTodos();
        Alist = new ArrayList();
        criaEm();
        for(Iterator<Object>it = listaPac.iterator(); it.hasNext();){
            Object elem = it.next();
            Alist.add(getEm().createNamedQuery("Paciente.findByIdPaciente").setParameter("idPaciente", elem).getSingleResult());
        }
        fechaEm();
        return Alist;
    }

    @Override
    public Paciente buscarPorId(Long id) {
        criaEm();
        getEm().getTransaction().begin();
        try {
            paciente = getEm().find(Paciente.class, id);
            System.out.println(paciente.toString());
            

        } catch (Exception e) {
            getEm().getTransaction().rollback();
            System.err.println("Erro: " + e.getMessage());
        } finally {
            fechaEm();
        }

        return paciente;
    }

    @Override
    public List<Paciente> listarPorString(String str) {
        criaEm();
        Query select = getEm().createQuery("from Paciente as pac where pac.nome like '"+str+"%'");
        select.setFirstResult(0);
        select.setMaxResults(15);
        listaPaciente = select.getResultList();
        fechaEm();
        return listaPaciente;
    }
}

nos metodos do superDao eu utilizei nos metodos retornos do tipo Object para que eu possa fazer o milagre da especilalização… :stuck_out_tongue:

podem me dizer o que poderia estar carregando tatno essa classe?

idéias, criticas, sugestões… está valendo de tudo…

:stuck_out_tongue:

obrigado

pessoal!

encontrei o que estava prejudicando o meu SuperDao e como vcs ja havam afirmado, a herança não tinha nada a ver mesmo!

o que estava carregando a minha classe abstrata era o EntityManagerFactory

private static final EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory(“DeskClinPersistence”);

terei que escolher um lugar estratégico para carrega-lo uma única vez em alguma situação em que esconda do cliente a demanda de tempo necessária para a criação do EMF.

acredito que um singleton vai ficar padrão! :stuck_out_tongue:

Bem, estou trabalhando em um projeto aqui na empresa que inicialmente era assim: havia uma interface e uma implementação para cada DAO. Por causa disso cada DAO tinha em média umas 2000 linhas e eram bem repetitivos. Bugs por causa de pequenas coisas tais como esquecer de fechar um statement no finally eram frequentes.

Precisávamos dar um jeito de reaproveitar código, coisa que interface não faz. A solução neste caso foi a herança. Colocamos um grande AbstractDAO que executa instruções INSERT, UPDATE, DELETE e SELECT, recebendo apenas a SQL e o pool de conexões e os parâmetros necessários ao PreparedStatement que ele vai criar por baixo. Daí ele cria os PreparedStatements, preenche com os parâmetros, e lê os resultsets e instancia objetos por reflection para cada linha do resultset (a classe do objeto que ele vai criar é um parâmetro). Como não é ele que fabrica a SQL e nem a conexão, ele não é preso a implementação de SGBD.
O resultado foi excelente: Nas subclasses, a maior parte dos métodos se resumiu a uma ou duas linhas.
E o melhor: abolimos as interfaces, uma vez que os DAOs executam o trabalho sem estarem ligados a nenhum banco de dados. A única restrição é que esses DAOs tem que trabalhar em cima de algo que funcione com JDBC.

Herança não é ruim. Herança é ruim quando usada inadequadamente, e saber quando é adequado usá-la é difícil.