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 调用底层 SessionFactoryopenSession 方法获取新的会话,然后将会话绑定到 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
spring.jpa.open-in-view=false

核心代码

若要手动配置 OpenEntityManagerInViewInterceptor,可参考以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

public class WebConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
OpenEntityManagerInViewInterceptor interceptor = new OpenEntityManagerInViewInterceptor();
registry.addWebRequestInterceptor(interceptor);
}
}

最佳实践

  • 关闭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. OpenEntityManagerInViewInterceptorOpenEntityManagerInViewFilter 有什么区别?

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/
作者
ww
发布于
2025年4月28日
许可协议