我在Spring Boot文档中看到了spring.jpa.open-in-view=true
属性,它与JPA配置相关。
- 如果没有提供此属性,
true
是否是默认值? - 这个属性实际上是做什么的?我没有找到任何好的解释。
- 它是否使您使用
SessionFactory
而不是EntityManagerFactory
?如果是,我该如何告诉它允许我使用EntityManagerFactory
?
谢谢!
我在Spring Boot文档中看到了spring.jpa.open-in-view=true
属性,它与JPA配置相关。
true
是否是默认值?SessionFactory
而不是EntityManagerFactory
?如果是,我该如何告诉它允许我使用EntityManagerFactory
?谢谢!
不要让业务层决定如何获取视图层所需的所有关联信息,而是使用OSIV(在视图中打开会话)强制持久性上下文保持打开状态,以便视图层可以触发代理初始化,如下图所示。
OpenSessionInViewFilter
调用底层 SessionFactory
的 openSession
方法,获得一个新的 Session
。Session
绑定到 TransactionSynchronizationManager
。OpenSessionInViewFilter
调用 javax.servlet.FilterChain
对象引用的 doFilter
方法,继续处理请求。DispatcherServlet
,并将 HTTP 请求路由到底层的 PostController
。PostController
调用 PostService
来获取 Post
实体列表。PostService
开启一个新事务,HibernateTransactionManager
重复使用由 OpenSessionInViewFilter
打开的同一 Session
。PostDAO
获取 Post
实体列表,不初始化任何懒加载属性。PostService
提交底层事务,但是 Session
没有关闭,因为它是外部打开的。DispatcherServlet
开始呈现 UI,并导航到懒加载属性并触发其初始化。OpenSessionInViewFilter
可以关闭 Session
,底层数据库连接也会被释放。UI层仅限于导航关联,这可能会触发N+1查询问题。虽然Hibernate提供了@BatchSize
以批处理方式获取关联数据,FetchMode.SUBSELECT
可应对此情况,但这些注释会影响默认的获取计划,因此会应用于每个业务用例。出于这个原因,数据访问层查询更加合适,因为它可以根据当前用例数据获取要求进行定制。
最后,数据库连接在UI渲染阶段被保持,这增加了连接租约时间,并由于数据库连接池拥塞而限制了整体事务吞吐量。连接被保持的时间越长,其他并发请求等待从池中获得连接的时间就越长。
不幸的是,在Spring Boot中默认启用OSIV(Open Session in View), 从性能和可伸缩性的角度来看,OSIV确实是一个糟糕的想法。
因此,请确保在application.properties
配置文件中有以下条目:
spring.jpa.open-in-view=false
这将禁用OSIV,以便您可以正确处理LazyInitializationException
。
从2.0版本开始,Spring Boot默认启用OSIV时会发出警告,因此您可以在影响生产系统之前发现此问题。
这个属性将注册一个OpenEntityManagerInViewInterceptor
,它会将一个EntityManager
注册到当前线程中,因此在Web请求结束之前,您将拥有相同的EntityManager
。这与Hibernate的SessionFactory
无关。
可能有点晚了,但是我正在尝试更深入地了解关闭与打开的影响,我发现这篇文章很有用 spring-open-session-in-view
希望这能帮助到某些人......
open-in-view
以防止LazyInitializationException的出现。spring:
jpa:
properties:
hibernate.enable_lazy_load_no_trans: true
join fetch
或@EntityGraph
,但这会增加开发人员的复杂性。但这可以在之后提高性能。hibernate.enable_lazy_load_no_trans
并关闭open-in-view
,但找到触发enable_lazy_load_no_trans
功能的地方(最好通过日志链接)并进行修正。