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

新手上路,请多包涵

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

  • true 如果根本没有提供此属性的默认值?
  • 这到底有什么作用?我没有找到任何好的解释;
  • 它会让您使用 SessionFactory 而不是 EntityManagerFactory 吗?如果是,我如何告诉它允许我使用 EntityManagerFactory 代替?

谢谢!

原文由 Carlos Alberto 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

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

原文由 dunni 发布,翻译遵循 CC BY-SA 4.0 许可协议

OSIV 反模式

OSIV(在视图中打开会话)不是让业务层决定如何最好地获取视图层所需的所有关联,而是强制持久性上下文保持打开状态,以便视图层可以触发代理初始化,如图所示通过下图。

OSIV 反模式

  • The OpenSessionInViewFilter calls the openSession method of the underlying SessionFactory and obtains a new Session .
  • Session 绑定到 TransactionSynchronizationManager
  • OpenSessionInViewFilter 调用 doFilter javax.servlet.FilterChain 对象引用并进一步处理请求
  • DispatcherServlet 被调用,并将 HTTP 请求路由到底层 PostController
  • PostController 调用 PostService 获取 Post 实体列表。
  • The PostService opens a new transaction, and the HibernateTransactionManager reuses the same Session that was opened by the OpenSessionInViewFilter .
  • 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(在视图中打开会话) ,从性能和可扩展性的角度来看,OSIV 确实是一个坏主意。

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

 spring.jpa.open-in-view=false

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

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

原文由 Vlad Mihalcea 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题