Open Session In View

6 respostas
jsfjavahibernate
C

alguém poderia me indicar uma solução mais elegante ao Open Session in View ?

6 Respostas

J

Seria melhor você especificar o problema que voce passa. O ideal é nao precisar de nada desse tipo.

L

Já que você tá usando Java EE, que tal usar Container Managed Transactions?

Você define o método do controller/service como REQUIRED e marca todos os outros como MANDATORY. Assim, toda operação de um controller/service é tratada de forma atômica, em relação às outras e você não precisa nem encostar em código de transação.

C

meu problema é o seguinte estou trabalhando com hibernate e com o pattern Open Session in View. o que funciona muito bem em determinados momentos mas que em alguns momentos acontecem muitos erros de LazyInitializationException.
eu gostei da sugestão do lvbarbabora mas se existirem outras podem comentar

L

Quando você faz uma busca e o Hibernate te devolve objetos, ele te devolve proxies (através de reflection), e não os objetos reais. Quando você acessa um método get, o proxy faz com que o framework emita uma nova query para o DB para popular a devida referência e te retornar no get. Para que isso ocorra, é necessário haver uma seção aberta. Eu não sei como é o default do Hibernate, mas eu acredito que as durações da seção e da transação sejam análogas: quando a transação termina, a seção é fechada.

Quando você chama um get no proxy sem que aquele dado esteja carregado e fora de uma seção, o proxy vai tentar contatar o framework e vai perceber que não há seção. Por isso uma LazyInitializationException é lançada.

Você pode fazer com que a seção continue aberta independente da presença de transações ou não. Não sei como fazer isso especificamente no Hibernate, mas no JPA existe o Extended Persistence Context feito exatamente para isso.

Outra solução é simplesmente mandar para a view (que eu acredito que é o lugar onde a exception está acontecendo) todos os dados que ela precisa, antes de encerrar a seção. Para isso, você pode ou chamar os métodos de lazy loading antes de fechar a seção (só chama sem capturar o retorno), ou então setar a propriedade como EAGER ao invés de LAZY.

C

realmente você está correto, a solução Open Session in View não é ruim mas estou tendo problemas (provavelmente por minha culpa) então estava querendo outras alternativas vou estudar essas que você me passou para ver se me atende.

J

“Open Sessino in View” é apelação, mas bem ou mal é uma forma de remediar o seu problema de arquitetura.

Se quiser trabalhar com hibernate com o mínimo de eficiência, então pelo menos utilize os recursos dele para gerar queries sob controle. Pode utilizar HQL/JPQL ou Criteria, aplicando “fetch” para redefinir os relacionamentos mapeados de lazy para eager. Assim evita inclusive o famoso problema de n+1 queries dentro de uma mesma requisição, com várias idas ao servidor de banco de dados sem necessidade, o que prejudica performance. Então, você resolve de uma vez ou com um mínimo de idas para pegar o que precisa do banco e atender de forma eficiente a requisição web. Com isso, durante o processamento da view não precisa mais ter a conexão aberta para ficar pipocando os lazys, podendo fechar o mais cedo possível.

Sei que HQL/JPQL/JPQ… e principalmente Criteria são horríveis de se trabalhar, mas Hibernate é a ferramenta que você escolheu, então terá arcar com os custos para entregar resultado eficiente. Eu pessoalmente prefiro trabalhar diretamente com SQL e sem Hibernate. Em último caso você também pode utilizar SQL com Hibernate.

Dá uma olhada:

Sobre HQL: https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/chapters/query/hql/HQL.html

Criado 18 de junho de 2017
Ultima resposta 20 de jun. de 2017
Respostas 6
Participantes 3