Spring Boot中spring.jpa.open-in-view=true属性解析
Spring Boot中spring.jpa.open-in-view=true属性解析
技术背景
在Spring Boot应用里进行JPA配置时,spring.jpa.open-in-view 是一个关键属性。它与Open Session in View(OSIV)模式相关,该模式会影响应用对数据库会话的管理,特别是在处理延迟加载的实体关联时。
实现步骤
1. 默认值
若未明确提供该属性,Spring Boot里 spring.jpa.open-in-view 的默认值为 true。这意味着默认启用了OSIV模式。
2. 开启 spring.jpa.open-in-view=true 时的工作原理
- 过滤器启动会话:
OpenSessionInViewFilter调用底层SessionFactory的openSession方法获取新的会话,然后将会话绑定到TransactionSynchronizationManager。 - 请求处理:
OpenSessionInViewFilter调用javax.servlet.FilterChain对象引用的doFilter方法,继续处理请求。DispatcherServlet接收HTTP请求并路由到对应的控制器。 - 服务层操作:控制器调用服务层方法,服务层开启新事务,
HibernateTransactionManager复用OpenSessionInViewFilter打开的会话。数据访问对象(DAO)获取实体列表,但不初始化任何延迟关联。 - 事务提交与会话保持:服务层提交事务,但会话不会关闭,因为它是外部打开的。
- 视图渲染与延迟关联初始化:
DispatcherServlet开始渲染UI,导航延迟关联并触发其初始化。 - 会话关闭:
OpenSessionInViewFilter关闭会话,释放底层数据库连接。
3. 关闭 spring.jpa.open-in-view=true
为避免OSIV模式带来的性能和可扩展性问题,建议在 application.properties 配置文件中设置:
1 | |
核心代码
若要手动配置 OpenEntityManagerInViewInterceptor,可参考以下示例:
1 | |
最佳实践
- 关闭OSIV:从性能和可扩展性角度考虑,应关闭
spring.jpa.open-in-view,并正确处理LazyInitializationException。 - 显式加载关联:采用连接查询(join fetch)或
@EntityGraph来显式加载延迟关联,避免在视图层触发不必要的查询。 - 日志监控:开启日志监控,找出触发延迟加载的位置,及时优化代码。
常见问题
1. 开启OSIV模式有哪些问题?
- 自动提交压力:服务层事务结束后,UI渲染阶段的额外语句以自动提交模式执行,增加数据库服务器压力。
- 关注点分离缺失:服务层和UI渲染过程都会生成数据库语句,增加集成测试的复杂度。
- N+1查询问题:UI层导航关联可能触发N+1查询问题,影响性能。
- 连接占用:数据库连接在UI渲染阶段一直被占用,增加连接租赁时间,限制事务吞吐量。
2. 关闭 spring.jpa.open-in-view 后如何处理 LazyInitializationException?
可使用连接查询(join fetch)或 @EntityGraph 显式加载关联,也可在必要时手动初始化延迟关联。
3. OpenEntityManagerInViewInterceptor 和 OpenEntityManagerInViewFilter 有什么区别?
OpenEntityManagerInViewInterceptor 是Spring机制,仅在使用 DispatcherServlet 时生效;OpenEntityManagerInViewFilter 可映射到所有配置的Servlet。若只使用 DispatcherServlet,可添加属性并移除过滤器;否则使用过滤器。
Spring Boot中spring.jpa.open-in-view=true属性解析
https://119291.xyz/posts/spring-boot-jpa-open-in-view-property-analysis/