如何为 Spring Data JPA 存储库管理数据库连接?

Mag*_*agg 5 jpa transactions spring-data spring-data-jpa

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

谁处理数据库连接?该@Transactional注解或JPA资料库?

Oli*_*ohm 4

太长了;博士

\n

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

\n

细节

\n

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

\n
@Component\nclass MyService {\n\n  private final FirstRepository first;\n  private final SecondRepository second;\n\n  // Constructor omitted for brevity\n\n  @Transactional\n  void someMethod() {\n\n     \xe2\x80\xa6 = first.save(\xe2\x80\xa6);\n     \xe2\x80\xa6 = second.save(\xe2\x80\xa6);\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

两个存储库都参与事务,其中一个存储库失败将回滚整个事务。

\n

为了实现这一点,JpaTransactionManager将使用 JPA 公开的事务管理 APIEntityManager来启动事务并在实例的生命周期内获取连接EntityManagerJpaTransactionManager.doBegin(\xe2\x80\xa6)详情请参阅。

\n

OpenEntityManagerInViewFilter或的作用\xe2\x80\x93Interceptor

\n

除非明确停用,否则 Spring Boot 1.x 和 2.x Web 应用程序将在OpenEntityManagerInViewFilter已部署的情况下运行。它用于创建EntityManager并因此很早就获取连接并将其保留到请求处理的最后阶段,即在渲染视图之后。这具有 JPA 延迟加载可用于视图渲染的效果,但保持连接打开的时间比仅用于实际事务工作时需要的时间更长。

\n

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

\n