事务资源同步

现在应该清楚如何创建不同的事务管理器以及它们如何链接到需要与事务同步的相关资源(例如,DataSourceTransactionManager 到 JDBC DataSourceHibernateTransactionManager 到 Hibernate SessionFactory 等)。本节描述了应用程序代码(直接或间接,通过使用持久化 API,例如 JDBC、Hibernate 或 JPA)如何确保正确创建、重用和清理这些资源。本节还讨论了如何通过相关的 TransactionManager(可选地)触发事务同步。

高级同步方法

首选方法是使用 Spring 最高级别的基于模板的持久化集成 API,或者使用事务感知的 FactoryBean 或代理管理本地资源工厂,从而使用本地 ORM API。这些事务感知的解决方案在内部处理资源的创建和重用、清理、资源的可选事务同步以及异常映射。因此,用户数据访问代码无需处理这些任务,只需专注于非样板式的持久化逻辑。通常,您可以使用本地 ORM API 或通过使用 JdbcTemplate 采用模板方法进行 JDBC 访问。这些解决方案将在本参考文档的后续章节中详细介绍。

低级同步方法

诸如 DataSourceUtils(用于 JDBC)、EntityManagerFactoryUtils(用于 JPA)、SessionFactoryUtils(用于 Hibernate)等类位于较低级别。当您希望应用程序代码直接处理本地持久化 API 的资源类型时,您可以使用这些类来确保获得正确的 Spring Framework 管理的实例,事务得到(可选)同步,并且过程中发生的异常被正确地映射到一致的 API。

例如,对于 JDBC,您可以使用 Spring 的 org.springframework.jdbc.datasource.DataSourceUtils 类,而不是传统的 JDBC 调用 DataSource 上的 getConnection() 方法的方法,如下所示

Connection conn = DataSourceUtils.getConnection(dataSource);

如果现有事务已经同步(链接)了一个连接,则返回该实例。否则,该方法调用将触发创建新连接,该连接(可选地)与任何现有事务同步,并在同一事务中可供后续重用。如前所述,任何 SQLException 都被包装在 Spring Framework 的 CannotGetJdbcConnectionException 中,它是 Spring Framework 非检查型 DataAccessException 类型层次结构中的一种。这种方法提供了比从 SQLException 轻松获得的信息更多,并确保了跨数据库甚至跨不同持久化技术的移植性。

这种方法在没有 Spring 事务管理(事务同步是可选的)的情况下也有效,因此无论您是否使用 Spring 进行事务管理,都可以使用它。

当然,一旦您使用了 Spring 的 JDBC 支持、JPA 支持或 Hibernate 支持,通常更倾向于不使用 DataSourceUtils 或其他辅助类,因为通过 Spring 抽象进行工作比直接使用相关 API 更令人满意。例如,如果您使用 Spring JdbcTemplatejdbc.object 包来简化 JDBC 的使用,正确的连接检索会在幕后发生,您无需编写任何特殊代码。

TransactionAwareDataSourceProxy

在最低级别存在 TransactionAwareDataSourceProxy 类。它是目标 DataSource 的代理,它包装了目标 DataSource 以添加对 Spring 管理的事务的感知。在这方面,它类似于 Jakarta EE 服务器提供的事务性 JNDI DataSource

您几乎不应该需要或想要使用此类,除非必须调用现有代码并传递一个标准的 JDBC DataSource 接口实现。在这种情况下,这段代码可能是可用的,但它参与了 Spring 管理的事务。您可以使用前面提到的更高级别抽象来编写新代码。