Lazy - opinião de vocês

Olá, tudo bom?

Bom, eu coloquei lazy = true nos relacionamentos.
Isto fez melhorar bastante a performance.
Então, comecei a usar o Hibernate.initialize(obj) para iniciar as collections
dentro do método get.
Ex.:

Company tem uma List de users.

então, dentro de company eu tenho um getUsers() que
está assim:

List getUsers() throws HibernateException
{
Hibernate.initialize(users);
return users;
}

Vcs acham que está é a maneira certa???

obrigado

abraço

se vc vai fazer um initialize para que usar lazy=true?

Então, eu devo não estar entendendo alguma coisa.

Como o lazy=true, as collections só serão carregadas quando eu precisar.
Seria isso?

Sim :smiley:

Mas quando eu preciso, num Action do Struts, vai dar
LazyInitializationException.

Então eu tava vendo na documentação que daí usa-se o
Hibernate.initialize(…) para a collection.
Onde eu coloco este?
Ou é o usuário que está usando o DAO que deve colocar?

obrigaduuu

ok,

nao é sempre que vc vai mostrar isto na tela correto? Vão existir lugares em que vc vai querer que seja lazy. Entao deixe no dao, ou nao própria Action do Struts, classe de negócios sei lá.

O problema é que não se pode fechar a session sem antes ter inicializado tudo, se implementar este pattern nao precisa fazer o initialize http://www.hibernate.org/43.html, pois a session é fechada depois que sua view estiver terminada.

O probleminha é que eu criei uma estrutura (já está praticamente tudo pronto) onde cada método abre e já fecha a session.
Na verdade, algumas vezes não sou nem eu quem controla isso,
pois criei uma classe que abstrai toda abertura e fechamento de Sessions.

obrigado!!!

ok, quando fiz em Struts eu também tinha uma classe abstrata assim.

legal!!!

e o Session vc pegava de um ThreadLocal ou do Open Session in View?

Como posso melhorar a performance das minha queries hibernate
usando a estrutura que falei anteriormente???

Ricardo, não entendi o seguinte, vc disse isso por que é redundante ou por que uma coisa é contraria a outra? Eu li em outro post aqui do GUJ que se vc usasse ThreadLocalSession não seria possivel usar lazy. No fim das contas não entendi bem, mas, então, se eu usar o initialize, a collection vai ser carregada apenas quando eu precisar tambem?

Até.

[quote=“tads”]legal!!!

e o Session vc pegava de um ThreadLocal ou do Open Session in View?[/quote]

Veja o código do site:

public class Persistance implements Filter
{    
    /**
     * Holds the current hibernate session, if one has been created.
     */
    protected static ThreadLocal hibernateHolder = new ThreadLocal(); 

ThreadLocal : retornar sempre a mesma session para uma request. Se em uma request vc chamar 10 DAO´s e vários métodos nestes DAO´s, vc terá usado apenas uma session session.

Open Session in View: Não fechar a Session na Action. Quando vc enviar para o JSP/velocity sua session vai estar aberta ainda. Isto é feito com um filtro, ou com um interceptor do WebWork. (ta aí uma das coisas que eu gosto nele)…

Vc somente vai usar o inicialize em casos como o do tads (“LazyInitializationException”). Isto acontece pq quando se tenta inicializar uma collection quando a session está fechada. Devido a isso agente pede para o Hiberante inicializar antes de fechar a Session. Mas como vc pode usar este relacionamento em outras áreas do sistema, é melhor deixar o lazy=true no xml.

Pode sim.

Nao.
-> laxy=true: só carrega quando vc usar
-> initialize: força o Hiberante a carregar uma collection com lazy=true ou um proxy.

[quote=“tads”]legal!!!

e o Session vc pegava de um ThreadLocal ou do Open Session in View?[/quote]

No sistema que fiz em Struts não usei o Open Session in View. Quando eu precisava eu fazia o inicialize igual vc. Tinha uma classe abstrata que controlava as transações.

Porém muitas vezes eu usava queries com o “fetch” para inicializar um objeto. Assim eu já forçava a inicialização no momento da query, evitando aquele Hiberante.inicialize() chato…

Em outro que usei o WebWork fiz um interceptor e o Open Session in View foi feito automaticamente. Resultado, nunca precisei fazer o inicialize :slight_smile: O interceptor que gerenciava as transações.

[quote=“tads”]Como posso melhorar a performance das minha queries hibernate
usando a estrutura que falei anteriormente???[/quote]

lazy=true é para one-to-many, tente usar proxies para many-to-one. Se não usar isso a performance vai para o saco. :wink:

O método session.filter é uma boa também. Vc filtra uma collection sem inicializá-la e seleciona somente o que vc quer.

Use os métodos para fazer paginação. Se tem 50.000 registros vc provavelmente não vai precisar trazer todos para memória…

query.setFirstResult(20);
query.setMaxResults(10);

Fora isso a performance do Hibernate é muito boa.

opa!

cara, desculpa levantar o tópico tanto tempo depois mas eu estava procurando algumas coisas sobre paginação e vi este tópico… estou usando ww + hibernate + velocity…

ricardo, implementando do jeito que vc falou, o que vc faria para saber a quantia de registros que a query iria retornar? desculpe se a resposta for um simples count(*)… o que quero é exatamente saber se existe outro modo melhor…
é que preciso saber a quantidade de páginas totais, e para isso necessito saber quantos registros seriam retornados… não quero pegar todos os registros da consulta prá mostrar uma dúzia na tela e cada vez que o cara trocar de página buscar tudo de novo…

valeu,
té+

count(*) mesmo

List l = ( List ) session.filter( obj.getOutrosObjs(), “SELECT count(*)” );
int count = l.get( 0 );

opa!

em primeiro lugar obrigado pela resposta!
em segundo lugar, o assunto já está totalmente fora do título do tópico… foi mal, mas acho que não precisa abrir outro tópico…

e agora ao que interessa:
como fica o desempenho com este count(*)?
acredito que deste jeito de menos i/o que selecionar tudo sempre, mas ainda resta a dúvida…

neste seu exemplo, ficaria +/- isso:
1º - seleciona os registros e joga num list;
2º - faz um filter com o list para pegar o count;

é isso?

por ex, seleciona os 10 primeiros depois faz um filter(list, “count”) prá retornar o total?

valeu,
té+

Acredito que a list tem que ser transiente.

Mas nem importa nesse caso, pois no count(*) os objetos do relacionamento não são inicializados.

Então sem problemas você fazer uma query e depois o filter.