Desempenho JPA + Hibernate ruim

Aew galera fiz uma aplicação com JPA + Hibernate e percebi um desempenho ruim ao fazer os filtros de busca, quando eu faço o primeiro findAll até que vai rapido, mas quando mando buscar novamente ele demora mais de 10segundos para trazer 10 registros, olhei os selects gerados pelo JPA e o estranho parece que ele popula todos os relacionamentos do objeto que estou buscando, mas eu mapiei tudo como LAZY justamente para nao ter esse problema, segue os mapeamentos…

Classe principal que estou chamando o findAll
Transportadora

[code]public class Transportadora implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@Basic(optional = false)
@Column(name = "CodTransportadora_ID", nullable = false)
private int codTransportadoraID;
@Basic(optional = false)
@Column(name = "NomeTransp", nullable = false, length = 40)
private String nomeTransp;
@Column(name = "EndTransp", length = 40)
private String endTransp;
@Column(name = "BaiTransp", length = 20)
private String baiTransp;
@Column(name = "CidTransp", length = 25)
private String cidTransp;
@Column(name = "EstTransp", length = 2)
private String estTransp;
@Column(name = "CEPTransp", length = 8)
private String cEPTransp;
@Column(name = "Telefone", length = 14)
private String telefone;
@Column(name = "Fax", length = 14)
private String fax;
@Column(name = "Contato", length = 40)
private String contato;
@Column(name = "Funcao", length = 20)
private String funcao;
@Column(name = "Ramal", length = 5)
private String ramal;
@Column(name = "Observacao", length = 2147483647)
private String observacao;
@Column(name = "CGC", length = 14)
private String cgc;
@Column(name = "INSESTADUAL", length = 15)
private String insestadual;
@Column(name = "CFFLAGFJ", length = 1)
private String cfflagfj;
@Column(name = "E_Mail", length = 255)
private String eMail;
@Column(name = "Ativo")
private Character ativo;
@Column(name = "Frete", length = 3)
private String frete;
@Column(name = "TpEntrega")
private Integer tpEntrega;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "transportadora", fetch = FetchType.LAZY)
private Set<Orcamento> orcamentoSet;

@OneToMany(cascade = CascadeType.ALL, mappedBy = "transportadora", fetch = FetchType.LAZY)
private Set<NFiscal> nfiscalSet;

@OneToOne(cascade = CascadeType.ALL, mappedBy = "transportadora", fetch = FetchType.LAZY)
private TransportadoraConsult transpConsult;
....

[/code]

TransportadoraConsult

[code]public class TransportadoraConsult implements Serializable {

private static final long serialVersionUID = 1L;

// <editor-fold defaultstate="collapsed" desc="Colunas">
@Id
@Basic(optional = false)
@Column(name = "cnpj", length = 255, nullable = false)
private String cnpj;


@OneToOne(optional = true, fetch = FetchType.LAZY)
@JoinColumn(name = “codTransp”)
private Transportadora transportadora;
…[/code]

NFiscal

@JoinColumn(name = "CodTransportadora_ID", referencedColumnName = "CodTransportadora_ID", nullable = false) @ManyToOne(optional = false, fetch = FetchType.LAZY) private Transportadora transportadora;

Orcamento

@JoinColumn(name = "CodTransportadora_ID", referencedColumnName = "CodTransportadora_ID", nullable = false) @ManyToOne(optional = false, fetch = FetchType.LAZY) private Transportadora transportadora;

Ao chamar a namedQuery

O que esta errado, ou melhor o que pode ser melhorado, pois o select funciona mas ele relaciona todas as tabelas sem que eu tenha dado um unico get a não ser em cnpj e RazaoSocial que nao relaciona com objeto nenhum

se a consulta demora quando vc utiliza filtros tente adiconar de indices nos campos filtrados.

uma coisa que pode ser melhorada no seu codigo, vc pode tirar esse atributo length e colocar a anotação @Lob

@Column(name = "Observacao", length = 2147483647)  
private String observacao; 

poste sua query do hibernate e a query nativa gerada

abrasssssss

@Entity @Table(name = "Transportadora", catalog = "deak", schema = "dbo", uniqueConstraints = { @UniqueConstraint(columnNames = {"CGC"})}) @NamedQueries({ @NamedQuery(name = "Transportadora.findAll", query = "SELECT t FROM Transportadora t"),

Segue a Query que o hibernate gerou

Hibernate: select nfiscal0_.Cgcemissor as Cgcemissor9_1_, nfiscal0_.Empresa as Empresa9_1_, nfiscal0_.Filial as Filial9_1_, nfiscal0_.NumNF as NumNF9_1_, nfiscal0_.Series as Series9_1_, nfiscal0_.Atendente_ID as Atendente5_9_1_, nfiscal0_.BAIENT as BAIENT9_1_, nfiscal0_.BaseICM as BaseICM9_1_, nfiscal0_.BaseSubst as BaseSubst9_1_, nfiscal0_.Bruto as Bruto9_1_, nfiscal0_.CEPENT as CEPENT9_1_, nfiscal0_.CFFLAGFJ as CFFLAGFJ9_1_, nfiscal0_.CIDENT as CIDENT9_1_, nfiscal0_.Cgc as Cgc9_1_, nfiscal0_.CodTranspCli as CodTran13_9_1_, nfiscal0_.CodVendedor_ID as CodVend14_9_1_, nfiscal0_.Codtributacao as Codtrib15_9_1_, nfiscal0_.Comissao as Comissao9_1_, nfiscal0_.ComissaoExt as Comissa17_9_1_, nfiscal0_.Comissaonf as Comissaonf9_1_, nfiscal0_.CondPagto_ID as CondPagto19_9_1_, nfiscal0_.ConttFone as ConttFone9_1_, nfiscal0_.ConttNome as ConttNome9_1_, nfiscal0_.ConttRamal as ConttRamal9_1_, nfiscal0_.CustoFinanc as CustoFi23_9_1_, nfiscal0_.DataEntrega as DataEnt24_9_1_, nfiscal0_.DataNota as DataNota9_1_, nfiscal0_.ENDENT as ENDENT9_1_, nfiscal0_.Especie as Especie9_1_, nfiscal0_.ESTENT as ESTENT9_1_, nfiscal0_.FPagto as FPagto9_1_, nfiscal0_.ICMSobreIPI as ICMSobr30_9_1_, nfiscal0_.Liquido as Liquido9_1_, nfiscal0_.Marca as Marca9_1_, nfiscal0_.Margem as Margem9_1_, nfiscal0_.Mensagem1 as Mensagem34_9_1_, nfiscal0_.Mensagem2 as Mensagem35_9_1_, nfiscal0_.Mensagem3 as Mensagem36_9_1_, nfiscal0_.NOPER as NOPER9_1_, nfiscal0_.Numero as Numero9_1_, nfiscal0_.ObsComissao as ObsComi39_9_1_, nfiscal0_.CodOrcamento_ID as CodOrca71_9_1_, nfiscal0_.OrdemCompra as OrdemCo40_9_1_, nfiscal0_.OrigemPedido as OrigemP41_9_1_, nfiscal0_.PerComl as PerComl9_1_, nfiscal0_.Placa as Placa9_1_, nfiscal0_.Quantidade as Quantidade9_1_, nfiscal0_.Revenda as Revenda9_1_, nfiscal0_.Status as Status9_1_, nfiscal0_.TipoNota as TipoNota9_1_, nfiscal0_.CodTransportadora_ID as CodTran72_9_1_, nfiscal0_.UF as UF9_1_, nfiscal0_.ValorExtra as ValorExtra9_1_, nfiscal0_.VlCofins as VlCofins9_1_, nfiscal0_.VlCsll as VlCsll9_1_, nfiscal0_.VlDescOutros as VlDescO52_9_1_, nfiscal0_.VlDescSuframa as VlDescS53_9_1_, nfiscal0_.VlICM as VlICM9_1_, nfiscal0_.VlIPI as VlIPI9_1_, nfiscal0_.VlIR as VlIR9_1_, nfiscal0_.VlInss as VlInss9_1_, nfiscal0_.VlIss as VlIss9_1_, nfiscal0_.VlMercadoria as VlMerca59_9_1_, nfiscal0_.VlNota as VlNota9_1_, nfiscal0_.VlPis as VlPis9_1_, nfiscal0_.VlRetInss as VlRetInss9_1_, nfiscal0_.VlRetIss as VlRetIss9_1_, nfiscal0_.VlServico as VlServico9_1_, nfiscal0_.VlSubst as VlSubst9_1_, nfiscal0_.Vlfrete as Vlfrete9_1_, nfiscal0_.Vloutros as Vloutros9_1_, nfiscal0_.Vlseguro as Vlseguro9_1_, cobrancase1_.Cliente as Cliente3_, cobrancase1_.Empresa as Empresa3_, cobrancase1_.Filial as Filial3_, cobrancase1_.Titulo as Titulo3_, cobrancase1_.Serie as Serie3_, cobrancase1_.Digito as Digito3_, cobrancase1_.Digito as Digito2_0_, cobrancase1_.Empresa as Empresa2_0_, cobrancase1_.Serie as Serie2_0_, cobrancase1_.Titulo as Titulo2_0_, cobrancase1_.Agencia as Agencia2_0_, cobrancase1_.ArquivoBoleto as ArquivoB6_2_0_, cobrancase1_.Banco as Banco2_0_, cobrancase1_.Cartorio as Cartorio2_0_, cobrancase1_.Ccontabil as Ccontabil2_0_, cobrancase1_.Ccusto as Ccusto2_0_, cobrancase1_.Cfflagfj as Cfflagfj2_0_, cobrancase1_.Conta as Conta2_0_, cobrancase1_.DataBoleto as DataBoleto2_0_, cobrancase1_.DataEmissao as DataEmi14_2_0_, cobrancase1_.DataIndice as DataIndice2_0_, cobrancase1_.DataVencto as DataVencto2_0_, cobrancase1_.Datavenctopre as Dataven17_2_0_, cobrancase1_.FlgTpCobr as FlgTpCobr2_0_, cobrancase1_.Indice as Indice2_0_, cobrancase1_.Cliente as Cliente2_0_, cobrancase1_.Filial as Filial2_0_, cobrancase1_.NossoNumero as NossoNu20_2_0_, cobrancase1_.NroBanco as NroBanco2_0_, cobrancase1_.Observacao as Observacao2_0_, cobrancase1_.Origem as Origem2_0_, cobrancase1_.Situacao as Situacao2_0_, cobrancase1_.TipoOper as TipoOper2_0_, cobrancase1_.Valor as Valor2_0_, cobrancase1_.ValorNego as ValorNego2_0_, cobrancase1_.ValorRefer as ValorRefer2_0_ from deak.dbo.NFiscal nfiscal0_ left outer join deak.dbo.Cobranca cobrancase1_ on nfiscal0_.Cgcemissor=cobrancase1_.Cliente and nfiscal0_.Empresa=cobrancase1_.Empresa and nfiscal0_.Filial=cobrancase1_.Filial and nfiscal0_.NumNF=cobrancase1_.Titulo and nfiscal0_.Series=cobrancase1_.Serie where nfiscal0_.Cgcemissor=? and nfiscal0_.Empresa=? and nfiscal0_.Filial=? and nfiscal0_.NumNF=? and nfiscal0_.Series=? Hibernate: select transporta0_.CodTransportadora_ID as CodTrans1_19_2_, transporta0_.Ativo as Ativo19_2_, transporta0_.BaiTransp as BaiTransp19_2_, transporta0_.CEPTransp as CEPTransp19_2_, transporta0_.CFFLAGFJ as CFFLAGFJ19_2_, transporta0_.CGC as CGC19_2_, transporta0_.CidTransp as CidTransp19_2_, transporta0_.Contato as Contato19_2_, transporta0_.E_Mail as E9_19_2_, transporta0_.EndTransp as EndTransp19_2_, transporta0_.EstTransp as EstTransp19_2_, transporta0_.Fax as Fax19_2_, transporta0_.Frete as Frete19_2_, transporta0_.Funcao as Funcao19_2_, transporta0_.INSESTADUAL as INSESTA15_19_2_, transporta0_.NomeTransp as NomeTransp19_2_, transporta0_.Observacao as Observacao19_2_, transporta0_.Ramal as Ramal19_2_, transporta0_.Telefone as Telefone19_2_, transporta0_.TpEntrega as TpEntrega19_2_, nfiscalset1_.CodTransportadora_ID as CodTran72_4_, nfiscalset1_.Cgcemissor as Cgcemissor4_, nfiscalset1_.Empresa as Empresa4_, nfiscalset1_.Filial as Filial4_, nfiscalset1_.NumNF as NumNF4_, nfiscalset1_.Series as Series4_, nfiscalset1_.Cgcemissor as Cgcemissor9_0_, nfiscalset1_.Empresa as Empresa9_0_, nfiscalset1_.Filial as Filial9_0_, nfiscalset1_.NumNF as NumNF9_0_, nfiscalset1_.Series as Series9_0_, nfiscalset1_.Atendente_ID as Atendente5_9_0_, nfiscalset1_.BAIENT as BAIENT9_0_, nfiscalset1_.BaseICM as BaseICM9_0_, nfiscalset1_.BaseSubst as BaseSubst9_0_, nfiscalset1_.Bruto as Bruto9_0_, nfiscalset1_.CEPENT as CEPENT9_0_, nfiscalset1_.CFFLAGFJ as CFFLAGFJ9_0_, nfiscalset1_.CIDENT as CIDENT9_0_, nfiscalset1_.Cgc as Cgc9_0_, nfiscalset1_.CodTranspCli as CodTran13_9_0_, nfiscalset1_.CodVendedor_ID as CodVend14_9_0_, nfiscalset1_.Codtributacao as Codtrib15_9_0_, nfiscalset1_.Comissao as Comissao9_0_, nfiscalset1_.ComissaoExt as Comissa17_9_0_, nfiscalset1_.Comissaonf as Comissaonf9_0_, nfiscalset1_.CondPagto_ID as CondPagto19_9_0_, nfiscalset1_.ConttFone as ConttFone9_0_, nfiscalset1_.ConttNome as ConttNome9_0_, nfiscalset1_.ConttRamal as ConttRamal9_0_, nfiscalset1_.CustoFinanc as CustoFi23_9_0_, nfiscalset1_.DataEntrega as DataEnt24_9_0_, nfiscalset1_.DataNota as DataNota9_0_, nfiscalset1_.ENDENT as ENDENT9_0_, nfiscalset1_.Especie as Especie9_0_, nfiscalset1_.ESTENT as ESTENT9_0_, nfiscalset1_.FPagto as FPagto9_0_, nfiscalset1_.ICMSobreIPI as ICMSobr30_9_0_, nfiscalset1_.Liquido as Liquido9_0_, nfiscalset1_.Marca as Marca9_0_, nfiscalset1_.Margem as Margem9_0_, nfiscalset1_.Mensagem1 as Mensagem34_9_0_, nfiscalset1_.Mensagem2 as Mensagem35_9_0_, nfiscalset1_.Mensagem3 as Mensagem36_9_0_, nfiscalset1_.NOPER as NOPER9_0_, nfiscalset1_.Numero as Numero9_0_, nfiscalset1_.ObsComissao as ObsComi39_9_0_, nfiscalset1_.CodOrcamento_ID as CodOrca71_9_0_, nfiscalset1_.OrdemCompra as OrdemCo40_9_0_, nfiscalset1_.OrigemPedido as OrigemP41_9_0_, nfiscalset1_.PerComl as PerComl9_0_, nfiscalset1_.Placa as Placa9_0_, nfiscalset1_.Quantidade as Quantidade9_0_, nfiscalset1_.Revenda as Revenda9_0_, nfiscalset1_.Status as Status9_0_, nfiscalset1_.TipoNota as TipoNota9_0_, nfiscalset1_.CodTransportadora_ID as CodTran72_9_0_, nfiscalset1_.UF as UF9_0_, nfiscalset1_.ValorExtra as ValorExtra9_0_, nfiscalset1_.VlCofins as VlCofins9_0_, nfiscalset1_.VlCsll as VlCsll9_0_, nfiscalset1_.VlDescOutros as VlDescO52_9_0_, nfiscalset1_.VlDescSuframa as VlDescS53_9_0_, nfiscalset1_.VlICM as VlICM9_0_, nfiscalset1_.VlIPI as VlIPI9_0_, nfiscalset1_.VlIR as VlIR9_0_, nfiscalset1_.VlInss as VlInss9_0_, nfiscalset1_.VlIss as VlIss9_0_, nfiscalset1_.VlMercadoria as VlMerca59_9_0_, nfiscalset1_.VlNota as VlNota9_0_, nfiscalset1_.VlPis as VlPis9_0_, nfiscalset1_.VlRetInss as VlRetInss9_0_, nfiscalset1_.VlRetIss as VlRetIss9_0_, nfiscalset1_.VlServico as VlServico9_0_, nfiscalset1_.VlSubst as VlSubst9_0_, nfiscalset1_.Vlfrete as Vlfrete9_0_, nfiscalset1_.Vloutros as Vloutros9_0_, nfiscalset1_.Vlseguro as Vlseguro9_0_, transporta2_.cnpj as cnpj20_1_, transporta2_.apuracaoIcms as apuracao2_20_1_, transporta2_.ativEconPrinc as ativEcon3_20_1_, transporta2_.ativEconSec as ativEcon4_20_1_, transporta2_.bairro as bairro20_1_, transporta2_.caePrimario as caePrima6_20_1_, transporta2_.caeSecundario as caeSecun7_20_1_, transporta2_.caixapostal as caixapos8_20_1_, transporta2_.cep as cep20_1_, transporta2_.cnaeFiscalPrimario as cnaeFis10_20_1_, transporta2_.cnaeFiscalSecundario as cnaeFis11_20_1_, transporta2_.complemento as complem12_20_1_, transporta2_.dtAbertura as dtAbertura20_1_, transporta2_.dtIniAtividade as dtIniAt14_20_1_, transporta2_.dtSitCadastral as dtSitCa15_20_1_, transporta2_.email as email20_1_, transporta2_.fax as fax20_1_, transporta2_.ie as ie20_1_, transporta2_.logradouro as logradouro20_1_, transporta2_.lote as lote20_1_, transporta2_.motSitCadastral as motSitC21_20_1_, transporta2_.municipio as municipio20_1_, transporta2_.natJuridica as natJuri23_20_1_, transporta2_.nomeFantasia as nomeFan24_20_1_, transporta2_.numero as numero20_1_, transporta2_.observacoes as observa26_20_1_, transporta2_.razaoSocial as razaoSo27_20_1_, transporta2_.sitCadastral as sitCada28_20_1_, transporta2_.statusConsulta as statusC29_20_1_, transporta2_.telefone as telefone20_1_, transporta2_.ticket as ticket20_1_, transporta2_.codTransp as codTransp20_1_, transporta2_.uf as uf20_1_ from deak.dbo.Transportadora transporta0_ left outer join deak.dbo.NFiscal nfiscalset1_ on transporta0_.CodTransportadora_ID=nfiscalset1_.CodTransportadora_ID left outer join deak.dbo.TransportadoraConsult transporta2_ on transporta0_.CodTransportadora_ID=transporta2_.codTransp where transporta0_.CodTransportadora_ID=?

O estranho que ele esta fazendo os selects relacionando as tabelas mas eu setei os relacionamentos como LAZY justamente pra não fazer isso, e em momento algum eu chamo algum get a não ser RazaoSocial e CNPJ que nao relaciona com nehum outro objeto, ou não tem nada a ver e estou falando besteira?

Srs.
Não quero fugir do escopo mais muito me interessou o título do tópico, por isso, queria saber se o desempenho do JPA (e suas implementações como Hibernate) efetivamente é ruim. Nunca utilizei (por isso a pergunta), e na minha empresa o pessoal não aderiu JPA justamente por esse motivo e por não conhecer gostaria de confirmar isso com a galera aqui do GUJ. E o que mais intriga o pessoal lá, além do desempenho, é o fato de “não saber o que acontece por dentro” (digamos assim) do framework. E diga-se de passagem, é o que o nosso colega acima está passando :smiley:
Se algum moderador achar conveniente abrir outro tópico para esse assunto fique a vontade…

Muito obrigado e aguardo opiniões!!

[]'s

Esse link tem um detalhe importante sobre LAZY em @OneToOne
http://pilhuhn.blogspot.com/2008/02/be-careful-with-onetoone-and-lazy.html
Veja se não se aplica ao teu caso.

Muito estranho uma aplicação pequena dessas ja dando trabalho ao realizar consultas de apenas 1300 registros ele estoura a memoria da JVM mas não oque esta errado em meu mapeamento e pq ele nao funciona como deveria no Lazy, esqueci de comentar mas essa eh uma aplicação Desktop

descobri o problema estar fazendo os selects, na verdade foi uma correção de um outro problema
segue o metodo do meu GenericDao

protected <T extends Serializable> T getPurePojo(String query, Object[]... parametros) { Query qr = em.createNamedQuery(query); for (Object[] param : parametros) { qr.setParameter(param[0].toString(), param[1].toString()); } Object retorno = qr.getSingleResult(); em.refresh(retorno); return (T) retorno; }

eu ja tive um problema do tipo, quando duas aplicações acessam um mesmo banco e eu chamo o metodo getPurePojo() sem o refresh ele não traz os dados do banco e sim os dados da sessao os objetos nao mudam de velor, entao consegui resolver utilizando o refresh em cada objeto de retorno para assim quando eu faço uma consulta ele atualiza os dados do objeto pegando os dados do banco mesmo, mas quando uso o refresh ele da outro select popula todo relacionamento do objeto.

Agora não sei mais como fazer para resolver o problema de nao atualizar os dados do banco, ele só atualiza quando eu dou um comando de insert,update ou exclusao e depois faço uma busca, os dados vem certo igual do banco.

Voce esta tendo problemas com dados “desatualizados” pq o Hibernate, por padrao, mantem um “cache” das entidades que ele ja conhece (First Level Cache). Este cache eh limpo automaticamente quando voce fecha a sessao ou quando voce executa o “session.clear()”. Isso deve resolver seu problema com os dados desatualizados :slight_smile:

@neeryck - Veja a discussao aqui: http://guj.com.br/posts/list/210953.java

Quais as opcoes eu tenho de configuração de cache no Hibernate?
poderia me passar algum material de exemplo estou utilizando JPA + Hibernate

com o em.clear() realmente funcionou valew

Vamos por partes :slight_smile:

  1. Cache x Hibernate
    Hibernate possui dois tipos de cache. Cache de Primeiro Nivel, que eh um cache interno que cada sessao possui e que eh zerado a cada “clear” ou quando a sessao fecha, e Cache de Segundo Nivel, onde se usa um produto que lida especificamente com cache, como o JBoss Cache ou EHCache.

  2. Cache significa “nao preciso ir ao banco de dados pq eu sei o que tem la”. Para isso, voce precisa ter um lugar central que coordena as atualizacoes do banco e que possa invalidar o que esta no cache (para que nao tenha informacoes antigas). No caso de aplicacoes desktop, nao existe este lugar “central” (a menos que vc esteja usando um cache distribuido, onde o cache de cada maquina conversa com o cache de outra, mas isso eh um topico mais avancado). Entao, no seu caso, diria que o cache causaria mais danos do que beneficios.

  3. Nao use cache. Nunca. (por padrao) :slight_smile: Cache foi feito para melhorar performance somente onde vc ja identificou um problema real de performance que nao pode ser solucionado de outro jeito. Entao, a menos que vc entenda exatamente o problema e saiba exatamente os beneficios/maleficios do cache, voce nao deve usar cache. Cache deve sempre ser uma decisao muito bem estudada e cirurgicamente implementada.

Se ainda assim quiser usar cache, veja aqui:
http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html#performance-cache

valew, as vezes esqueço que to desenvolvendo aplicação Desktop :slight_smile: