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

高层级的同步方法

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

低层级的同步方法

诸如 DataSourceUtils(用于 JDBC)、EntityManagerFactoryUtils(用于 JPA)、SessionFactoryUtils(用于 Hibernate)等类存在于较低层次。当你想让应用程序代码直接处理本地持久化 API 的资源类型时,你可以使用这些类来确保获得正确的 Spring 框架管理的实例,事务(可选择)同步,以及在此过程中发生的异常被正确地映射到一致的 API。

例如,在 JDBC 的情况下,你可以使用 Spring 的 org.springframework.jdbc.datasource.DataSourceUtils类,而不是传统的 JDBC 方法,即调用 DataSource 上的 getConnection()方法,如下所示:

  1. Connection conn = DataSourceUtils.getConnection(dataSource);

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

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

当然,一旦你使用了 Spring 的 JDBC 支持、JPA 支持或 Hibernate 支持,一般来说,你最好不要使用 DataSourceUtils 或其他辅助类,因为你通过 Spring 的抽象工作要比直接使用相关的 API 更快乐。例如,如果你使用 Spring JdbcTemplate 或 jdbc.object 包来简化你对 JDBC 的使用,正确的连接检索会在幕后发生,你不需要编写任何特殊代码。

TransactionAwareDataSourceProxy

最底层的是 TransactionAwareDataSourceProxy 类。这是一个目标数据源的代理,它包装了目标数据源以增加对 Spring 管理的事务的认识。在这方面,它类似于由 Java EE 服务器提供的交易型 JNDI 数据源。

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