Synchronizing Resources with Transactions
如何创建不同的事务管理器以及它们如何链接到需要与事务同步的相关资源(例如 DataSourceTransactionManager
到 JDBC DataSource
,HibernateTransactionManager
到 Hibernate SessionFactory
,等等)现在应该很清楚了。本小节描述了应用程序代码(直接或间接地,通过使用诸如 JDBC、Hibernate 或 JPA 之类的持久化 API)如何确保这些资源被正确创建、重用和清理。本小节还讨论了如何通过相关的 TransactionManager
(可选地)触发事务同步。
How to create different transaction managers and how they are linked to related resources
that need to be synchronized to transactions (for example DataSourceTransactionManager
to a JDBC DataSource
, HibernateTransactionManager
to a Hibernate SessionFactory
,
and so forth) should now be clear. This section describes how the application code
(directly or indirectly, by using a persistence API such as JDBC, Hibernate, or JPA)
ensures that these resources are created, reused, and cleaned up properly. The section
also discusses how transaction synchronization is (optionally) triggered through the
relevant TransactionManager
.
High-level Synchronization Approach
首选方法是使用 Spring 的最高级别基于模板的持久化集成 API 或将本机 ORM API 与事务感知的工厂 bean 或代理一起使用以管理本机资源工厂。这些事务感知的解决方案在内部处理资源创建和重用、清理、资源的可选事务同步和异常映射。因此,用户数据访问代码不必处理这些任务,而可以完全专注于非样板化持久化逻辑。通常,您使用本机 ORM API 或采用模板的 JDBC 访问方法,即使用 JdbcTemplate
。这些解决方案在本参考文档的后续部分中进行了详细说明。
The preferred approach is to use Spring’s highest-level template-based persistence
integration APIs or to use native ORM APIs with transaction-aware factory beans or
proxies for managing the native resource factories. These transaction-aware solutions
internally handle resource creation and reuse, cleanup, optional transaction
synchronization of the resources, and exception mapping. Thus, user data access code does
not have to address these tasks but can focus purely on non-boilerplate
persistence logic. Generally, you use the native ORM API or take a template approach
for JDBC access by using the JdbcTemplate
. These solutions are detailed in subsequent
sections of this reference documentation.
Low-level Synchronization Approach
DataSourceUtils
(用于 JDBC)、EntityManagerFactoryUtils
(用于 JPA)、SessionFactoryUtils
(用于 Hibernate)等类存在于较低层次。当您希望应用程序代码直接处理本机持久化 API 的资源类型时,可以使用这些类来确保获取适当的 Spring 框架管理的实例,(可选地)同步事务,并在过程中发生的异常被正确地映射到一个一致的 API。
Classes such as DataSourceUtils
(for JDBC), EntityManagerFactoryUtils
(for JPA),
SessionFactoryUtils
(for Hibernate), and so on exist at a lower level. When you want the
application code to deal directly with the resource types of the native persistence APIs,
you use these classes to ensure that proper Spring Framework-managed instances are obtained,
transactions are (optionally) synchronized, and exceptions that occur in the process are
properly mapped to a consistent API.
例如,在 JDBC 的情况下,您可以使用 Spring 的 org.springframework.jdbc.datasource.DataSourceUtils
类替代调用 DataSource
上的 getConnection()
方法的传统 JDBC 方法,如下所示:
For example, in the case of JDBC, instead of the traditional JDBC approach of calling
the getConnection()
method on the DataSource
, you can instead use Spring’s
org.springframework.jdbc.datasource.DataSourceUtils
class, as follows:
Connection conn = DataSourceUtils.getConnection(dataSource);
如果一个现有的事务已经有一个与其同步(链接)的连接,那么会返回该实例。否则,该方法调用会触发创建一个新连接,该连接会(可选地)同步到任何现有的事务中并在同一事务中可用以供后续重用。如前所述,任何 SQLException
都被封装在一个 Spring 框架的 CannotGetJdbcConnectionException
中,CannotGetJdbcConnectionException
是 Spring 框架的一系列未签入的 DataAccessException
类型中的一个。这种方法为您提供了比从 SQLException
中轻松获取到的更多的信息,并确保跨数据库甚至跨不同的持久化技术实现可移植性。
If an existing transaction already has a connection synchronized (linked) to it, that
instance is returned. Otherwise, the method call triggers the creation of a new
connection, which is (optionally) synchronized to any existing transaction and made
available for subsequent reuse in that same transaction. As mentioned earlier, any
SQLException
is wrapped in a Spring Framework CannotGetJdbcConnectionException
, one
of the Spring Framework’s hierarchy of unchecked DataAccessException
types. This approach
gives you more information than can be obtained easily from the SQLException
and
ensures portability across databases and even across different persistence technologies.
这种方法在没有 Spring 事务管理的情况下也能工作(事务同步是可选的),因此无论您是否将 Spring 用于事务管理,您都可以使用它。
This approach also works without Spring transaction management (transaction synchronization is optional), so you can use it whether or not you use Spring for transaction management.
当然,一旦您使用过 Spring 的 JDBC 支持、JPA 支持或 Hibernate 支持,您通常会倾向于不使用 DataSourceUtils
或其他帮助类,因为与直接使用相关的 API 相比,您更愿意通过 Spring 抽象来工作。例如,如果您使用 Spring JdbcTemplate
或 jdbc.object
包来简化对 JDBC 的使用,那么正确的连接检索将发生在场景的幕后,而您不需要编写任何特殊代码。
Of course, once you have used Spring’s JDBC support, JPA support, or Hibernate support,
you generally prefer not to use DataSourceUtils
or the other helper classes,
because you are much happier working through the Spring abstraction than directly
with the relevant APIs. For example, if you use the Spring JdbcTemplate
or
jdbc.object
package to simplify your use of JDBC, correct connection retrieval occurs
behind the scenes and you need not write any special code.
TransactionAwareDataSourceProxy
在最低层,存在 TransactionAwareDataSourceProxy
类。这是一个目标 DataSource
的代理,它封装了目标 DataSource
以增加对 Spring 管理的事务的感知。在这方面,它类似于事务性 JNDI DataSource
,由 Jakarta EE 服务器提供。
At the very lowest level exists the TransactionAwareDataSourceProxy
class. This is a
proxy for a target DataSource
, which wraps the target DataSource
to add awareness of
Spring-managed transactions. In this respect, it is similar to a transactional JNDI
DataSource
, as provided by a Jakarta EE server.
除了当必须调用现有的代码并传递了标准 JDBC DataSource
接口实现时,您几乎永远不需要或不想使用这个类。在这种情况下,这代码可能可用,但参与了 Spring 管理的事务。您可以使用前面提到的更高层次的抽象来编写新代码。
You should almost never need or want to use this class, except when existing
code must be called and passed a standard JDBC DataSource
interface implementation. In
that case, it is possible that this code is usable but is participating in Spring-managed
transactions. You can write your new code by using the higher-level
abstractions mentioned earlier.