Spring的Open Session In View模式下能否管控事务的Connection获取及实现方法?
OSIV模式下Spring Boot事务Connection获取管控实现方案
OSIV模式下完全可以实现对Connection获取时机的管控,避免事务执行前的业务逻辑占用连接导致的空闲浪费甚至连接泄漏问题,常用实现方案如下:
方案1:保留OSIV功能,开启延迟Connection获取
Spring Boot 2.0+ 内置的Hibernate版本已经支持延迟获取连接的配置,无需修改业务代码,仅调整配置即可保留OSIV的懒加载能力,同时避免提前占用连接:
- 核心原理:开启配置后,请求绑定EntityManager时不会立刻申请数据库连接,仅当真正执行SQL操作、或进入
@Transactional事务方法时才会从连接池获取Connection - 配置示例:
spring: jpa: open-in-view: true # 保持OSIV开启,保留懒加载能力 properties: hibernate: connection: # 延迟获取连接核心配置,要求数据源默认auto-commit为true provider_disables_autocommit: true datasource: auto-commit: true # 保持默认配置即可,无需额外修改 hikari: maximum-pool-size: 20
方案2:关闭OSIV,完全自主管控连接生命周期
如果业务不需要用到Controller层的实体懒加载能力,关闭OSIV是最彻底的管控方案,此时Connection只会在@Transactional事务执行期间被占用,事务结束后立刻归还连接池:
- 首先关闭OSIV配置:
spring: jpa: open-in-view: false # 关闭OSIV模式
- 业务代码示例,将非事务耗时逻辑和事务逻辑拆分,避免耗时逻辑占用连接:
@Service public class OrderService { @Autowired private OrderRepository orderRepository; @Autowired private ThirdPartyRemoteService thirdPartyRemoteService; public OrderDetailVO getOrderDetail(Long orderId) { // 非事务逻辑:参数校验、调用第三方接口等耗时操作,此时不占用数据库连接 RemoteExtInfo extInfo = thirdPartyRemoteService.getOrderExtInfo(orderId); // 进入事务方法时才申请Connection,事务执行完成后立刻归还连接池 Order order = getTransactionOrder(orderId); // 后续非事务组装逻辑也不会占用连接 return assembleOrderDetail(order, extInfo); } @Transactional(readOnly = true) public Order getTransactionOrder(Long orderId) { return orderRepository.findById(orderId) .orElseThrow(() -> new IllegalArgumentException("订单不存在")); } private OrderDetailVO assembleOrderDetail(Order order, RemoteExtInfo extInfo) { // 省略VO组装逻辑 return new OrderDetailVO(); } }
注意:关闭OSIV后如果在Controller层直接访问实体类的懒加载属性,会抛出
LazyInitializationException异常,需要提前在事务内完成懒加载属性的初始化。
连接获取时机验证方法
可以通过Hikari连接池的监控指标验证配置是否生效,添加如下配置暴露监控端点:
management: endpoints: web: exposure: include: hikaricp
调用业务接口前后访问/actuator/hikaricp端点查看活跃连接数变化,即可确认连接是否仅在事务执行期间被占用。
内容的提问来源于stack exchange,提问作者skyho
相关产品推荐
相关产品推荐

