Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

477
Visualizações
La carga diferida funciona, pero no debería

El contexto de esta pregunta está dentro de spring-boot, usando spring-data-jpa e hibernate.

Un colega escribió un @Service y anotó el método de servicio con @Transactional . El método de servicio carga una entidad y, posteriormente, accede a una colección cargada de forma diferida de uno a muchos ( fetch = FetchType.LAZY ). El método de servicio es invocado por algún delegador personalizado, al que volveré. Esto funciona bien cuando se invoca desde un punto final @RestController .

Cuando invoqué el servicio desde una ruta de camello (nuevamente a través del delegador personalizado) vomitó con una excepción de inicialización perezosa.

Al excavar, descubrió que el servicio implementa una interfaz, el delegador personalizado busca el servicio (se inyecta, por lo que tiene el proxy adecuado) y llama a un método en la interfaz que en realidad es un método predeterminado de Java-8. Este método predeterminado luego llama localmente al método @Transactional .

Así que ahí está el problema: esta es una llamada de método LOCAL, por lo que no se realiza el aspecto/proxy de la anotación @Transactional (usamos aspectJAutoProxy), por lo que el método NO se invoca dentro de una transacción, por lo que la carga diferida DEBERÍA fallar. Y para volver a verificar, también lo probé a través de una anotación @Scheduled : mismo comportamiento. Vomita como debería.

Mi pregunta: Entonces, ¿por qué funciona cuando se llama desde @RestController ? ¡Esto me está volviendo loco!

No hay ninguna anotación transaccional en el punto final del controlador de descanso.

Agregué un código de depuración al servicio usando TransactionSynchronizationManager.isActualTransactionActive() y muestra que en ningún caso hay una transacción, incluso cuando se llama a través del punto final del controlador.

Entonces, ¿por qué funciona la carga diferida cuando se llama desde el controlador? Descargué todo el SQL y en ningún momento la colección perezosa ya está cargada, por lo que no están en ningún caché de hibernación.

Recuerdo haber leído una vez que la carga diferida era una pista, no un comando, pero aun así... ¿por qué funciona en ese caso?

about 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

después de estar perplejos por esto en muchas ocasiones, me he topado con la respuesta:

sprint-boot está haciendo un administrador de entidad abierta a la vista a nuestras espaldas a través del interceptor OpenEntityManagerInView. No tenía idea de que esto estaba pasando.

Vea esta excelente respuesta de Vlad Mihalcea https://stackoverflow.com/a/48222934/208687

about 4 years ago · Santiago Trujillo Relatório

0

Cuando su método anota en la sesión de hibernación transaccional, se cierra después del método de retorno, si el objeto que regresa del método tiene la propiedad perezosa, la propiedad perezosa no se carga y obtiene una excepción de que la sesión se cierra. Puede usar buscar en la consulta o usar OSIV

about 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda