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/2025-04-28.spring-boot-jpa-open-in-view-property-analysis/