[Hibernate] Problema com collections de objeto na session

8 respostas
A

Em um projeto web com VRaptor, tenho um objeto user armazenado na session.

Esse objeto tem uma collection mapeada com Hibernate Annotations, da seguinte maneira:

@OneToMany(mappedBy="user")
	private List<UserOps> ops;

Na minha UserLogic tenho a ‘action’, home, que pelo fato do objeto user estar armazenado na sessão não faz nada e retorna void.

No user.home.jsp, eu tenho que exibir a collection ops usando displaytag. Até aí tudo bem, funciona direitinho. O único problema, é que se eu adiciono um registro na tabela ops do diretamente no banco de dados e dou um reload na user.home.logic, esse registro não aparece.

<display:table id="op" name="${user.ops}" requestURI="user.home.logic" excludedParams="*">

Já tentei usando as annotations @LazyCollection, @Fetch e mesmo assim, o Hibernate só carrega a collection no momento em que o objeto user é armazenado na seção (no login, no caso).

Como faço para que o Hibernate sempre busque os itens da collection no BD?

8 Respostas

A

Nenhuma dica?

Tentei, colocar o id do objeto User na sessão (ao invés de todo o objeto) e a cada ‘logic’ do VRaptor recuperar o objeto usando o UserDao(). Nesse caso, ops reflete todos os objetos da tabela a cada reload. Mas essa é a solução correta?

Não tem como fazer o método getOps sempre fazer o loading da collection a partir da base, ou, em outras palavras, toda vez que a propriedades ops for acessada executar o SQL na base?

Como? Esse comportamente é chamado de Lazy ou Eager (termos da documentação do Hibernate).

Qualquer ajuda é bem-vinda!

Obrigado.

rodrigoallemand

Peloi que eu entendi vc retorna um objeto do hibernate, coloca na sessão e pretende que mudanças no banco sejam “vistas” por esse objeto… o problema do objeto persistente x objeto transiente…

Acho que seu problema é que quando vc coloca o objeto na sessão e “commita” a transação (pode ser pelo simples fato de fechar a sessão) o objeto user se torna transiente, e não mais persistente. A sessão que ele estava ligado não existe mais… As novas mudanças não serão refletida…

Existe uma maneira de tratar sessões “grandes” no Hibernate (Hibernate in Action) pelo que eu lembro, mas nunca fiz isso.

Mas acho que seu problema é esse… o objeto perdeu a referencia da sessão… e lembre-se que, se vc tiver ativado alguma politica de cache (primeiro ou segundo nivel) as mudanças “manuais” podem não ser vistas diretamente…

A

Então, eu já desativei os cache justamente por causa disso.

Sob a luz da sua dia, acho que realmente tem que ver com o lance da sessão.

Eu tenho uma aplicação com Struts onde não tenho esse problema. Uso um filtro que a documentação do Hibernate sugere.

Nessa com VRaptor, achei que o DaoInterceptor (da apostila da Caelum) resolvesse o problema.

rodrigoallemand

Pois é… nunca user o VRaptor, não posso te ajudar nisso… mas o intuito do Intercepting Filter proposto do Hibernate deve ser o mesmo do DAOInterceptor proposto pela Caelum.

Mas funcionava assim com o Filter? Teoricamente não deveria funcionar tambem…

O problema está justamente no fechamento da sessão que gerou aquele objeto, deixando-o desatachado e consequentemente não mais controlado, nem por Lazy nem pro intervenção divina…

A

É acho que o problema é esse mesmo.

Pois é, usando o Intercepting Filter funciona em uma outra aplicação que tenho usando o Struts.

A diferença dessa outra aplicação é que eu não armazeno o objeto user na sessão, só o id dele, e toda vez que preciso acessar alguma propriedade, carrego o objeto na action.

Já testei essa alternativa com o VRaptor e funciona. Mas imagino que armazenar o objeto todo melhore a perfomance da aplicação, já que economizo o load do objeto user.

A

Tentei usar o método lock de Session, para reassociar o objeto a uma sessão do Hibernate. Mas mesmo assim, ele só faz uma busca na base, pelo Id do meu objeto user.

Algum outro meio de solucionar esse problema?

rodrigoallemand

Recapitulado…
Vc precisa buscar um objeto no banco, coloca-lo na sessão e a qualquer momento quando solicitado, seja após 20 requests processados, vc quer que ele esteja linkado no banco, correto?

Sugiro vc usar um controle de sessão longo exclusivo para este objeto…
[url=http://www.hibernate.org/43.html#A5http://www.hibernate.org/43.html#A5[/url]

A

Só para deixar claro, o que eu preciso é que cada vez que uma página for carregada, o método getOps retornasse os registros atualizados da base de dados.

Porque eu tenho outro processo atualizando/criando esses registros. Quero que cada request, reflita essas alterações, do jeito que está, o método getOps de User só faz a consulta no momento do login do User.

Eu já tentei usar esse Open In View, mas não entendi direito como ele se integra com o VRaptor.

Teoricamente, não é a mesma coisa que faz o DaoInterceptor?

Ou seja, os Interceptors do VRaptor não equivalem ao Filter? Se eu usar um Filter, como ele se encaixa do fluxo de processamento do VRaptor?

Criado 6 de junho de 2007
Ultima resposta 22 de jun. de 2007
Respostas 8
Participantes 2