Spring Data JPA库中如何管理数据库连接?

5

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

是谁负责处理数据库连接?@Transactional注释还是JPA仓库?

1个回答

4

简而言之

最终,Spring JPA / 事务基础架构通过线程绑定的EntityManager实例管理连接。事务的范围由用户代码中的@Transactional注释控制,但最终在Spring Data JPA的存储库实现中进行默认设置。如果使用OpenEntityManagerInViewFilter(在Spring Boot 1.x和2.x中默认启用),则会急切地执行连接获取。

详细信息

SimpleJpaRepository 配备了 Spring 的 @Transactional 注解,以确保在需要 JPA 运行事务的情况下(例如执行调用EntityManager.persist(…)….merge(…)),它将运行这些事务。它们的默认配置确保它们自动参与抽象级别较高的事务。也就是说,如果您有一个 Spring 组件本身被标记为 @Transactional,则存储库将仅参与已经运行的事务中:

@Component
class MyService {

  private final FirstRepository first;
  private final SecondRepository second;

  // Constructor omitted for brevity

  @Transactional
  void someMethod() {

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

两个仓库都参与事务,其中一个失败将回滚整个事务。
为了实现这一点,JpaTransactionManager 将使用 JPA 的 EntityManager 公开的事务管理 API 来启动事务并获取连接以供 EntityManager 实例的生命周期使用。有关详细信息,请参见 JpaTransactionManager.doBegin(…)OpenEntityManagerInViewFilter-Interceptor 的作用。
除非显式停用,否则Spring Boot 1.x和2.x Web应用程序将运行一个OpenEntityManagerInViewFilter。它用于创建EntityManager并因此相当早地获取连接并保持到请求处理的最后阶段,即在视图呈现之后。这使得JPA懒加载可用于视图呈现,但会使连接保持打开时间比仅用于实际事务工作所需的时间更长。
该主题是相当有争议的,因为它需要在开发人员方便性(能够遍历对象关系以在视图渲染阶段进行惰性加载)和触发昂贵额外查询以及资源使用时间更长之间取得平衡。

嗨,Oliver,谢谢你的解释。那么,即使响应是Json / Xml格式,OpenEntityManagerInViewFilter也会激活Lazy加载,对吗? - Magg
我同意不应该使用实体进行响应转换。 - Magg
大多数情况下,响应是基于某些实体状态进行渲染的,例如实体可能只是被转发到Jackson进行JSON编组。在这些情况下,您必须确保在渲染期间可以遍历关联。 - Oliver Drotbohm
在使用Jpa实体的情况下,由于所有惰性集合都在JSON序列化期间被初始化,这难道不会影响服务延迟吗? - Magg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接