现在应该比较清楚的是:不同的事务管理器是如何创建的,以及它们如何被连接到相应的需要被同步到事务的资源上(例如,DataSourceTransactionManager
对应到JDBC DataSource
,
HibernateTransactionManager
对应到Hibernate的 SessionFactory
等)。可是,剩下的问题是,直接或间接地使用一种持久化API(JDBC、Hibernate、JDO等)的应用代码,如何确保通过相关的 PlatformTransactionManager
来恰当地获取并操作资源,来满足事务同步,这些操作包括:创建、复用、清理 和 触发(可能没有)。
首选的方法是使用Spring的高层持久化集成API。这种方式不会替换原始的API,而是在内部封装了资源创建、复用、清理、事务同步以及异常映射等功能,这样用户的数据访问代码就不必关心这些,而集中精力于自己的持久化逻辑。通常,对所有持久化API都采用这种 模板 方法,包括 JdbcTemplate
、HibernateTemplate
和JdoTemplate
类(这些在这份参考文档后面的章节中详细叙述)。
在较低层次上,有以下这些类:DataSourceUtils
(针对JDBC),SessionFactoryUtils
(针对Hibernate),PersistenceManagerFactoryUtils
(针对JDO)等等。当对应用代码来说,直接同原始持久化API特有的资源类型打交道是更好的选择时,这些类确保应用代码获取到正确的Spring框架所管理的bean,事务被正确同步,处理过程中的异常被映射到一致的API。
例如,在JDBC环境下,你不再使用传统的调用 DataSource
的 getConnection()
方法的方式,而是使用Spring的 org.springframework.jdbc.datasource.DataSourceUtils
,像这样:
Connection conn = DataSourceUtils.getConnection(dataSource);
如果已有一个事务及与之关联的connection存在,该实例将被返回。否则,该方法调用将触发起一个新的connection的创建动作,该connection(可选地)被同步到任何现有的事务,并可以在同一事务范围内被后续的调用复用。正如上面提到的,这个过程有一个额外的好处,就是任何 SQLException
将被包装为Spring框架的 CannotGetJdbcConnectionException
,该类是Spring框架的unchecked的DataAccessExceptions层次体系中的一员。这将给你比从 SQLException
中简单所得更多的信息,而且保证了跨数据库——甚至其他持久化技术——的移植性。
应该指出的是,这些类同样可以在没有Spring事务管理的环境中工作良好(事务同步能力是可选的),所以无论你是否使用Spring的事务管理,你都可以使用这些类。
当然,一旦你用过Spring的JDBC支持或Hibernate支持,你一般就不再会选择 DataSourceUtils
或是别的辅助类了,因为你会更乐意与Spring抽象一起工作,而不是直接使用相关的API。例如,如果你使用Spring的 JdbcTemplate
或 jdbc.object
包来简化使用JDBC,Spring会在幕后替你正确地获取连接,而你不需要写任何特殊代码。