O OSIV Anti-Padrão
Em vez de deixar a camada de negócios decidir como é melhor buscar todas as associações que são necessárias para a camada de Visualização, OSIV (Sessão Aberta na Visualização) força o Contexto de Persistência a permanecer aberto para que a camada de Visualização possa acionar a inicialização do Proxy, conforme ilustrado pelo diagrama a seguir.

- O
OpenSessionInViewFilterchama o openSessionmétodo do subjacente SessionFactorye obtém um novo Session.
- O
Sessionestá vinculado ao TransactionSynchronizationManager.
- O
OpenSessionInViewFilterchama doFilterda javax.servlet.FilterChainreferência do objeto e a solicitação é processada posteriormente
- O
DispatcherServleté chamado e encaminha a solicitação HTTP para o subjacente PostController.
- O
PostControllerchama o PostServicepara obter uma lista de Postentidades.
- O
PostServiceabre uma nova transação e HibernateTransactionManagerreutiliza a mesma Sessionque foi aberta pelo OpenSessionInViewFilter.
- O
PostDAObusca a lista de Postentidades sem inicializar qualquer associação preguiçosa.
- O
PostServiceconfirma a transação subjacente, mas Sessionnão é fechado porque foi aberto externamente.
- O
DispatcherServletcomeça a renderizar a IU, que, por sua vez, navega pelas associações lazy e aciona sua inicialização.
- O
OpenSessionInViewFilterpode fechar o Sessione a conexão de banco de dados subjacente também é liberada.
À primeira vista, pode não parecer uma coisa terrível de se fazer, mas, uma vez que você vê da perspectiva do banco de dados, uma série de falhas começa a se tornar mais óbvia.
A camada de serviço abre e fecha uma transação de banco de dados, mas depois disso, não há nenhuma transação explícita acontecendo. Por esse motivo, cada instrução adicional emitida na fase de renderização da IU é executada no modo de confirmação automática. A confirmação automática pressiona o servidor de banco de dados porque cada instrução deve liberar o log de transações para o disco, causando, portanto, muito tráfego de E / S no lado do banco de dados. Uma otimização seria marcar o Connectioncomo somente leitura, o que permitiria ao servidor de banco de dados evitar a gravação no log de transações.
Não há mais separação de interesses porque as instruções são geradas tanto pela camada de serviço quanto pelo processo de renderização da IU. Escrever testes de integração que afirmam o número de instruções que estão sendo geradas requer passar por todas as camadas (web, serviço, DAO) enquanto o aplicativo é implantado em um contêiner da web. Mesmo ao usar um banco de dados na memória (por exemplo, HSQLDB) e um servidor web leve (por exemplo, Jetty), esses testes de integração serão mais lentos para executar do que se as camadas fossem separadas e os testes de integração de back-end usassem o banco de dados, enquanto o Os testes de integração front-end estavam zombando da camada de serviço como um todo.
A camada de IU é limitada a associações de navegação que podem, por sua vez, acionar N + 1 problemas de consulta . Embora o Hibernate ofereça @BatchSizeassociações de busca em lotes e FetchMode.SUBSELECTpara lidar com este cenário, as anotações estão afetando o plano de busca padrão, portanto, são aplicadas a todos os casos de uso de negócios. Por esse motivo, uma consulta da camada de acesso a dados é muito mais adequada porque pode ser adaptada aos requisitos atuais de busca de dados do caso de uso.
Por último, mas não menos importante, a conexão com o banco de dados é mantida durante toda a fase de renderização da IU, o que aumenta o tempo de concessão da conexão e limita o rendimento geral da transação devido ao congestionamento no conjunto de conexões do banco de dados. Quanto mais a conexão for mantida, mais outras solicitações simultâneas irão esperar para obter uma conexão do pool.
Spring Boot e OSIV
Infelizmente, OSIV (Open Session in View) é habilitado por padrão no Spring Boot , e OSIV é realmente uma má ideia do ponto de vista de desempenho e escalabilidade .
Portanto, certifique-se de que, no application.propertiesarquivo de configuração, você tenha a seguinte entrada:
spring.jpa.open-in-view=false
Isso desabilitará o OSIV para que você possa lidar da LazyInitializationExceptionmaneira certa .
A partir da versão 2.0, o Spring Boot emite um aviso quando o OSIV está habilitado por padrão, para que você possa descobrir esse problema muito antes que ele afete um sistema de produção.
Para obter mais detalhes sobre OSIV, consulte este artigo .