这个 spring.jpa.open-in-view=true 属性在 Spring Boot 中是什么?

16 浏览
0 Comments

这个 spring.jpa.open-in-view=true 属性在 Spring Boot 中是什么?

我在Spring Boot JPA配置的文档中看到了 spring.jpa.open-in-view=true 属性。

  • 如果没有提供该属性,true是否为默认值?
  • 这个属性真正做了什么?我没有找到任何好的解释;
  • 它是否使您使用 SessionFactory 而不是 EntityManagerFactory?如果是,我该如何告诉它允许我使用 EntityManagerFactory

谢谢!

admin 更改状态以发布 2023年5月24日
0
0 Comments

此属性将注册一个OpenEntityManagerInViewInterceptor,它会将一个EntityManager注册到当前线程,因此您将拥有相同的EntityManager,直到网络请求完成。这与Hibernate SessionFactory等内容无关。

0
0 Comments

OSIV反模式

开放会话试图(Open Session in View)强制将持久上下文保持打开状态,以便视图层可以触发代理初始化,而不是让业务层决定如何最好地获取视图层所需的所有关联。下图说明了该过程:

OSIV反模式

  • OpenSessionInViewFilter调用底层SessionFactoryopenSession方法并获取一个新的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渲染阶段发出的每一条额外语句都在自动提交模式下执行。自动提交会给数据库服务器带来压力,因为每个事务都会在结束时发出提交命令,这可能会触发将事务日志刷新到磁盘上。一种优化方法是将Connection标记为只读,这将使数据库服务器避免写入事务日志。

由于语句既由服务层生成,也由UI渲染过程生成,因此不再有关注点的分离。编写断言正在生成的语句数量的集成测试需要通过所有层(web、服务、DAO),同时将应用程序部署在web容器上。即使使用内存数据库(例如HSQLDB)和轻量级web服务器(例如Jetty),这些集成测试执行起来也比分离层且后端集成测试使用数据库,而前端集成测试则完全模拟服务层更慢。

UI层仅限于导航关联,这可能会触发N+1查询问题。尽管Hibernate提供了批量获取关联的@BatchSize和用于应对该场景的FetchMode.SUBSELECT,但注释会影响默认的获取计划,因此它们将应用于每个业务用例。因此,数据访问层查询更加适合,因为它可以为当前用例的数据获取要求进行调整。

最后但并非最不重要的,数据库连接在UI渲染期间保持,这增加了连接租赁时间并限制了整体事务吞吐量,因为数据库连接池拥塞。连接被保持得越久,其他并发请求就越会等待从池中获取连接。

Spring Boot和OSIV

不幸的是,在Spring Boot中默认启用了OSIV(Open Session in View),从性能和可扩展性的角度来看,OSIV真的是一个不好的想法。

因此,请确保在application.properties配置文件中有以下条目:

spring.jpa.open-in-view=false

这将禁用OSIV,以便您可以正确处理LazyInitializationException

从2.0版本开始,Spring Boot默认启用OSIV时会发出警告,因此您可以在它影响到生产系统之前发现此问题。

0