通过事务同步资源
如何创建不同的事务管理器,以及这些事务管理器如何与需要与事务同步的相关资源关联(例如DataSourceTransactionManager与JDBC DataSource的关联、HibernateTransactionManager与Hibernate SessionFactory的关联等),现在应该已经清晰明了。本节将描述应用程序代码(直接或间接地,通过使用如JDBC、Hibernate或JPA这样的持久化API)如何确保这些资源能够被正确创建、重用和清理。此外,本节还探讨了如何(可选地)通过相关的TransactionManager来触发事务同步。
高级同步方法
首选方法是使用Spring最高级别的基于模板的持久化集成API,或者使用具有事务感知功能的工厂Bean或代理来管理原生资源工厂。这些事务感知的解决方案内部会处理资源的创建和重用、资源清理、资源的可选事务同步以及异常映射。因此,用户的数据访问代码无需处理这些任务,而可以纯粹专注于非样板化的持久化逻辑。通常,你可以使用原生ORM API,或者通过使用JdbcTemplate来采用基于模板的方法进行JDBC访问。这些解决方案将在本参考文档的后续章节中详细说明。
低级同步方法
像DataSourceUtils(用于JDBC)、EntityManagerFactoryUtils(用于JPA)、SessionFactoryUtils(用于Hibernate)这样的类存在于更低的层级。当你希望应用程序代码直接处理原生持久化API的资源类型时,就会使用这些类来确保获取到由Spring Framework正确管理的实例,交易(可选地)能够被同步,并且在此过程中发生的异常能够被正确映射到一致的API上。
例如,在JDBC的情况下,你可以不采用传统的在DataSource上调用.getConnection()方法的方式,而是使用Spring的org.springframework.jdbc.datasource.DataSourceUtils类,如下所示:
Connection conn = DataSourceUtils.getConnection(dataSource);
如果现有的交易已经有一个已同步(链接)的连接,那么就会返回该连接实例。否则,方法调用会触发新连接的创建,这个新连接可以选择性地与任何现有交易进行同步,并可供在同一交易中后续重复使用。如前所述,任何 SQLException 都会被包装在 Spring Framework 的 CannotGetJdbcConnectionException 中,这是 Spring Framework 未检查的 DataAccessException 类型层次结构中的一个异常。这种方法能提供比直接从 SQLException 中获取的更多信息,并确保了跨数据库甚至不同持久化技术的可移植性。
这种方法也可以在不使用Spring事务管理的情况下工作(事务同步是可选的),因此无论你是否使用Spring进行事务管理,都可以使用它。
当然,一旦你使用了Spring的JDBC支持、JPA支持或Hibernate支持,通常你就不愿意再使用DataSourceUtils或其他辅助类了,因为通过Spring的抽象层进行操作要比直接使用相关API更加方便。例如,如果你使用Spring的JdbcTemplate或jdbc.object包来简化JDBC的使用,正确的连接获取过程会在幕后自动完成,你无需编写任何特殊代码。
TransactionAwareDataSourceProxy
在最底层存在TransactionAwareDataSourceProxy类。这是一个目标DataSource的代理,它包装了目标DataSource以增加对Spring管理的事务的感知。在这方面,它类似于Jakarta EE服务器提供的事务性JNDI DataSource。
你几乎永远不需要也不想使用这个类,除非必须调用现有的代码,并且需要传递一个标准的JDBC DataSource接口实现。在那种情况下,虽然这段代码可能仍然可以使用,但它可能会参与Spring管理的事务。你可以使用前面提到的更高级别的抽象来编写新的代码。