首页 > 解决方案 > 如何为 Spring Data JPA 存储库管理数据库连接?

问题描述

我有一个关于 Spring Data 存储库如何处理数据源连接的问题。假设 Spring Data 存储库在方法执行时打开和关闭连接以及连接,那么通过在我的服务层中声明的事务如何@Transactional跨多个存储库调用启动?

谁处理数据库连接?@Transactional注释还是 JPA 存储库?

标签: jpatransactionsspring-data-jpaspring-data

解决方案


tl;博士

EntityManager最终是 Spring JPA / Transaction 基础设施通过实例的绑定管理来管理连接。事务的范围由@Transactional用户代码中的注释控制,但最终默认在 Spring Data JPA 的存储库实现中。在使用an 的情况下会急切地执行连接获取OpenEntityManagerInViewFilter(在 Spring Boot 1.x 和 2.x 中默认启用)。

细节

SimpleJpaRepository配备了 Spring 的@Transactional注解,以确保它在 JPA 需要它们的情况下运行事务(例如,执行对EntityManager.persist(…)or的调用….merge(…))。它们的默认配置确保它们自动参与以更高抽象级别开始的事务。即,如果您有一个@Transactional本身的 Spring 组件,存储库将简单地参与已经运行的事务:

@Component
class MyService {

  private final FirstRepository first;
  private final SecondRepository second;

  // Constructor omitted for brevity

  @Transactional
  void someMethod() {

     … = first.save(…);
     … = second.save(…);
  }
}

两个存储库都参与事务,其中一个存储库发生故障将回滚整个事务。

为此,JpaTransactionManager将使用 JPA 公开的事务管理 API来启动事务并在实例EntityManager的生命周期内获取连接。EntityManager详情请参阅JpaTransactionManager.doBegin(…)

OpenEntityManagerInViewFilter一个或的角色–Interceptor

除非显式停用,否则 Spring Boot 1.x 和 2.x Web 应用程序将在已OpenEntityManagerInViewFilter部署的情况下运行。它用于在EntityManager很早的时候创建一个连接并因此获得一个连接,并将其保留到请求处理的很晚,即在视图呈现之后。这具有 JPA 延迟加载可用于视图呈现的效果,但保持连接打开的时间比仅用于实际事务工作的时间长。

该主题是一个颇具争议的话题,因为它在开发人员便利(在视图渲染阶段遍历对象关系以延迟加载的能力)之间的微妙平衡,冒着触发昂贵的额外查询和保持资源使用更长时间的风险时间。


推荐阅读