[RESOLVIDO] (JPA + EclipseLink) - Problema de perfomance com uma simples consulta

7 respostas
italoBoss

Olá galera do GUJ! :slight_smile:

Sou iniciante em JPA e estou enfrentando um problema de performance. Até mesmo consultas que deveriam ser simples estão sendo muito demoradas. Estou utilizando o NetBeans 7.1.1 e adicionei ao persistence.xml o seguinte código para visualizar as consultas:

<property name="eclipselink.logging.level" value="FINE"/>

Para exemplificar, fiz o seguinte:

//Na POJO Fabricantes
@NamedQuery(name = "Fabricantes.findAll", query = "SELECT f FROM Fabricantes f")
...

//Na DAO de Fabricantes
...
       Query query=em.createNamedQuery("Fabricantes.findAll");
       return query.getResultList();
...

Executando um teste só com essa consulta, obtive na saída o seguinte:

...
[EL Fine]: 2012-11-08 11:55:00.984--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes
[EL Fine]: 2012-11-08 11:55:01.093--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes WHERE (idfabricantes = ?)
	bind => [1]
[EL Fine]: 2012-11-08 11:55:01.093--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes WHERE (idfabricantes = ?)
	bind => [2]
[EL Fine]: 2012-11-08 11:55:01.109--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes WHERE (idfabricantes = ?)
	bind => [3]
[EL Fine]: 2012-11-08 11:55:01.109--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes WHERE (idfabricantes = ?)
	bind => [4]
.
.
.
[EL Fine]: 2012-11-08 11:55:02.375--ServerSession(22293109)--Connection(18122243)--Thread(Thread[main,5,main])--SELECT idfabricantes, data_cadastro, descricao FROM fabricantes WHERE (idfabricantes = ?)
	bind => [1000]

Me perdoem se estou sendo equivocado, mas está sendo feita uma consulta a mais pra recuperar cada registro da tabela??
Isso estaria sendo feito pra montar cada objeto?
Se é isso, então por que o EclipseLink faz isso? Não vejo sentindo. :?

Procurei um bucado sobre o assunto, mas só encontrei sobre problemas de performance para o caso de tabelas com relacionamentos. Mas no meu caso, ao que me parece, é algo bem mais simples (ou não).

Alguém saberia tirar minha dúvida e como eu poderia corrigir?
Desde já, agradeço a todos.
Abraço.

7 Respostas

Hebert_Coelho

Tem algum relacionamento terminado com ONE (OneToOne, ManyToOne) ou algum relacionamento EAGER?

italoBoss

Olá, Hebert.
Sim. Existe um relacionamento OneToMany com a tabela Equipamentos.
Segue a minha classe Fabricantes:

@Entity
@Table(name = "fabricantes")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Fabricantes.findAll", query = "SELECT f FROM Fabricantes f"),
    @NamedQuery(name = "Fabricantes.findByIdfabricantes", query = "SELECT f FROM Fabricantes f WHERE f.idfabricantes = :idfabricantes"),
    @NamedQuery(name = "Fabricantes.findByDescricao", query = "SELECT f FROM Fabricantes f WHERE f.descricao = :descricao"),
    @NamedQuery(name = "Fabricantes.findByDataCadastro", query = "SELECT f FROM Fabricantes f WHERE f.dataCadastro = :dataCadastro")})

public class Fabricantes implements Serializable {
    @Id    
    @Basic(optional = false)
    @Column(name = "idfabricantes")
    private Integer idfabricantes;
    @Basic(optional = false)
    @NotNull
    @Column(name = "descricao")
    private String descricao;
    @Basic(optional = false)
    @NotNull
    @Column(name = "data_cadastro")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dataCadastro;
    @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "fabricantesIdfabricantes")
    private Collection<Equipamentos> equipamentosCollection;
    ...
    getters e setters
    ...
}
Hebert_Coelho

Na verdade nos termos que eu perguntei não tem.

Realmente tá estranho ele disparar 3 vezes a mesma consulta? Você está utilizando JSF? Tem certeza que o método não está sendo invocado 3 vezes não?

italoBoss

Verdade, desculpa, não me toquei que perguntou só quanto a OneToOne ou ManyToOne.

Perdão novamente, acabei não dizendo, mas a aplicação no caso é em Swing.
Sim, só é executado uma vez. Fiz essa consulta de forma separada para ter certeza disso.

public static void main(String[] args) {
        FabricantesDAO dao = new FabricantesDAO();
        List<Fabricantes> lis = dao.findAll();
        System.out.println("Qtd de Fabricantes: " + lis.size());
}

Na verdade são 237 SELECTS, sendo que na primeira já seria para ele recuperar todos os registros.
E nas consultas seguintes ele tá buscando registro por registro através do ID.

Todas as POJOS foram geradas automaticamente no NetBeans, apenas com a leitura do BD. Estou utilizando o MySQL.

italoBoss

Encontrei o problema! :smiley:
Erro besta! :lol:

Em um trecho do código estava utilizando o método [color=blue]refresh()[/color] do EntityManager.
Acabamos por usar o método, pois tivemos um problema anteriormente de um objeto modificado que não se atualizava na hora de listar. E como a empresa é de locação e eventos, era necessário que todos os dados sempre estivessem coerentes.

Mas no caso de uma busca de todos os registros, o método não se faz necessário. A principio não percebi isso, pq havia retirado o refresh() antes e não mudava nada. Só veio a funcionar após eu ter limpado e construído o projeto (talvez alguma besteira do NetBeans).

Agora, quanto ao problema anterior que tivemos, pq o objeto não se atualizava automaticamente? Seria devido ao cache ou algo assim? A solução mais correta seria utilizar o refresh?

Valeu pela atenção, Hebert! E desculpa a besteira minha. :slight_smile:

Hebert_Coelho

É cara, infelizmente não confio em códigos gerados de modo automático.

E eu não sei te falar o por que. Teria que analisar o código todo. Sorry.

italoBoss

Tranquilo, cara. Agradeço pela atenção. :slight_smile:

Criado 8 de novembro de 2012
Ultima resposta 8 de nov. de 2012
Respostas 7
Participantes 2