Comprehensive transaction support is among the most compelling reasons to use the Spring Framework. The Spring Framework
provides a consistent abstraction for transaction management that delivers the following benefits:
全面的事务支持是使用 Spring 框架的最有说服力的理由之一。Spring 框架为事务管理提供了一致的抽象,从而带来以下好处:
A consistent programming model across different transaction APIs, such as Java Transaction API (JTA), JDBC, Hibernate,
and the Java Persistence API (JPA).
跨不同事务 API 的一致编程模型,例如 Java 事务 API(JTA)、JDBC、Hibernate 和 Java 持久化 API(JPA)。
Support for declarative transaction management.
支持声明式事务管理。
A simpler API for programmatic transaction management than complex transaction APIs, such
as JTA.
一个比复杂的交易 API(如 JTA)更简单的程序化事务管理 API。
Excellent integration with Spring’s data access abstractions.
与 Spring 数据访问抽象的出色集成。
The following sections describe the Spring Framework’s transaction features and technologies:
以下章节描述了 Spring 框架的事务特性和技术:
Advantages of the Spring Framework’s transaction support model describes why you would use
the Spring Framework’s transaction abstraction instead of EJB Container-Managed Transactions (CMT) or choosing to
drive local transactions through a proprietary API, such as Hibernate.
Spring 框架事务支持模型的优势描述了为什么你会选择使用 Spring 框架的事务抽象而不是 EJB 容器管理事务(CMT)或选择通过专有
API(如 Hibernate)驱动本地事务。
Understanding the Spring Framework transaction abstraction outlines the core classes and
describes how to configure and obtain DataSource instances from a variety of sources.
理解 Spring 框架的事务抽象概述了核心类,并描述了如何从各种来源配置和获取 DataSource 实例。
Synchronizing resources with transactions describes how the application code ensures
that resources are created, reused, and cleaned up properly.
同步事务中的资源描述了应用程序代码如何确保资源被正确创建、重用和清理。
Declarative transaction management describes support for declarative transaction
management.
声明式事务管理描述了对声明式事务管理的支持。
Programmatic transaction management covers support for programmatic (that is, explicitly
coded) transaction management.
程序化事务管理涵盖了支持程序化(即明确编码的)事务管理。
Transaction bound event describes how you could use application events within a transaction.
事务边界事件描述了您如何在事务中使用应用程序事件。
The chapter also includes discussions of best
practices, application server integration,
and solutions to common problems.
该章节还包括最佳实践、应用服务器集成和常见问题解决方案的讨论。
1.1. Spring 框架事务支持模型的优势
Traditionally, Java EE developers have had two choices for transaction management: global or local transactions, both of
which have profound limitations.
传统上,Java EE 开发者在事务管理方面有两个选择:全局事务或本地事务,这两种方式都有深刻的局限性。
Global and local transaction management is reviewed in the next two sections, followed by a discussion of how the Spring
Framework’s transaction management support addresses the limitations of the global and local transaction models.
全局和本地事务管理将在下一两节中进行回顾,随后将讨论 Spring 框架的事务管理支持如何解决全局和本地事务模型的局限性。
1.1.1. 全球交易
Global transactions let you work with multiple transactional resources, typically relational databases and message
queues. The application server manages global transactions through the JTA, which is a cumbersome API (partly due to its
exception model). Furthermore, a JTA UserTransaction normally needs to be sourced from JNDI, meaning that you also
need to use JNDI in order to use JTA. The use of global transactions limits any potential reuse of application code, as
JTA is normally only available in an application server environment.
全局事务让您可以与多个事务性资源一起工作,通常是关系数据库和消息队列。应用程序服务器通过 JTA 管理全局事务,JTA 是一个繁琐的
API(部分原因是其异常模型)。此外,JTA 通常需要从 JNDI 中获取,这意味着您也需要使用 JNDI 才能使用
JTA。全局事务的使用限制了应用程序代码的潜在重用,因为 JTA 通常仅在应用程序服务器环境中可用。
Previously, the preferred way to use global transactions was through EJB CMT (Container Managed Transaction). CMT is a
form of declarative transaction management (as distinguished from programmatic transaction management).
以前,使用全局事务的首选方式是通过 EJB CMT(容器管理事务)。CMT 是一种声明式事务管理形式(与程序式事务管理区分开来)。
EJB CMT removes the need for transaction-related JNDI lookups, although the use of EJB itself necessitates the use of
JNDI. It removes most but not all of the need to write Java code to control transactions.
EJB CMT 消除了对事务相关 JNDI 查找的需求,尽管使用 EJB 本身需要使用 JNDI。它消除了编写 Java
代码来控制事务的大部分需求,但并非全部。
The significant downside is that CMT is tied to JTA and an application server environment. Also, it is only available if
one chooses to implement business logic in EJBs (or at least behind a transactional EJB facade).
显著的缺点是 CMT 与 JTA 和应用程序服务器环境相关联。此外,只有当选择在 EJB(或至少在事务 EJB
外观之后)中实现业务逻辑时,它才可用。
The negatives of EJB in general are so great that this is not an attractive proposition, especially in the face of
compelling alternatives for declarative transaction management.
EJB 的缺点普遍如此之大,以至于这并不是一个有吸引力的提议,尤其是在面对声明式事务管理的有力替代方案时。
1.1.2. 本地事务
Local transactions are resource-specific, such as a transaction associated with a JDBC connection. Local transactions
may be easier to use but have a significant disadvantage: They cannot work across multiple transactional resources.
本地事务是资源特定的,例如与 JDBC
连接关联的事务。本地事务可能更容易使用,但有一个显著的缺点:它们无法在多个事务资源之间工作。
For example, code that manages transactions by using a JDBC connection cannot run within a global JTA transaction.
Because the application server is not involved in transaction management, it cannot help ensure correctness across
multiple resources.
例如,使用 JDBC 连接管理事务的代码不能在全局 JTA
事务中运行。因为应用程序服务器不参与事务管理,所以它无法帮助确保跨多个资源的正确性。
(It is worth noting that most applications use a single transaction resource.) Another downside is that local
transactions are invasive to the programming model.
(值得注意的是,大多数应用程序都使用单个事务资源。)另一个缺点是本地事务对编程模型具有侵入性。
1.1.3. Spring 框架的一致编程模型
Spring resolves the disadvantages of global and local transactions. It lets application developers use a consistent
programming model in any environment. You write your code once, and it can benefit from different transaction management
strategies in different environments.
Spring
解决了全局和本地事务的缺点。它允许应用程序开发者在任何环境中使用一致的编程模型。你只需编写一次代码,它就可以从不同环境中的不同事务管理策略中受益。
The Spring Framework provides both declarative and programmatic transaction management. Most users prefer declarative
transaction management, which we recommend in most cases.
Spring 框架提供声明式和编程式事务管理。大多数用户更喜欢声明式事务管理,我们通常推荐使用这种方式。
With programmatic transaction management, developers work with the Spring Framework transaction abstraction, which can
run over any underlying transaction infrastructure.
使用程序化事务管理,开发人员与 Spring 框架的事务抽象层一起工作,该抽象层可以在任何底层事务基础设施上运行。
With the preferred declarative model, developers typically write little or no code related to transaction management
and, hence, do not depend on the Spring Framework transaction API or any other transaction API.
使用首选的声明性模型,开发者通常编写很少或没有与事务管理相关的代码,因此不依赖于 Spring 框架的事务 API 或任何其他事务 API。
1.2. 理解 Spring 框架的事务抽象
The key to the Spring transaction abstraction is the notion of a transaction strategy. A transaction strategy is defined
by a TransactionManager, specifically the org.springframework.transaction.PlatformTransactionManager interface for
imperative transaction management and the org.springframework.transaction.ReactiveTransactionManager interface for
reactive transaction management. The following listing shows the definition of the PlatformTransactionManager API:
Spring 事务抽象的关键是事务策略的概念。事务策略由一个 TransactionManager 定义,具体是用于命令式事务管理的
org.springframework.transaction.PlatformTransactionManager 接口和用于响应式事务管理的
org.springframework.transaction.ReactiveTransactionManager 接口。以下列表显示了 PlatformTransactionManager API 的定义:
This is primarily a service provider interface (SPI), although you can use
it programmatically from your application code. Because PlatformTransactionManager is
an interface, it can be easily mocked or stubbed as necessary. It is not tied to a lookup strategy, such as JNDI.
PlatformTransactionManager implementations are defined like any other object (or bean) in the Spring Framework IoC
container. This benefit alone makes Spring Framework transactions a worthwhile abstraction, even when you work with
JTA.
这是一个主要的服务提供者接口(SPI),尽管您也可以从应用程序代码中以编程方式使用它。因为 PlatformTransactionManager
是一个接口,所以可以根据需要轻松地进行模拟或存根。它不依赖于查找策略,如 JNDI。 PlatformTransactionManager 的实现方式与
Spring Framework IoC 容器中的任何其他对象(或 bean)相同。仅此一项优势就使得 Spring Framework 事务成为一个值得拥有的抽象,即使您在使用
JTA 时也是如此。
You can test transactional code much more easily than if it used JTA directly.
您测试事务代码比直接使用 JTA 要容易得多。
Again, in keeping with Spring’s philosophy, the TransactionException that can be thrown by any of the
PlatformTransactionManager interface’s methods is unchecked (that is, it extends the java.lang.RuntimeException
class). Transaction infrastructure failures are almost invariably fatal. In rare cases where application code can
actually recover from a transaction failure, the application developer can still choose to catch and handle
TransactionException. The salient point is that developers are not forced to do so.
再次,遵循 Spring 的哲学,任何 TransactionException 接口的方法可以抛出的异常都是未检查的(即,它扩展了
java.lang.RuntimeException 类)。事务基础设施故障几乎总是致命的。在极少数情况下,应用程序代码实际上可以从事务故障中恢复,应用程序开发者仍然可以选择捕获和处理
TransactionException 。关键点是开发者并非被迫这样做。
The getTransaction(..) method returns a TransactionStatus object, depending on a TransactionDefinition parameter.
The returned TransactionStatus might represent a new transaction or can represent an existing transaction, if a
matching transaction exists in the current call stack. The implication in this latter case is that, as with Java EE
transaction contexts, a TransactionStatus is associated with a thread of execution.
该方法返回一个 TransactionStatus 对象,取决于一个 TransactionDefinition 参数。返回的 TransactionStatus
可能代表一个新事务,也可能代表一个现有事务,如果当前调用栈中存在匹配的事务。在后一种情况下,这意味着,与 Java EE 事务上下文一样,一个
TransactionStatus 与一个执行线程相关联。
As of Spring Framework 5.2, Spring also provides a transaction management abstraction for reactive applications that
make use of reactive types or Kotlin Coroutines. The following listing shows the transaction strategy defined by
org.springframework.transaction.ReactiveTransactionManager:
截至 Spring Framework 5.2,Spring 还为使用响应式类型或 Kotlin Coroutines 的响应式应用程序提供了事务管理抽象。以下列表显示了由
org.springframework.transaction.ReactiveTransactionManager 定义的事务策略。
The reactive transaction manager is primarily a service provider interface (SPI), although you can use
it programmatically from your application code. Because ReactiveTransactionManager is
an interface, it can be easily mocked or stubbed as necessary.
反应式事务管理器主要是服务提供者接口(SPI),尽管您也可以从您的应用程序代码中以编程方式使用它。因为
ReactiveTransactionManager 是一个接口,所以可以根据需要轻松地进行模拟或存根。
The TransactionDefinition interface specifies:
The TransactionDefinition interface specifies: TransactionDefinition 接口指定:
Propagation: Typically, all code within a transaction scope runs in that transaction. However, you can specify the
behavior if a transactional method is run when a transaction context already exists.
传播:通常,事务作用域内的所有代码都在该事务中运行。然而,如果您在已存在事务上下文的情况下运行事务方法,可以指定其行为。
For example, code can continue running in the existing transaction (the common case), or the existing transaction can
be suspended and a new transaction created. Spring offers all of the transaction propagation options familiar from EJB
CMT.
例如,代码可以在现有事务中继续运行(常见情况),或者现有事务可以暂停并创建一个新事务。Spring 提供了从 EJB CMT
熟悉的全部事务传播选项。
To read about the semantics of transaction propagation in Spring, see Transaction Propagation.
关于 Spring 中事务传播的语义,请参阅事务传播。
Isolation: The degree to which this transaction is isolated from the work of other transactions. For example, can this
transaction see uncommitted writes from other transactions?
隔离:此事务与其他事务工作隔离的程度。例如,此事务能否看到其他事务的未提交写操作?
Timeout: How long this transaction runs before timing out and being automatically rolled back by the underlying
transaction infrastructure.
超时:此事务在超时前运行的时间,以及在此期间由底层事务基础设施自动回滚。
Read-only status: You can use a read-only transaction when your code reads but does not modify data. Read-only
transactions can be a useful optimization in some cases, such as when you use Hibernate.
只读状态:当您的代码读取但不修改数据时,您可以使用只读事务。在某些情况下,如使用 Hibernate 时,只读事务可以是一种有用的优化。
These settings reflect standard transactional concepts. If necessary, refer to resources that discuss transaction
isolation levels and other core transaction concepts. Understanding these concepts is essential to using the Spring
Framework or any transaction management solution.
这些设置反映了标准事务概念。如有必要,请参考讨论事务隔离级别和其他核心事务概念的资源。理解这些概念对于使用 Spring
框架或任何事务管理解决方案至关重要。
The TransactionStatus interface provides a simple way for transactional code to control transaction execution and
query transaction status. The concepts should be familiar, as they are common to all transaction APIs. The following
listing shows the TransactionStatus interface:
TransactionStatus 接口为事务代码提供了控制事务执行和查询事务状态的简单方法。这些概念应该是熟悉的,因为它们对所有事务 API
都是通用的。以下列表显示了 TransactionStatus 接口:
Regardless of whether you opt for declarative or programmatic transaction management in Spring, defining the correct
TransactionManager implementation is absolutely essential. You typically define this implementation through dependency
injection.
无论您在 Spring 中选择声明式还是程序式事务管理,定义正确的 TransactionManager 实现绝对至关重要。您通常通过依赖注入来定义此实现。
TransactionManager implementations normally require knowledge of the environment in which they work: JDBC, JTA,
Hibernate, and so on. The following examples show how you can define a local PlatformTransactionManager
implementation (in this case, with plain JDBC.)
TransactionManager 实现通常需要了解它们所在的环境:JDBC、JTA、Hibernate 等。以下示例展示了如何定义一个本地
PlatformTransactionManager 实现(在这种情况下,使用纯 JDBC)。
You can define a JDBC DataSource by creating a bean similar to the following:
您可以通过创建一个类似于以下示例的 bean 来定义一个 JDBC DataSource :
The related PlatformTransactionManager bean definition then has a reference to the DataSource definition. It should
resemble the following example:
相关 PlatformTransactionManager 豆定义随后引用了 DataSource 定义。它应该类似于以下示例:
If you use JTA in a Java EE container, then you use a container DataSource, obtained through JNDI, in conjunction with
Spring’s JtaTransactionManager. The following example shows what the JTA and JNDI lookup version would look like:
如果您在 Java EE 容器中使用 JTA,那么您将使用通过 JNDI 获得的容器 DataSource ,与 Spring 的 JtaTransactionManager
一起使用。以下示例显示了 JTA 和 JNDI 查找版本的示例:
The JtaTransactionManager does not need to know about the DataSource (or any other specific resources) because it
uses the container’s global transaction management infrastructure.
JtaTransactionManager 不需要了解 DataSource (或任何其他特定资源),因为它使用容器全局事务管理基础设施。
The preceding definition of the dataSource bean uses the <jndi-lookup/> tag from the jee namespace. For more
information
see The JEE Schema.
前一个对 dataSource bean 的定义使用了 jee 命名空间中的 <jndi-lookup/> 标签。更多信息请参阅 JEE Schema。
If you use JTA, your transaction manager definition should look the same, regardless of what data access technology you
use, be it JDBC, Hibernate JPA, or any other supported technology.
如果您使用 JTA,无论您使用的是 JDBC、Hibernate JPA 还是任何其他受支持的技术,您的交易管理器定义都应该相同。
This is due to the fact that JTA transactions are global transactions, which can enlist any transactional resource.
这是由于 JTA 事务是全局事务,可以注册任何事务性资源。
In all Spring transaction setups, application code does not need to change. You can change how transactions are managed
merely by changing configuration, even if that change means moving from local to global transactions or vice versa.
在所有 Spring 事务设置中,应用代码无需更改。您只需通过更改配置即可更改事务管理方式,即使这意味着从本地事务切换到全局事务或反之亦然。
1.2.1. Hibernate 事务设置
You can also easily use Hibernate local transactions, as shown in the following examples. In this case, you need to
define a Hibernate LocalSessionFactoryBean, which your application code can use to obtain Hibernate Session
instances.
您也可以轻松使用 Hibernate 本地事务,如下例所示。在这种情况下,您需要定义一个 Hibernate LocalSessionFactoryBean
,您的应用程序代码可以使用它来获取 Hibernate Session 实例。
The DataSource bean definition is similar to the local JDBC example shown previously and, thus, is not shown in the
following example.
The DataSource bean definition is similar to the local JDBC example shown previously and, thus, is not shown in the
following example. DataSource的 bean 定义与之前展示的本地 JDBC 示例类似,因此以下示例中没有展示。
If the DataSource (used by any non-JTA transaction manager) is looked up through JNDI and managed by a Java EE
container, it should be non-transactional, because the Spring Framework (rather than the Java EE container) manages the
transactions.
如果通过 JNDI 查找并由 Java EE 容器管理的 DataSource (由任何非 JTA 事务管理器使用)应该是非事务性的,因为 Spring 框架(而不是
Java EE 容器)管理事务。
The txManager bean in this case is of the HibernateTransactionManager type. In the same way as the
DataSourceTransactionManager needs a reference to the DataSource, the HibernateTransactionManager needs a
reference to the SessionFactory. The following example declares sessionFactory and txManager beans:
在这种情况下, txManager 豆是 HibernateTransactionManager 类型的。与 DataSourceTransactionManager 需要引用
DataSource 一样, HibernateTransactionManager 需要引用 SessionFactory 。以下示例声明了 sessionFactory 和
txManager 豆:
If you use Hibernate and Java EE container-managed JTA transactions, you should use the same JtaTransactionManager as
in the previous JTA example for JDBC, as the following example shows. Also, it is recommended to make Hibernate aware of
JTA through its transaction coordinator and possibly also its connection release mode configuration:
如果您使用 Hibernate 和 Java EE 容器管理的 JTA 事务,您应该使用与上一个 JTA 示例中相同的 JtaTransactionManager
,如下例所示。此外,建议通过其事务协调器和可能的连接释放模式配置让 Hibernate 了解 JTA:
Or alternatively, you may pass the JtaTransactionManager into your LocalSessionFactoryBean for enforcing the same
defaults:
或者,您可以将 JtaTransactionManager 传递到您的 LocalSessionFactoryBean 中,以强制执行相同的默认值:
1.3. 使用事务同步资源
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.
如何创建不同的事务管理器以及它们如何与需要同步到事务中的相关资源(例如 DataSourceTransactionManager 到 JDBC
DataSource , HibernateTransactionManager 到 Hibernate SessionFactory ,等等)相连接现在应该很清楚。本节描述了应用程序代码(直接或间接地,通过使用持久化
API 如 JDBC、Hibernate 或 JPA)如何确保这些资源被正确创建、重用和清理。
The section also discusses how transaction synchronization is (optionally) triggered through the relevant
TransactionManager.
该部分还讨论了如何通过相关 TransactionManager (可选地)触发事务同步。
1.3.1. 高级同步方法
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.
首选方法是使用 Spring 最高级别的基于模板的持久性集成 API,或者使用具有事务感知的工厂 bean 或代理的本地 ORM API
来管理本地资源工厂。
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.
因此,用户数据访问代码不必处理这些任务,而可以专注于纯非样板持久化逻辑。通常,您使用原生 ORM API 或采用模板方法通过使用
JdbcTemplate 进行 JDBC 访问。这些解决方案在后续章节的参考文档中有详细说明。
1.3.2. 低级同步方法
Classes such as DataSourceUtils (for JDBC), EntityManagerFactoryUtils (for JPA), SessionFactoryUtils (for
Hibernate), and so on exist at a lower level.
类如 DataSourceUtils (用于 JDBC)、 EntityManagerFactoryUtils (用于 JPA)、 SessionFactoryUtils (用于
Hibernate)等存在于较低级别。
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.
当你希望应用程序代码直接处理原生持久化 API 的资源类型时,您使用这些类来确保获取适当的 Spring
框架管理的实例,事务(可选)同步,并将过程中发生的异常正确映射到一致的 API。
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:
例如,在 JDBC 的情况下,您可以使用 Spring 的 org.springframework.jdbc.datasource.DataSourceUtils 类,而不是传统的在
DataSource 上调用 getConnection() 方法的方法,如下所示:
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.
否则,方法调用将触发创建一个新的连接,该连接(可选地)与任何现有事务同步,并在同一事务中可供后续重用。如前所述,任何
SQLException 都被 Spring 框架的 CannotGetJdbcConnectionException 包装,这是 Spring 框架的未检查 DataAccessException
类型层次结构之一。这种方法提供了比从 SQLException 更容易获得的信息,并确保了跨数据库甚至跨不同持久化技术的可移植性。
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 事务管理(事务同步是可选的),因此无论是否使用 Spring 进行事务管理,您都可以使用它。
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.
当然,一旦您使用了 Spring 的 JDBC 支持、JPA 支持或 Hibernate 支持,您通常更愿意不使用 DataSourceUtils 或其他辅助类,因为您更乐意通过
Spring 抽象层工作,而不是直接与相关 API 交互。例如,如果您使用 Spring JdbcTemplate 或 jdbc.object 包来简化 JDBC
的使用,正确的连接检索会在幕后自动完成,您无需编写任何特殊代码。
TransactionAwareDataSourceProxyAt 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 Java EE server.
在最底层存在 TransactionAwareDataSourceProxy 类。这是一个针对目标 DataSource 的代理,它封装目标 DataSource 以增加对
Spring 管理的交易的认识。在这方面,它与 Java EE 服务器提供的事务性 JNDI DataSource 类似。
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.
您几乎永远不需要或想要使用这个类,除非现有代码必须调用并传递一个标准的 JDBC DataSource 接口实现。在这种情况下,这段代码可能是可用的,但它参与了
Spring 管理的事务。您可以通过使用前面提到的更高级抽象来编写您的新代码。
1.4. 声明式事务管理
Most Spring Framework users choose declarative transaction management. This option has the least impact on application
code and, hence, is most consistent with the ideals of a non-invasive lightweight container.
大多数 Spring 框架用户选择声明式事务管理。此选项对应用程序代码的影响最小,因此最符合非侵入式轻量级容器的理念。
The Spring Framework’s declarative transaction management is made possible with Spring aspect-oriented programming (
AOP).
Spring 框架的声明式事务管理是通过 Spring 面向切面编程(AOP)实现的。
However, as the transactional aspects code comes with the Spring Framework distribution and may be used in a boilerplate
fashion, AOP concepts do not generally have to be understood to make effective use of this code.
然而,由于事务方面代码包含在 Spring 框架发行版中,并且可能以模板方式使用,因此通常不需要理解 AOP 概念就能有效地使用此代码。
The Spring Framework’s declarative transaction management is similar to EJB CMT, in that you can specify transaction
behavior (or lack of it) down to the individual method level. You can make a setRollbackOnly() call within a
transaction context, if necessary. The differences between the two types of transaction management are:
Spring 框架的声明式事务管理类似于 EJB CMT,因为您可以将事务行为(或没有行为)指定到单个方法级别。如果需要,您可以在事务上下文中进行
setRollbackOnly() 调用。这两种类型的事务管理之间的区别是:
Unlike EJB CMT, which is tied to JTA, the Spring Framework’s declarative transaction management works in any
environment. It can work with JTA transactions or local transactions by using JDBC, JPA, or Hibernate by adjusting the
configuration files.
与 EJB CMT 不同,它与 JTA 绑定,Spring 框架的声明式事务管理在任何环境中都可以工作。它可以通过调整配置文件,使用 JDBC、JPA 或
Hibernate 与 JTA 事务或本地事务一起工作。
You can apply the Spring Framework declarative transaction management to any class, not merely special classes such as
EJBs.
您可以将 Spring 框架的声明式事务管理应用于任何类,而不仅仅是像 EJBs 这样的特殊类。
The Spring Framework offers declarative rollback rules, a feature with no EJB
equivalent. Both programmatic and declarative support for rollback rules is provided.
Spring 框架提供声明式回滚规则,这是一个没有 EJB 等价物的功能。提供了对回滚规则的程序性和声明性支持。
The Spring Framework lets you customize transactional behavior by using AOP. For example, you can insert custom
behavior in the case of transaction rollback. You can also add arbitrary advice, along with transactional advice.
Spring 框架允许您通过使用 AOP
来自定义事务行为。例如,您可以在事务回滚的情况下插入自定义行为。您还可以添加任意建议,包括事务建议。
With EJB CMT, you cannot influence the container’s transaction management, except with setRollbackOnly().
使用 EJB CMT,您无法影响容器的交易管理,除非使用 setRollbackOnly() 。
The Spring Framework does not support propagation of transaction contexts across remote calls, as high-end application
servers do. If you need this feature, we recommend that you use EJB.
Spring 框架不支持跨远程调用传播事务上下文,就像高端应用服务器所做的那样。如果您需要此功能,我们建议您使用 EJB。
However, consider carefully before using such a feature, because, normally, one does not want transactions to span
remote calls.
然而,在使用此功能之前请仔细考虑,因为通常情况下,人们不希望事务跨越远程调用。
The concept of rollback rules is important. They let you specify which exceptions (and throwables) should cause
automatic rollback. You can specify this declaratively, in configuration, not in Java code. So, although you can still
call setRollbackOnly() on the TransactionStatus object to roll back the current transaction back, most often you can
specify a rule that MyApplicationException must always result in rollback. The significant advantage to this option is
that business objects do not depend on the transaction infrastructure. For example, they typically do not need to import
Spring transaction APIs or other Spring APIs.
回滚规则的概念很重要。它们允许您指定哪些异常(和可抛出对象)应导致自动回滚。您可以在配置中声明性地指定此内容,而不是在 Java
代码中。因此,尽管您仍然可以在 TransactionStatus 对象上调用 setRollbackOnly() 来回滚当前事务,但大多数情况下,您可以指定一个规则,使得
MyApplicationException 必须始终导致回滚。这个选项的显著优势是业务对象不依赖于事务基础设施。例如,它们通常不需要导入
Spring 事务 API 或其他 Spring API。
Although EJB container default behavior automatically rolls back the transaction on a system exception (usually a
runtime exception), EJB CMT does not roll back the transaction automatically on an application exception (that is, a
checked exception other than java.rmi.RemoteException). While the Spring default behavior for declarative transaction
management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize
this behavior.
尽管 EJB 容器默认行为会在系统异常(通常是运行时异常)发生时自动回滚事务,但 EJB CMT 不会在应用程序异常(即除了
java.rmi.RemoteException 之外的检查异常)发生时自动回滚事务。虽然 Spring 对声明式事务管理的默认行为遵循 EJB
约定(仅在未检查的异常上自动回滚),但通常很有必要自定义此行为。
1.4.1. 理解 Spring 框架的声明式事务实现
It is not sufficient merely to tell you to annotate your classes with the @Transactional annotation, add
@EnableTransactionManagement to your configuration, and expect you to understand how it all works. To provide a deeper
understanding, this section explains the inner workings of the Spring Framework’s declarative transaction infrastructure
in the context of transaction-related issues.
仅仅告诉您使用 @Transactional 注解标注您的类,添加 @EnableTransactionManagement
到您的配置中,并期望您理解这一切是如何工作的,这是不够的。为了提供更深入的理解,本节解释了在事务相关问题的背景下,Spring
框架声明式事务基础设施的内部工作原理。
The most important concepts to grasp with regard to the Spring Framework’s declarative transaction support are that this
support is
enabled via AOP proxies
and that the transactional advice is driven by metadata (currently XML- or annotation-based). The combination of AOP
with transactional metadata yields an AOP proxy that uses a TransactionInterceptor in conjunction with an appropriate
TransactionManager implementation to drive transactions around method invocations.
Spring 框架声明式事务支持最重要的概念是,这种支持通过 AOP 代理启用,事务建议由元数据(目前基于 XML 或注解)驱动。AOP
与事务元数据的结合产生了一个 AOP 代理,该代理使用 TransactionInterceptor 与适当的 TransactionManager 实现一起驱动方法调用的事务。
Spring Framework’s TransactionInterceptor provides transaction management for imperative and reactive programming
models. The interceptor detects the desired flavor of transaction management by inspecting the method return type.
Methods returning a reactive type such as Publisher or Kotlin Flow (or a subtype of those) qualify for reactive
transaction management. All other return types including void use the code path for imperative transaction
management.
Spring 框架的 TransactionInterceptor 为命令式和响应式编程模型提供事务管理。拦截器通过检查方法返回类型来检测所需的事务管理风格。返回响应式类型(如
Publisher 或 Kotlin Flow (或这些类型的子类型))的方法符合响应式事务管理。所有其他返回类型(包括 void )使用命令式事务管理的代码路径。
Transaction management flavors impact which transaction manager is required. Imperative transactions require a
PlatformTransactionManager, while reactive transactions use ReactiveTransactionManager implementations.
事务管理风格影响所需的交易管理器。命令式事务需要 PlatformTransactionManager ,而响应式事务使用
ReactiveTransactionManager 实现。
@Transactional commonly works with thread-bound transactions managed by PlatformTransactionManager, exposing a
transaction to all data access operations within the current execution thread. Note: This does not propagate to newly
started threads within the method.
@Transactional 通常与由 PlatformTransactionManager 管理的线程绑定事务一起工作,将事务暴露给当前执行线程内的所有数据访问操作。注意:此操作不会传播到方法内新启动的线程。
A reactive transaction managed by ReactiveTransactionManager uses the Reactor context instead of thread-local
attributes. As a consequence, all participating data access operations need to execute within the same Reactor context
in the same reactive pipeline.
由 ReactiveTransactionManager 管理的反应式事务使用 Reactor 上下文而不是线程局部属性。因此,所有参与的数据访问操作必须在同一反应管道中的同一
Reactor 上下文中执行。
The following image shows a conceptual view of calling a method on a transactional proxy:
以下图像展示了在事务代理上调用方法的概念视图:

1.4.2. 声明式事务实现示例
Consider the following interface and its attendant implementation. This example uses Foo and Bar classes as
placeholders so that you can concentrate on the transaction usage without focusing on a particular domain model. For the
purposes of this example, the fact that the DefaultFooService class throws UnsupportedOperationException instances
in the body of each implemented method is good. That behavior lets you see transactions being created and then rolled
back in response to the UnsupportedOperationException instance. The following listing shows the FooService
interface:
考虑以下接口及其相关实现。此示例使用 Foo 和 Bar 类作为占位符,以便您可以将注意力集中在事务使用上,而无需关注特定领域模型。在本例中,
DefaultFooService 类在实现方法的主体中抛出 UnsupportedOperationException 实例的事实是有益的。这种行为让您可以看到事务的创建和随后因
UnsupportedOperationException 实例而回滚。以下列表显示了 FooService 接口:
The following example shows an implementation of the preceding interface:
以下示例展示了先前接口的实现:
Assume that the first two methods of the FooService interface, getFoo(String) and getFoo(String, String), must run
in the context of a transaction with read-only semantics and that the other methods, insertFoo(Foo) and
updateFoo(Foo), must run in the context of a transaction with read-write semantics. The following configuration is
explained in detail in the next few paragraphs:
假设 FooService 接口的前两种方法 getFoo(String) 和 getFoo(String, String) 必须在只读语义的事务上下文中运行,而其他方法
insertFoo(Foo) 和 updateFoo(Foo) 必须在读写语义的事务上下文中运行。以下配置将在接下来的几段中详细解释:
Examine the preceding configuration. It assumes that you want to make a service object, the fooService bean,
transactional. The transaction semantics to apply are encapsulated in the <tx:advice/> definition. The <tx:advice/>
definition reads as "all methods starting with get are to run in the context of a read-only transaction, and all other
methods are to run with the default transaction semantics". The transaction-manager attribute of the <tx:advice/>
tag is set to the name of the TransactionManager bean that is going to drive the transactions (in this case, the
txManager bean).
检查前面的配置。它假设您想要创建一个服务对象,即 fooService 的 bean,使其具有事务性。要应用的事务语义封装在 <tx:advice/>
的定义中。 <tx:advice/> 的定义是“所有以 get 开头的所有方法将在只读事务的上下文中运行,而所有其他方法将使用默认的事务语义”。
<tx:advice/> 标签的 transaction-manager 属性设置为将要驱动事务的 TransactionManager bean 的名称(在这种情况下,是
txManager bean)。
You can omit the transaction-manager attribute in the transactional advice (<tx:advice/>) if the bean name of the
TransactionManager that you want to wire in has the name transactionManager. If the TransactionManager bean that
you want to wire in has any other name, you must use the transaction-manager attribute explicitly, as in the preceding
example.
您可以在事务建议( <tx:advice/> )中省略 transaction-manager 属性,如果您要连接的 TransactionManager 的 bean 名称是
transactionManager 。如果要将 TransactionManager bean 连接到其他名称,您必须显式使用 transaction-manager 属性,如前例所示。
The <aop:config/> definition ensures that the transactional advice defined by the txAdvice bean runs at the
appropriate points in the program. First, you define a pointcut that matches the execution of any operation defined in
the FooService interface (fooServiceOperation). Then you associate the pointcut with the txAdvice by using an
advisor. The result indicates that, at the execution of a fooServiceOperation, the advice defined by txAdvice is
run.
<aop:config/> 定义确保由 txAdvice 实现定义的事务建议在程序中的适当点运行。首先,您定义一个切入点,该切入点匹配
FooService 接口中定义的任何操作( fooServiceOperation )。然后,您通过使用建议者将切入点与 txAdvice 关联。结果指示,在执行
fooServiceOperation 时,运行由 txAdvice 定义的建议。
The expression defined within the <aop:pointcut/> element is an AspectJ pointcut expression.
See the AOP section for more details
on pointcut expressions in Spring.
该元素 <aop:pointcut/> 定义的表达式是一个 AspectJ 切点表达式。有关 Spring 中切点表达式的更多详细信息,请参阅 AOP 部分。
A common requirement is to make an entire service layer transactional. The best way to do this is to change the pointcut
expression to match any operation in your service layer. The following example shows how to do so:
一个常见的需求是将整个服务层设置为事务性。实现这一目标的最佳方法是更改切入点表达式以匹配您服务层中的任何操作。以下示例展示了如何进行操作:
In the preceding example, it is assumed that all your service interfaces are defined in the x.y.service package.
See the AOP section for more
details.
在前面示例中,假设您所有的服务接口都定义在 x.y.service 包中。请参阅 AOP 部分以获取更多详细信息。
Now that we have analyzed the configuration, you may be asking yourself, "What does all this configuration actually
do?"
现在我们已经分析了配置,你可能想知道:“所有这些配置实际上都做了什么?”
The configuration shown earlier is used to create a transactional proxy around the object that is created from the
fooService bean definition. The proxy is configured with the transactional advice so that, when an appropriate method
is invoked on the proxy, a transaction is started, suspended, marked as read-only, and so on, depending on the
transaction configuration associated with that method.
之前显示的配置用于在由 fooService bean
定义创建的对象周围创建一个事务代理。该代理配置了事务建议,以便在代理上调用适当的方法时,根据与该方法关联的事务配置,启动事务、挂起事务、将其标记为只读等。
Consider the following program that test drives the configuration shown earlier:
考虑以下测试驱动先前所示配置的程序:
The output from running the preceding program should resemble the following (the Log4J output and the stack trace from
the UnsupportedOperationException thrown by the insertFoo(..) method of the DefaultFooService class have been
truncated for clarity):
运行前面的程序后,输出应类似于以下内容(为了清晰,已截断 Log4J 输出和由 DefaultFooService 类中的 insertFoo(..) 方法抛出的
UnsupportedOperationException 异常的堆栈跟踪):
To use reactive transaction management the code has to use reactive types.
要使用反应式事务管理,代码必须使用反应式类型。
Spring Framework uses the ReactiveAdapterRegistry to determine whether a method return type is reactive.
Spring 框架使用 ReactiveAdapterRegistry 来确定方法返回类型是否为响应式。
The following listing shows a modified version of the previously used FooService, but this time the code uses reactive
types:
以下列表显示了之前使用的 FooService 的修改版本,但这次代码使用了响应式类型:
The following example shows an implementation of the preceding interface:
以下示例展示了先前接口的实现:
Imperative and reactive transaction management share the same semantics for transaction boundary and transaction
attribute definitions. The main difference between imperative and reactive transactions is the deferred nature of the
latter. TransactionInterceptor decorates the returned reactive type with a transactional operator to begin and clean
up the transaction. Therefore, calling a transactional reactive method defers the actual transaction management to a
subscription type that activates processing of the reactive type.
命令式和响应式事务管理共享相同的语义,用于事务边界和事务属性定义。命令式和响应式事务之间的主要区别在于后者的延迟性质。
TransactionInterceptor 使用事务操作符装饰返回的响应式类型,以开始和清理事务。因此,调用事务响应式方法将实际事务管理推迟到激活响应式类型处理的订阅类型。
Another aspect of reactive transaction management relates to data escaping which is a natural consequence of the
programming model.
另一个与反应式事务管理相关的方面是数据逃逸,这是编程模型的自然结果。
Method return values of imperative transactions are returned from transactional methods upon successful termination of a
method so that partially computed results do not escape the method closure.
方法返回 imperative 事务的值,在方法成功终止时从事务方法返回,以确保部分计算结果不会从方法作用域中逃逸。
Reactive transaction methods return a reactive wrapper type which represents a computation sequence along with a promise
to begin and complete the computation.
响应式事务方法返回一个表示计算序列以及开始和完成计算的承诺的响应式包装类型。
A Publisher can emit data while a transaction is ongoing but not necessarily completed. Therefore, methods that depend
upon successful completion of an entire transaction need to ensure completion and buffer results in the calling code.
一个 Publisher 可以在事务进行中发出数据,但不一定完成。因此,依赖于整个事务成功完成的方 法需要确保完成并在调用代码中缓冲结果。
1.4.3. 回滚声明式事务
The previous section outlined the basics of how to specify transactional settings for classes, typically service layer
classes, declaratively in your application.
上一节概述了如何在您的应用程序中以声明方式指定类(通常是服务层类)的事务设置的基本方法。
This section describes how you can control the rollback of transactions in a simple, declarative fashion in XML
configuration. For details on controlling rollback semantics declaratively with the @Transactional annotation, see
@Transactional Settings.
本节描述了您如何以简单、声明性的方式在 XML 配置中控制事务回滚。有关使用 @Transactional 注解声明性控制回滚语义的详细信息,请参阅
@Transactional 设置。
The recommended way to indicate to the Spring Framework’s transaction infrastructure that a transaction’s work is to be
rolled back is to throw an Exception from code that is currently executing in the context of a transaction. The Spring
Framework’s transaction infrastructure code catches any unhandled Exception as it bubbles up the call stack and makes
a determination whether to mark the transaction for rollback.
推荐向 Spring 框架的事务基础设施指示事务的工作需要回滚的方法是在当前执行事务上下文中的代码中抛出 Exception 。Spring
框架的事务基础设施代码在调用栈中捕获任何未处理的 Exception ,并决定是否标记事务为回滚。
In its default configuration, the Spring Framework’s transaction infrastructure code marks a transaction for rollback
only in the case of runtime, unchecked exceptions. That is, when the thrown exception is an instance or subclass of
RuntimeException. (Error instances also, by default, result in a rollback). Checked exceptions that are thrown from
a transactional method do not result in rollback in the default configuration.
在其默认配置中,Spring 框架的事务基础设施代码仅在运行时未检查的异常发生时标记事务进行回滚。也就是说,当抛出的异常是
RuntimeException 的实例或其子类时。(默认情况下, Error 实例也会导致回滚)。在默认配置下,从事务方法抛出的已检查异常不会导致回滚。
You can configure exactly which Exception types mark a transaction for rollback, including checked exceptions by
specifying rollback rules.
您可以配置哪些 Exception 类型标记事务为回滚,包括通过指定回滚规则来指定检查异常。
Rollback rules 回滚规则
Rollback rules determine if a transaction should be rolled back when a given exception is thrown, and the rules are
based on patterns. A pattern can be a fully qualified class name or a substring of a fully qualified class name for an
exception type (which must be a subclass of Throwable), with no wildcard support at present. For example, a value of
"javax.servlet.ServletException" or "ServletException" will match javax.servlet.ServletException and its
subclasses.
回滚规则确定在抛出给定异常时是否应该回滚事务,这些规则基于模式。一个模式可以是一个完全限定的类名,或者是一个异常类型的完全限定类名的子串(该异常类型必须是
Throwable 的子类),目前不支持通配符。例如, "javax.servlet.ServletException" 或 "ServletException" 的值将匹配
javax.servlet.ServletException 及其子类。
Rollback rules may be configured in XML via the rollback-for and no-rollback-for attributes, which allow patterns to
be specified as strings. When using @Transactional, rollback
rules may be configured via the rollbackFor/noRollbackFor and rollbackForClassName/noRollbackForClassName
attributes, which allow patterns to be specified as Class references or strings, respectively. When an exception type
is specified as a class reference its fully qualified name will be used as the pattern. Consequently,
@Transactional(rollbackFor = example.CustomException.class) is equivalent to
@Transactional(rollbackForClassName = "example.CustomException").
回滚规则可以通过 XML 中的 rollback-for 和 no-rollback-for 属性进行配置,这些属性允许将模式指定为字符串。当使用
@Transactional 时,可以通过 rollbackFor / noRollbackFor 和 rollbackForClassName / noRollbackForClassName
属性配置回滚规则,这些属性允许将模式指定为 Class 引用或字符串,分别。当指定异常类型为类引用时,其完全限定名称将用作模式。因此,
@Transactional(rollbackFor = example.CustomException.class) 等同于
@Transactional(rollbackForClassName = "example.CustomException") 。
You must carefully consider how specific the pattern is and whether to include package information (which isn’t
mandatory). For example, "Exception" will match nearly anything and will probably hide other rules.
"java.lang.Exception" would be correct if "Exception" were meant to define a rule for all checked exceptions. With
more unique exception names such as "BaseBusinessException" there is likely no need to use the fully qualified class
name for the exception pattern.
您必须仔细考虑模式的具体程度以及是否包含包信息(这不是强制性的)。例如, "Exception" 将匹配几乎所有内容,可能会隐藏其他规则。如果打算用
"Exception" 定义所有已检查异常的规则,那么 "java.lang.Exception" 将是正确的。对于像 "BaseBusinessException"
这样更独特的异常名称,可能没有必要使用完全限定的类名作为异常模式。
Furthermore, rollback rules may result in unintentional matches for similarly named exceptions and nested classes.
此外,回滚规则可能导致对名称相似异常和嵌套类的无意匹配。
This is due to the fact that a thrown exception is considered to be a match for a given rollback rule if the name of
thrown exception contains the exception pattern configured for the rollback rule. For example, given a rule configured
to match on com.example.CustomException, that rule would match against an exception named
com.example.CustomExceptionV2 (an exception in the same package as CustomException but with an additional suffix) or
an exception named com.example.CustomException$AnotherException (an exception declared as a nested class in
CustomException).
这是由于抛出的异常被认为与给定的回滚规则匹配,如果抛出的异常名称包含为回滚规则配置的异常模式。例如,给定一个配置为匹配
com.example.CustomException 的规则,该规则将与名为 com.example.CustomExceptionV2 (与 CustomException
在同一包中的异常,但带有附加后缀)的异常或名为 com.example.CustomException$AnotherException (在 CustomException
中声明的嵌套类异常)的异常匹配。
The following XML snippet demonstrates how to configure rollback for a checked, application-specific Exception type by
supplying an exception pattern via the rollback-for attribute:
以下 XML 片段演示了如何通过提供异常模式通过 rollback-for 属性来配置已检查的应用特定 Exception 类型的回滚:
If you do not want a transaction rolled back when an exception is thrown, you can also specify 'no rollback' rules. The
following example tells the Spring Framework’s transaction infrastructure to commit the attendant transaction even in
the face of an unhandled InstrumentNotFoundException:
如果您不希望在抛出异常时回滚事务,您也可以指定'不回滚'规则。以下示例告诉 Spring 框架的事务基础设施即使在面对未处理的异常
InstrumentNotFoundException 时也要提交相关事务。
When the Spring Framework’s transaction infrastructure catches an exception and consults the configured rollback rules
to determine whether to mark the transaction for rollback, the strongest matching rule wins.
当 Spring 框架的事务基础设施捕获到异常并咨询配置的回滚规则以确定是否标记事务进行回滚时,最匹配的规则获胜。
So, in the case of the following configuration, any exception other than an InstrumentNotFoundException results in a
rollback of the attendant transaction:
因此,在以下配置的情况下,除了 InstrumentNotFoundException 以外的任何异常都会导致相关事务回滚:
You can also indicate a required rollback programmatically. Although simple, this process is quite invasive and tightly
couples your code to the Spring Framework’s transaction infrastructure. The following example shows how to
programmatically indicate a required rollback:
您也可以通过编程方式指示所需的回滚。尽管这个过程很简单,但它相当侵入性,并且将您的代码紧密耦合到 Spring
框架的事务基础设施中。以下示例展示了如何通过编程方式指示所需的回滚:
You are strongly encouraged to use the declarative approach to rollback, if at all possible. Programmatic rollback is
available should you absolutely need it, but its usage flies in the face of achieving a clean POJO-based architecture.
强烈建议尽可能使用声明式方法进行回滚。如果绝对需要,程序化回滚也是可用的,但其使用与实现基于 POJO 的清晰架构背道而驰。
1.4.4. 为不同的 Bean 配置不同的事务语义
Consider the scenario where you have a number of service layer objects, and you want to apply a totally different
transactional configuration to each of them. You can do so by defining distinct <aop:advisor/> elements with differing
pointcut and advice-ref attribute values.
考虑这样一个场景,你拥有多个服务层对象,并且希望为每个对象应用完全不同的交易配置。你可以通过定义具有不同 pointcut 和
advice-ref 属性值的独立 <aop:advisor/> 元素来实现这一点。
As a point of comparison, first assume that all of your service layer classes are defined in a root x.y.service
package. To make all beans that are instances of classes defined in that package (or in subpackages) and that have names
ending in Service have the default transactional configuration, you could write the following:
作为比较的一个点,首先假设您所有的服务层类都定义在根 x.y.service 包中。为了使所有属于该包(或子包)中定义的类实例,并且名称以
Service 结尾的 bean 具有默认的事务配置,您可以编写以下内容:
The following example shows how to configure two distinct beans with totally different transactional settings:
以下示例展示了如何配置两个具有完全不同事务设置的独立 bean:
1.4.5. 设置
This section summarizes the various transactional settings that you can specify by using the <tx:advice/> tag. The
default <tx:advice/> settings are:
本节总结了您可以通过使用 <tx:advice/> 标签指定的各种事务设置。默认的 <tx:advice/> 设置是:
The propagation setting is REQUIRED.
传播设置是 REQUIRED.
The isolation level is DEFAULT.
隔离级别是 DEFAULT.
The transaction is read-write.
事务是读写操作。
The transaction timeout defaults to the default timeout of the underlying transaction system or none if timeouts are
not supported.
事务超时默认为底层事务系统的默认超时时间,如果不支持超时则无超时。
Any RuntimeException triggers rollback, and any checked Exception does not.
任何 RuntimeException 都会触发回滚,而任何已检查的 Exception 则不会。
You can change these default settings. The following table summarizes the various attributes of the <tx:method/> tags
that are nested within <tx:advice/> and <tx:attributes/> tags:
您可以更改这些默认设置。以下表格总结了嵌套在 <tx:advice/> 和 <tx:attributes/> 标签内的 <tx:method/> 标签的各种属性:
Table 1. tx:method/ settings
表 1. 设置
Attribute 属性
Required? 需要吗?
Default 默认
Description 描述
name
Yes 是的
Method names with which the transaction attributes are to be associated. The wildcard (*) character can be used to
associate the same transaction attribute settings with a number of methods (for example, get*, handle*, on*Event,
and so forth).
方法名称,用于关联事务属性。可以使用通配符(*)字符将相同的事务属性设置关联到多个方法(例如, get* 、 handle* 、 on*Event
等等)。
propagation
No 没有
REQUIRED
Transaction propagation behavior.
事务传播行为。
isolation
No 没有
DEFAULT
Transaction isolation level. Only applicable to propagation settings of REQUIRED or REQUIRES_NEW.
事务隔离级别。仅适用于 REQUIRED 或 REQUIRES_NEW 的传播设置。
timeout
No 没有
-1
Transaction timeout (seconds). Only applicable to propagation REQUIRED or REQUIRES_NEW.
交易超时(秒)。仅适用于传播 REQUIRED 或 REQUIRES_NEW 。
read-only
No 没有
false
Read-write versus read-only transaction. Applies only to REQUIRED or REQUIRES_NEW.
读写交易与只读交易。仅适用于 REQUIRED 或 REQUIRES_NEW 。
rollback-for
No 没有
Comma-delimited list of Exception instances that trigger rollback. For example,
com.foo.MyBusinessException,ServletException.
逗号分隔的触发回滚的 Exception 实例列表。例如, com.foo.MyBusinessException,ServletException 。
no-rollback-for
No 没有
Comma-delimited list of Exception instances that do not trigger rollback. For example,
com.foo.MyBusinessException,ServletException.
逗号分隔的 Exception 实例列表,这些实例不会触发回滚。例如, com.foo.MyBusinessException,ServletException 。
@Transactional 1.4.6. 使用@TransactionalIn addition to the XML-based declarative approach to transaction configuration, you can use an annotation-based
approach. Declaring transaction semantics directly in the Java source code puts the declarations much closer to the
affected code.
除了基于 XML 的声明性事务配置方法之外,您还可以使用基于注解的方法。直接在 Java
源代码中声明事务语义将声明放置得更接近受影响的代码。
There is not much danger of undue coupling, because code that is meant to be used transactionally is almost always
deployed that way anyway.
没有过度耦合的危险,因为本意用于事务处理的代码几乎总是以这种方式部署。
The standard javax.transaction.Transactional annotation is also supported as a drop-in replacement to Spring’s own
annotation. Please refer to JTA 1.2 documentation for more details.
标准 javax.transaction.Transactional 注解也支持作为 Spring 自身注解的即插即用替代。请参阅 JTA 1.2 文档以获取更多详细信息。
The ease-of-use afforded by the use of the @Transactional annotation is best illustrated with an example, which is
explained in the text that follows. Consider the following class definition:
使用 @Transactional 注解带来的易用性最好通过以下示例来说明,具体解释见下文。考虑以下类定义:
1
The line that makes the bean instance transactional.
Used at the class level as above, the annotation indicates a default for all methods of the declaring class (as well as
its subclasses). Alternatively, each method can be annotated individually. See Method visibility and
@Transactional for further details on which methods Spring
considers transactional.
在类级别上使用,该注解表示声明类(及其子类)的所有方法的默认值。或者,每个方法都可以单独注解。有关 Spring
认为哪些方法为事务性的进一步详细信息,请参阅方法可见性和 @Transactional 。
Note that a class-level annotation does not apply to ancestor classes up the class hierarchy; in such a scenario,
inherited methods need to be locally redeclared in order to participate in a subclass-level annotation.
请注意,类级别的注解不适用于类层次结构中的祖先类;在这种情况下,需要在本地重新声明继承的方法,以便参与子类级别的注解。
When a POJO class such as the one above is defined as a bean in a Spring context, you can make the bean instance
transactional through an @EnableTransactionManagement annotation in a @Configuration class. See
the javadoc
for full details.
当定义如上所示的 POJO 类为 Spring 上下文中的 bean 时,您可以通过在 @Configuration 类中使用
@EnableTransactionManagement 注解使 bean 实例具有事务性。请参阅 javadoc 以获取完整详细信息。
In XML configuration, the <tx:annotation-driven/> tag provides similar convenience:
在 XML 配置中, <tx:annotation-driven/> 标签提供了类似的便利:
You can omit the transaction-manager attribute in the <tx:annotation-driven/> tag if the bean name of the
TransactionManager that you want to wire in has the name transactionManager. If the TransactionManager bean that
you want to dependency-inject has any other name, you have to use the transaction-manager attribute, as in the
preceding example.
您可以在 <tx:annotation-driven/> 标签中省略 transaction-manager 属性,如果您要连接的 TransactionManager 的 bean 名称是
transactionManager 。如果想要依赖注入的 TransactionManager bean 有其他名称,您必须使用 transaction-manager
属性,就像前面的例子一样。
Reactive transactional methods use reactive return types in contrast to imperative programming arrangements as the
following listing shows:
响应式事务方法使用响应式返回类型,与以下列表所示的命令式编程安排相反:
Note that there are special considerations for the returned Publisher with regards to Reactive Streams cancellation
signals. See the Cancel Signals section under "Using the TransactionalOperator" for more
details.
请注意,对于返回的 Publisher 在 Reactive Streams 取消信号方面有特殊考虑。有关详细信息,请参阅“使用
TransactionalOperator”下的“取消信号”部分。
Method visibility and @Transactional
方法可见性和 @Transactional
When you use transactional proxies with Spring’s standard configuration, you should apply the @Transactional
annotation only to methods with public visibility. If you do annotate protected, private, or package-visible
methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the
configured transactional settings.
当您使用 Spring 标准配置中的事务代理时,应仅将 @Transactional 注解应用于具有 public 可见性的方法。如果您对
protected 、 private 或包可见方法使用 @Transactional 注解,则不会引发错误,但被注解的方法不会显示配置的事务设置。
If you need to annotate non-public methods, consider the tip in the following paragraph for class-based proxies or
consider using AspectJ compile-time or load-time weaving (described later).
如果您需要注释非公共方法,请考虑下一段中提到的基于类的代理提示,或者考虑使用 AspectJ 编译时或加载时织入(稍后描述)。
When using @EnableTransactionManagement in a @Configuration class, protected or package-visible methods can also
be made transactional for class-based proxies by registering a custom transactionAttributeSource bean like in the
following example. Note, however, that transactional methods in interface-based proxies must always be public and
defined in the proxied interface.
当在 @Configuration 类中使用 @EnableTransactionManagement 时,通过注册自定义的 transactionAttributeSource
bean,也可以使类代理的 protected 或包可见方法变得事务性,如下例所示。请注意,然而,基于接口的代理中的事务性方法必须始终是
public 并在代理的接口中定义。
The Spring TestContext Framework supports non-private @Transactional test methods by default.
See Transaction Management
in the testing chapter for examples.
Spring 测试上下文框架默认支持非私有 @Transactional 测试方法。请参阅测试章节中的事务管理部分以获取示例。
You can apply the @Transactional annotation to an interface definition, a method on an interface, a class definition,
or a method on a class. However, the mere presence of the @Transactional annotation is not enough to activate the
transactional behavior. The @Transactional annotation is merely metadata that can be consumed by corresponding runtime
infrastructure which uses that metadata to configure the appropriate beans with transactional behavior. In the preceding
example, the <tx:annotation-driven/> element switches on actual transaction management at runtime.
您可以将 @Transactional 注解应用于接口定义、接口上的方法、类定义或类上的方法。然而,仅存在 @Transactional 注解并不足以激活事务行为。
@Transactional 注解仅是元数据,可以被相应的运行时基础设施消费,该基础设施使用这些元数据来配置具有事务行为的适当
bean。在前面的示例中, <tx:annotation-driven/> 元素在运行时开启了实际的事务管理。
The Spring team recommends that you annotate methods of concrete classes with the @Transactional annotation, rather
than relying on annotated methods in interfaces, even if the latter does work for interface-based and target-class
proxies as of 5.0. Since Java annotations are not inherited from interfaces, interface-declared annotations are still
not recognized by the weaving infrastructure when using AspectJ mode, so the aspect does not get applied.
Spring 团队建议您使用 @Transactional 注解标注具体类的的方法,而不是依赖于接口中注解的方法,即使从 5.0
版本开始,后者的方法对基于接口和目标类代理也有效。由于 Java 注解不是从接口继承的,因此在使用 AspectJ
模式时,接口声明的注解仍然不会被编织基础设施识别,因此方面无法应用。
As a consequence, your transaction annotations may be silently ignored: Your code might appear to "work" until you test
a rollback scenario.
因此,您的交易注释可能会被无声地忽略:您的代码可能看起来“工作”正常,直到您测试回滚场景。
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted.
在代理模式下(这是默认设置),只有通过代理进入的外部方法调用会被拦截。
This means that self-invocation (in effect, a method within the target object calling another method of the target
object) does not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.
Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in
your initialization code — e.g. in a @PostConstruct method.
这意味着自我调用(实际上,目标对象中的方法调用目标对象的另一个方法)即使在运行时调用的方法被标记为 @Transactional
,也不会导致实际的事务。此外,代理必须完全初始化以提供预期的行为,因此您不应在初始化代码中依赖此功能——例如,在
@PostConstruct 方法中。
Consider using AspectJ mode (see the mode attribute in the following table) if you expect self-invocations to be
wrapped with transactions as well. In this case, there is no proxy in the first place. Instead, the target class is
woven (that is, its byte code is modified) to support @Transactional runtime behavior on any kind of method.
考虑使用 AspectJ 模式(参见下表中 mode 属性),如果您期望自我调用也被事务包装。在这种情况下,最初就没有代理。相反,目标类被编织(即其字节码被修改)以支持
@Transactional 在任何类型的函数上的运行时行为。
Table 2. Annotation driven transaction settings
表 2. 注解驱动的事务设置
XML Attribute XML 属性
Annotation Attribute 注释属性
Default 默认
Description 描述
transaction-manager
N/A (see
TransactionManagementConfigurer
javadoc)N/A(见 TransactionManagementConfigurer javadoc)
transactionManager
Name of the transaction manager to use. Required only if the name of the transaction manager is not
transactionManager, as in the preceding example.
交易管理器的名称。仅在交易管理器名称不是 transactionManager 时需要,如前例所示。
mode
mode
proxy
The default mode (proxy) processes annotated beans to be proxied by using Spring’s AOP framework (following proxy
semantics, as discussed earlier, applying to method calls coming in through the proxy only). The alternative mode (
aspectj) instead weaves the affected classes with Spring’s AspectJ transaction aspect, modifying the target class byte
code to apply to any kind of method call. AspectJ weaving requires spring-aspects.jar in the classpath as well as
having load-time weaving (or compile-time weaving) enabled. (
See Spring configuration
for details on how to set up load-time weaving.)
默认模式( proxy )通过使用 Spring 的 AOP 框架(遵循前面讨论的代理语义,仅适用于通过代理传入的方法调用)处理要代理的注解豆。另一种模式(
aspectj )则使用 Spring 的 AspectJ 事务方面将受影响的类编织在一起,修改目标类字节码以适用于任何类型的方法调用。AspectJ
编织需要在类路径中包含 spring-aspects.jar ,并且启用加载时编织(或编译时编织)。(有关如何设置加载时编织的详细信息,请参阅
Spring 配置。)
proxy-target-class
proxyTargetClass
false
Applies to proxy mode only. Controls what type of transactional proxies are created for classes annotated with the
@Transactional annotation. If the proxy-target-class attribute is set to true, class-based proxies are created. If
proxy-target-class is false or if the attribute is omitted, then standard JDK interface-based proxies are created. (
See Proxying Mechanisms for
a detailed examination of the different proxy types.)
仅适用于 proxy 模式。控制为带有 @Transactional 注解的类创建哪种类型的交易代理。如果 proxy-target-class 属性设置为
true ,则创建基于类的代理。如果 proxy-target-class 是 false 或省略了该属性,则创建基于标准 JDK
接口的代理。(有关不同代理类型的详细检查,请参阅代理机制。)
order
order
Ordered.LOWEST_PRECEDENCE
Defines the order of the transaction advice that is applied to beans annotated with @Transactional. (For more
information about the rules related to ordering of AOP advice,
see Advice Ordering.)
No specified ordering means that the AOP subsystem determines the order of the advice.
定义应用于标注为 @Transactional 的豆的交易建议的顺序。(有关 AOP 建议排序的相关规则,请参阅建议排序。)未指定顺序意味着 AOP
子系统确定建议的顺序。
The default advice mode for processing @Transactional annotations is proxy, which allows for interception of calls
through the proxy only. Local calls within the same class cannot get intercepted that way. For a more advanced mode of
interception, consider switching to aspectj mode in combination with compile-time or load-time weaving.
默认的处理 @Transactional 注解的建议模式是 proxy ,这仅允许通过代理拦截调用。同一类内的本地调用无法通过这种方式拦截。对于更高级的拦截模式,考虑结合编译时或加载时织入切换到
aspectj 模式。
The proxy-target-class attribute controls what type of transactional proxies are created for classes annotated with
the @Transactional annotation. If proxy-target-class is set to true, class-based proxies are created. If
proxy-target-class is false or if the attribute is omitted, standard JDK interface-based proxies are created. (
See Proxying Mechanisms for
a discussion of the different proxy types.)
proxy-target-class 属性控制为带有 @Transactional 注解的类创建哪种类型的交易代理。如果 proxy-target-class 设置为
true ,则创建基于类的代理。如果 proxy-target-class 是 false 或者省略了该属性,则创建基于标准 JDK
接口的代理。(有关不同代理类型的讨论,请参阅代理机制。)
@EnableTransactionManagement and <tx:annotation-driven/> look for @Transactional only on beans in the same
application context in which they are defined. This means that, if you put annotation-driven configuration in a
WebApplicationContext for a DispatcherServlet, it checks for @Transactional beans only in your controllers and not
in your services. See MVC for
more information.
@EnableTransactionManagement 和 <tx:annotation-driven/> 只在它们定义的应用程序上下文中查找 @Transactional
。这意味着,如果您在一个 WebApplicationContext 中为 DispatcherServlet 放置注解驱动的配置,它只会在您的控制器中检查
@Transactional ,而不是在您的服务中。有关更多信息,请参阅 MVC。
The most derived location takes precedence when evaluating the transactional settings for a method. In the case of the
following example, the DefaultFooService class is annotated at the class level with the settings for a read-only
transaction, but the @Transactional annotation on the updateFoo(Foo) method in the same class takes precedence over
the transactional settings defined at the class level.
在评估方法的事务设置时,最派生的位置具有优先权。在以下示例中, DefaultFooService 类在类级别上注解了只读事务的设置,但同一类中的
updateFoo(Foo) 方法的 @Transactional 注解优先于类级别定义的事务设置。
@Transactional Settings@Transactional 设置The @Transactional annotation is metadata that specifies that an interface, class, or method must have transactional
semantics (for example, "start a brand new read-only transaction when this method is invoked, suspending any existing
transaction"). The default @Transactional settings are as follows:
@Transactional 注解是元数据,指定接口、类或方法必须具有事务语义(例如,“当调用此方法时,启动一个新的只读事务,挂起任何现有事务”)。默认的
@Transactional 设置如下:
The propagation setting is PROPAGATION_REQUIRED.
传播设置是 PROPAGATION_REQUIRED.
The isolation level is ISOLATION_DEFAULT.
隔离级别是 ISOLATION_DEFAULT.
The transaction is read-write.
事务是读写操作。
The transaction timeout defaults to the default timeout of the underlying transaction system, or to none if timeouts
are not supported.
事务超时默认为底层事务系统的默认超时时间,或者如果不支持超时,则为无超时。
Any RuntimeException or Error triggers rollback, and any checked Exception does not.
任何 RuntimeException 或 Error 都会触发回滚,而任何已检查的 Exception 则不会。
You can change these default settings. The following table summarizes the various properties of the @Transactional
annotation:
您可以更改这些默认设置。下表总结了 @Transactional 注解的各种属性:
Table 3. @Transactional Settings
表 3. @Transactional 设置
Property 属性
Type 类型
Description 描述
String
Optional qualifier that specifies the transaction manager to be used.
可选限定符,用于指定要使用的交易管理器。
transactionManager
String
Alias for value. 别名 for value .
label
Array of String labels to add an expressive description to the transaction.
数组,用于添加表达性描述的交易标签。
Labels may be evaluated by transaction managers to associate implementation-specific behavior with the actual
transaction.
标签可能由事务管理器评估,以将特定于实现的操作与实际事务关联。
enum: Propagation
Optional propagation setting.
可选传播设置。
isolation
enum: Isolation
Optional isolation level. Applies only to propagation values of REQUIRED or REQUIRES_NEW.
可选隔离级别。仅适用于 REQUIRED 或 REQUIRES_NEW 的传播值。
timeout
int (in seconds of granularity)
int (以秒为粒度)
Optional transaction timeout. Applies only to propagation values of REQUIRED or REQUIRES_NEW.
可选事务超时。仅适用于 REQUIRED 或 REQUIRES_NEW 的传播值。
timeoutString
String (in seconds of granularity)
String (以秒为粒度)
Alternative for specifying the timeout in seconds as a String value — for example, as a placeholder.
替代指定 timeout 为秒的 String 值——例如,作为一个占位符。
readOnly
boolean
Read-write versus read-only transaction. Only applicable to values of REQUIRED or REQUIRES_NEW.
读写交易与只读交易。仅适用于 REQUIRED 或 REQUIRES_NEW 的值。
rollbackFor
Array of Class objects, which must be derived from Throwable.
对象数组,必须从 Throwable. 派生
Optional array of exception types that must cause rollback.
可选的异常类型数组,必须导致回滚。
rollbackForClassName
Array of exception name patterns.
异常名称模式数组。
Optional array of exception name patterns that must cause rollback.
可选的异常名称模式数组,必须导致回滚。
noRollbackFor
Array of Class objects, which must be derived from Throwable.
对象数组,必须从 Throwable. 派生
Optional array of exception types that must not cause rollback.
可选的异常类型数组,这些类型不应导致回滚。
noRollbackForClassName
Array of exception name patterns.
异常名称模式数组。
Optional array of exception name patterns that must not cause rollback.
可选的异常名称模式数组,不得导致回滚。
See Rollback rules for further details on rollback rule semantics, patterns,
and warnings regarding possible unintentional matches.
查看回滚规则以获取有关回滚规则语义、模式和有关可能意外匹配的警告的更多详细信息。
Currently, you cannot have explicit control over the name of a transaction, where 'name' means the transaction name that
appears in a transaction monitor, if applicable (for example, WebLogic’s transaction monitor), and in logging output.
目前,您无法明确控制事务的名称,这里的“名称”指的是在事务监控器中显示的事务名称(如果适用,例如 WebLogic
的事务监控器),以及在日志输出中显示的事务名称。
For declarative transactions, the transaction name is always the fully-qualified class name + . + the method name of
the transactionally advised class. For example, if the handlePayment(..) method of the BusinessService class started
a transaction, the name of the transaction would be: com.example.BusinessService.handlePayment.
对于声明式事务,事务名称始终是完全限定的类名 + . + 具有事务性建议的类的方程序名。例如,如果 BusinessService 类的
handlePayment(..) 方程序启动了一个事务,事务的名称将是: com.example.BusinessService.handlePayment 。
@Transactional多个事务管理器 @Transactional
Most Spring applications need only a single transaction manager, but there may be situations where you want multiple
independent transaction managers in a single application. You can use the value or transactionManager attribute of
the @Transactional annotation to optionally specify the identity of the TransactionManager to be used. This can
either be the bean name or the qualifier value of the transaction manager bean. For example, using the qualifier
notation, you can combine the following Java code with the following transaction manager bean declarations in the
application context:
大多数 Spring 应用程序只需要一个事务管理器,但可能存在你希望在单个应用程序中使用多个独立事务管理器的情况。你可以使用
@Transactional 注解的 value 或 transactionManager 属性来可选地指定要使用的 TransactionManager 的身份。这可以是
bean 名称或事务管理器 bean 的 qualifier 值。例如,使用 qualifier 表示法,你可以在应用程序上下文中将以下 Java 代码与以下事务管理器
bean 声明组合起来:
The following listing shows the bean declarations:
以下列表显示了 Bean 声明:
In this case, the individual methods on TransactionalService run under separate transaction managers, differentiated
by the order, account, and reactive-account qualifiers. The default <tx:annotation-driven> target bean name,
transactionManager, is still used if no specifically qualified TransactionManager bean is found.
在这种情况下, TransactionalService 上的各个方法在单独的事务管理器下运行,通过 order 、 account 和 reactive-account
限定符进行区分。如果没有找到特定限定符的 TransactionManager 豆,则仍然使用默认的 <tx:annotation-driven> 目标豆名称
transactionManager 。
自定义注释
If you find you repeatedly use the same attributes with @Transactional on many different
methods, Spring’s meta-annotation support
lets you define custom composed annotations for your specific use cases. For example, consider the following annotation
definitions:
如果您在许多不同的方法中反复使用相同的属性与 @Transactional ,Spring 的元注解支持允许您为特定的用例定义自定义组合注解。例如,考虑以下注解定义:
The preceding annotations let us write the example from the previous section as follows:
前述注释使我们能够将上一节中的示例编写如下:
In the preceding example, we used the syntax to define the transaction manager qualifier and transactional labels, but
we could also have included propagation behavior, rollback rules, timeouts, and other features.
在先前的示例中,我们使用了语法来定义事务管理器限定符和事务标签,但我们也可以包括传播行为、回滚规则、超时和其他功能。
1.4.7. 事务传播
This section describes some semantics of transaction propagation in Spring. Note that this section is not a proper
introduction to transaction propagation. Rather, it details some of the semantics regarding transaction propagation in
Spring.
本节描述了 Spring 中事务传播的一些语义。请注意,本节并非对事务传播的适当介绍。相反,它详细说明了 Spring 中关于事务传播的一些语义。
In Spring-managed transactions, be aware of the difference between physical and logical transactions, and how the
propagation setting applies to this difference.
在 Spring 管理的交易中,请注意物理交易和逻辑交易之间的区别,以及传播设置如何应用于这种区别。
PROPAGATION_REQUIRED 理解PROPAGATION_REQUIRED
PROPAGATION_REQUIRED enforces a physical transaction, either locally for the current scope if no transaction exists
yet or participating in an existing 'outer' transaction defined for a larger scope.
PROPAGATION_REQUIRED
强制执行一个物理事务,如果当前作用域中尚未存在事务,则在本地上执行,或者参与为更大作用域定义的现有“外部”事务。
This is a fine default in common call stack arrangements within the same thread (for example, a service facade that
delegates to several repository methods where all the underlying resources have to participate in the service-level
transaction).
这是一个在相同线程中常见的调用栈安排中的良好默认设置(例如,一个将职责委托给多个存储库方法的业务外观,其中所有底层资源都必须参与服务级别的交易)。
By default, a participating transaction joins the characteristics of the outer scope, silently ignoring the local
isolation level, timeout value, or read-only flag (if any). Consider switching the validateExistingTransactions flag
to true on your transaction manager if you want isolation level declarations to be rejected when participating in an
existing transaction with a different isolation level.
默认情况下,参与事务会继承外部作用域的特性,静默忽略本地隔离级别、超时值或只读标志(如果有)。如果您希望在参与具有不同隔离级别的现有事务时拒绝隔离级别声明,请考虑将您的交易管理器上的
validateExistingTransactions 标志切换为 true 。
This non-lenient mode also rejects read-only mismatches (that is, an inner read-write transaction that tries to
participate in a read-only outer scope).
这种非宽容模式也拒绝只读不匹配(即尝试参与只读外部作用域的内部读写事务)。
When the propagation setting is PROPAGATION_REQUIRED, a logical transaction scope is created for each method upon
which the setting is applied. Each such logical transaction scope can determine rollback-only status individually, with
an outer transaction scope being logically independent from the inner transaction scope.
当传播设置是 PROPAGATION_REQUIRED
时,为应用此设置的每个方法创建一个逻辑事务范围。每个这样的逻辑事务范围可以单独确定回滚只读状态,外部事务范围在逻辑上独立于内部事务范围。
In the case of standard PROPAGATION_REQUIRED behavior, all these scopes are mapped to the same physical transaction.
So a rollback-only marker set in the inner transaction scope does affect the outer transaction’s chance to actually
commit.
在标准 PROPAGATION_REQUIRED 行为的情况下,所有这些作用域都映射到同一个物理事务。因此,在内部事务作用域中设置的仅回滚标记确实会影响外部事务实际提交的机会。
However, in the case where an inner transaction scope sets the rollback-only marker, the outer transaction has not
decided on the rollback itself, so the rollback (silently triggered by the inner transaction scope) is unexpected. A
corresponding UnexpectedRollbackException is thrown at that point. This is expected behavior so that the caller of a
transaction can never be misled to assume that a commit was performed when it really was not.
然而,在内部事务作用域设置回滚标记的情况下,外部事务尚未决定是否回滚,因此由内部事务作用域(静默触发)的回滚是意外的。此时会抛出相应的
UnexpectedRollbackException 异常。这是预期行为,以确保事务的调用者永远不会被误导,认为已执行提交,而实际上并未执行。
So, if an inner transaction (of which the outer caller is not aware) silently marks a transaction as rollback-only, the
outer caller still calls commit. The outer caller needs to receive an UnexpectedRollbackException to indicate clearly
that a rollback was performed instead.
因此,如果一个内部事务(外部调用者并不知情)静默地将事务标记为仅回滚,外部调用者仍然调用提交。外部调用者需要接收到一个
UnexpectedRollbackException 以明确表示已执行回滚。
PROPAGATION_REQUIRES_NEW 理解PROPAGATION_REQUIRES_NEW
PROPAGATION_REQUIRES_NEW, in contrast to PROPAGATION_REQUIRED, always uses an independent physical transaction for
each affected transaction scope, never participating in an existing transaction for an outer scope.
PROPAGATION_REQUIRES_NEW 与 PROPAGATION_REQUIRED
相比,始终为每个受影响的交易范围使用独立的物理事务,从不参与外部范围现有的交易。
In such an arrangement, the underlying resource transactions are different and, hence, can commit or roll back
independently, with an outer transaction not affected by an inner transaction’s rollback status and with an inner
transaction’s locks released immediately after its completion.
在这种安排下,底层资源事务不同,因此可以独立提交或回滚,外部事务不受内部事务回滚状态的影响,并且内部事务在完成后立即释放其锁。
Such an independent inner transaction can also declare its own isolation level, timeout, and read-only settings and not
inherit an outer transaction’s characteristics.
这样的独立内部事务也可以声明自己的隔离级别、超时和只读设置,并且不会继承外部事务的特性。
The resources attached to the outer transaction will remain bound there while the inner transaction acquires its own
resources such as a new database connection.
外部事务附加的资源将保持绑定状态,而内部事务将获取自己的资源,例如新的数据库连接。
This may lead to exhaustion of the connection pool and potentially to a deadlock if several threads have an active outer
transaction and wait to acquire a new connection for their inner transaction, with the pool not being able to hand out
any such inner connection anymore.
这可能导致连接池耗尽,如果多个线程有活跃的外部事务并等待获取其内部事务的新连接,而池无法再分配此类内部连接,可能会引发死锁。
Do not use PROPAGATION_REQUIRES_NEW unless your connection pool is appropriately sized, exceeding the number of
concurrent threads by at least 1.
不要使用 PROPAGATION_REQUIRES_NEW ,除非您的连接池大小适当,至少比并发线程数多 1。
PROPAGATION_NESTED 理解PROPAGATION_NESTEDPROPAGATION_NESTED uses a single physical transaction with multiple savepoints that it can roll back to.
PROPAGATION_NESTED 使用单个物理事务,并具有多个可以回滚到的事务点。
Such partial rollbacks let an inner transaction scope trigger a rollback for its scope, with the outer transaction being
able to continue the physical transaction despite some operations having been rolled back.
这种部分回滚允许内部事务作用域触发其作用域的回滚,尽管某些操作已回滚,但外部事务仍能继续物理事务。
This setting is typically mapped onto JDBC savepoints, so it works only with JDBC resource transactions. See Spring’s
DataSourceTransactionManager.
此设置通常映射到 JDBC 保存点,因此仅适用于 JDBC 资源事务。请参阅 Spring 的 DataSourceTransactionManager 。
1.4.8. 建议事务操作
Suppose you want to run both transactional operations and some basic profiling advice. How do you effect this in the
context of <tx:annotation-driven/>?
假设您想同时运行事务操作和一些基本性能分析建议。如何在 <tx:annotation-driven/> 的上下文中实现这一点?
When you invoke the updateFoo(Foo) method, you want to see the following actions:
当你调用 updateFoo(Foo) 方法时,你希望看到以下操作:
The configured profiling aspect starts.
配置的配置方面开始。
The transactional advice runs.
交易建议正在进行。
The method on the advised object runs.
该方法在建议对象上运行。
The transaction commits.
事务提交。
The profiling aspect reports the exact duration of the whole transactional method invocation.
该配置方面报告了整个事务方法调用的确切持续时间。
This chapter is not concerned with explaining AOP in any great detail (except as it applies to transactions).
See AOP for detailed coverage of the
AOP configuration and AOP in general.
本章不涉及对 AOP 进行详细解释(除非涉及到事务)。有关 AOP 配置和 AOP 的详细信息,请参阅 AOP。
The following code shows the simple profiling aspect discussed earlier:
以下代码展示了之前讨论过的简单分析方面:
The ordering of advice is controlled through the Ordered interface. For full details on advice ordering,
see Advice ordering.
建议的排序通过 Ordered 接口控制。有关建议排序的详细信息,请参阅建议排序。
The following configuration creates a fooService bean that has profiling and transactional aspects applied to it in
the desired order:
以下配置创建了一个应用了所需顺序的配置文件和事务属性的 fooService bean:
You can configure any number of additional aspects in similar fashion.
您可以以类似方式配置任意数量的附加方面。
The following example creates the same setup as the previous two examples but uses the purely XML declarative
approach:
以下示例创建了与前面两个示例相同的设置,但使用的是纯 XML 声明式方法:
The result of the preceding configuration is a fooService bean that has profiling and transactional aspects applied to
it in that order. If you want the profiling advice to run after the transactional advice on the way in and before the
transactional advice on the way out, you can swap the value of the profiling aspect bean’s order property so that it
is higher than the transactional advice’s order value.
前述配置的结果是一个应用了配置顺序的 fooService bean,其中包含了配置的配置和事务方面。如果您希望在进入时在事务建议之后和退出时在事务建议之前运行配置建议,您可以交换配置方面
bean 的 order 属性值,使其高于事务建议的顺序值。
You can configure additional aspects in similar fashion.
您可以以类似方式配置其他方面。
@Transactional with AspectJ1.4.9. 使用 @Transactional 与 AspectJ
You can also use the Spring Framework’s @Transactional support outside of a Spring container by means of an AspectJ
aspect. To do so, first annotate your classes (and optionally your classes' methods) with the @Transactional
annotation, and then link (weave) your application with the
org.springframework.transaction.aspectj.AnnotationTransactionAspect defined in the spring-aspects.jar file. You must
also configure the aspect with a transaction manager. You can use the Spring Framework’s IoC container to take care of
dependency-injecting the aspect. The simplest way to configure the transaction management aspect is to use the
<tx:annotation-driven/> element and specify the mode attribute to aspectj as described in Using
@Transactional. Because we focus here on applications that run outside of a
Spring container, we show you how to do it programmatically.
您也可以通过 AspectJ 方面在 Spring 容器外部使用 Spring 框架的 @Transactional 支持。为此,首先使用 @Transactional
注解您的类(以及可选的类方法),然后链接(编织)您的应用程序与 spring-aspects.jar 文件中定义的
org.springframework.transaction.aspectj.AnnotationTransactionAspect 相关联。您还必须使用事务管理器配置方面。您可以使用
Spring 框架的 IoC 容器来处理方面的依赖注入。配置事务管理方面最简单的方法是使用 <tx:annotation-driven/> 元素并指定
mode 属性为 aspectj ,如使用 @Transactional 所述。因为我们在这里关注运行在 Spring 容器之外的应用程序,所以我们向您展示如何以编程方式完成此操作。
Prior to continuing, you may want to read Using @Transactional
and AOP respectively.
在继续之前,你可能想分别阅读使用 @Transactional 和 AOP 的内容。
The following example shows how to create a transaction manager and configure the AnnotationTransactionAspect to use
it:
以下示例展示了如何创建事务管理器并配置 AnnotationTransactionAspect 以使用它:
When you use this aspect, you must annotate the implementation class (or the methods within that class or both), not the
interface (if any) that the class implements. AspectJ follows Java’s rule that annotations on interfaces are not
inherited.
当您使用此方面时,必须注释实现类(或该类中的方法或两者),而不是类实现的接口(如果有)。AspectJ 遵循 Java 的规则,即接口上的注解不会继承。
The @Transactional annotation on a class specifies the default transaction semantics for the execution of any public
method in the class.
类上的 @Transactional 注解指定了该类中任何公共方法执行时的默认事务语义。
The @Transactional annotation on a method within the class overrides the default transaction semantics given by the
class annotation (if present). You can annotate any method, regardless of visibility.
with the class annotation (如果存在)。您可以注解任何方法,无论其可见性如何。
To weave your applications with the AnnotationTransactionAspect, you must either build your application with AspectJ (
see the AspectJ Development Guide) or use load-time
weaving.
See Load-time weaving with AspectJ in the Spring Framework
for a discussion of load-time weaving with AspectJ.
要将您的应用程序与 AnnotationTransactionAspect 编织在一起,您必须使用 AspectJ 构建您的应用程序(请参阅 AspectJ
开发指南)或使用加载时编织。有关使用 AspectJ 的加载时编织的讨论,请参阅 Spring 框架中的“使用 AspectJ 进行加载时编织”。
1.5. 程序化事务管理
The Spring Framework provides two means of programmatic transaction management, by using:
Spring 框架提供了两种程序化事务管理的方式,通过使用:
The TransactionTemplate or TransactionalOperator.
TransactionTemplate 或 TransactionalOperator 。
A TransactionManager implementation directly.
直接实现一个 TransactionManager 。
The Spring team generally recommends the TransactionTemplate for programmatic transaction management in imperative
flows and TransactionalOperator for reactive code. The second approach is similar to using the JTA UserTransaction
API, although exception handling is less cumbersome.
Spring 团队通常推荐在命令式流程中使用 TransactionTemplate 进行程序化事务管理,在响应式代码中使用
TransactionalOperator 。第二种方法类似于使用 JTA UserTransaction API,尽管异常处理不那么繁琐。
TransactionTemplate 1.5.1. 使用TransactionTemplateThe TransactionTemplate adopts the same approach as other Spring templates, such as the JdbcTemplate. It uses a
callback approach (to free application code from having to do the boilerplate acquisition and release transactional
resources) and results in code that is intention driven, in that your code focuses solely on what you want to do.
TransactionTemplate 采用与其他 Spring 模板相同的做法,例如 JdbcTemplate
。它使用回调方法(以使应用程序代码从必须执行样板式的获取和释放事务性资源中解放出来),从而产生以意图驱动的代码,即您的代码仅关注您想要做的事情。
As the examples that follow show, using the TransactionTemplate absolutely couples you to Spring’s transaction
infrastructure and APIs. Whether or not programmatic transaction management is suitable for your development needs is a
decision that you have to make yourself.
如以下示例所示,使用 TransactionTemplate 绝对地将您绑定到 Spring 的事务基础设施和 API。是否程序化事务管理适合您的开发需求,这是您必须自己做出的决定。
Application code that must run in a transactional context and that explicitly uses the TransactionTemplate resembles
the next example. You, as an application developer, can write a TransactionCallback implementation (typically
expressed as an anonymous inner class) that contains the code that you need to run in the context of a transaction. You
can then pass an instance of your custom TransactionCallback to the execute(..) method exposed on the
TransactionTemplate. The following example shows how to do so:
应用程序代码必须在事务上下文中运行,并且明确使用 TransactionTemplate 的,类似于下一个示例。作为应用程序开发者,您可以编写一个
TransactionCallback 实现(通常表示为匿名内部类),其中包含您需要在事务上下文中运行的代码。然后,您可以将您自定义的
TransactionCallback 实例传递给在 TransactionTemplate 上公开的 execute(..) 方法。以下示例展示了如何做到这一点:
If there is no return value, you can use the convenient TransactionCallbackWithoutResult class with an anonymous
class, as follows:
如果没有返回值,您可以使用方便的 TransactionCallbackWithoutResult 类与匿名类一起使用,如下所示:
Code within the callback can roll the transaction back by calling the setRollbackOnly() method on the supplied
TransactionStatus object, as follows:
回调函数中的代码可以通过在提供的 TransactionStatus 对象上调用 setRollbackOnly() 方法来回滚事务,如下所示:
指定事务设置
You can specify transaction settings (such as the propagation mode, the isolation level, the timeout, and so forth) on
the TransactionTemplate either programmatically or in configuration. By default, TransactionTemplate instances have
the default transactional settings. The following example shows the
programmatic customization of the transactional settings for a specific TransactionTemplate:
a 您可以在 TransactionTemplate 上指定事务设置(如传播模式、隔离级别、超时等),既可以通过程序方式也可以通过配置进行。默认情况下,
TransactionTemplate 实例具有默认的事务设置。以下示例展示了针对特定 TransactionTemplate: 事务设置的程序化自定义
The following example defines a TransactionTemplate with some custom transactional settings by using Spring XML
configuration:
以下示例通过使用 Spring XML 配置定义了一个具有一些自定义事务设置的 TransactionTemplate :
You can then inject the sharedTransactionTemplate into as many services as are required.
您可以将 sharedTransactionTemplate 注入到所需的所有服务中。
Finally, instances of the TransactionTemplate class are thread-safe, in that instances do not maintain any
conversational state. TransactionTemplate instances do, however, maintain configuration state. So, while a number of
classes may share a single instance of a TransactionTemplate, if a class needs to use a TransactionTemplate with
different settings (for example, a different isolation level), you need to create two distinct TransactionTemplate
instances.
最后, TransactionTemplate 类的实例是线程安全的,因为实例不维护任何对话状态。然而, TransactionTemplate
实例确实维护配置状态。因此,虽然多个类可能共享单个 TransactionTemplate 实例,但如果一个类需要使用具有不同设置(例如,不同的隔离级别)的
TransactionTemplate ,则需要创建两个不同的 TransactionTemplate 实例。
TransactionalOperator 1.5.2. 使用TransactionalOperatorThe TransactionalOperator follows an operator design that is similar to other reactive operators.
TransactionalOperator 遵循与其他反应式操作符类似的操作员设计。
It uses a callback approach (to free application code from having to do the boilerplate acquisition and release
transactional resources) and results in code that is intention driven, in that your code focuses solely on what you want
to do.
它使用回调方法(以使应用程序代码从必须执行样板式的获取和释放事务性资源的操作中解放出来),从而生成以意图驱动的代码,即你的代码仅关注你想要做的事情。
As the examples that follow show, using the TransactionalOperator absolutely couples you to Spring’s transaction
infrastructure and APIs. Whether or not programmatic transaction management is suitable for your development needs is a
decision that you have to make yourself.
如以下示例所示,使用 TransactionalOperator 绝对地将您绑定到 Spring 的事务基础设施和 API。是否程序化事务管理适合您的开发需求,这是您必须自己做出的决定。
Application code that must run in a transactional context and that explicitly uses the TransactionalOperator resembles
the next example:
应用程序必须在事务性环境中运行且明确使用 TransactionalOperator 的代码类似于以下示例:
TransactionalOperator can be used in two ways:
TransactionalOperator 可以有两种用法:
Operator-style using Project Reactor types (mono.as(transactionalOperator::transactional))
操作符样式使用 Project Reactor 类型( mono.as(transactionalOperator::transactional) )
Callback-style for every other case (transactionalOperator.execute(TransactionCallback<T>))
回调式处理每个其他情况( transactionalOperator.execute(TransactionCallback<T>) )
Code within the callback can roll the transaction back by calling the setRollbackOnly() method on the supplied
ReactiveTransaction object, as follows:
回调函数中的代码可以通过在提供的 ReactiveTransaction 对象上调用 setRollbackOnly() 方法来回滚事务,如下所示:
In Reactive Streams, a Subscriber can cancel its Subscription and stop its Publisher. Operators in Project
Reactor, as well as in other libraries, such as next(), take(long), timeout(Duration), and others can issue
cancellations. There is no way to know the reason for the cancellation, whether it is due to an error or a simply lack
of interest to consume further. Since version 5.3 cancel signals lead to a roll back.
在响应式流中,一个 Subscriber 可以取消其 Subscription 并停止其 Publisher 。Project Reactor 中的操作符,以及其他库如
next() 、 take(long) 、 timeout(Duration) 等都可以发出取消操作。无法知道取消的原因,无论是由于错误还是简单地缺乏进一步消费的兴趣。自
5.3 版本以来,取消信号会导致回滚。
As a result it is important to consider the operators used downstream from a transaction Publisher. In particular in
the case of a Flux or other multi-value Publisher, the full output must be consumed to allow the transaction to
complete.
因此,考虑交易下游使用的操作符非常重要 Publisher 。特别是在 Flux 或其他多值 Publisher 的情况下,必须消耗完整输出以允许事务完成。
指定事务设置
You can specify transaction settings (such as the propagation mode, the isolation level, the timeout, and so forth) for
the TransactionalOperator. By default, TransactionalOperator instances
have default transactional settings. The following example shows
customization of the transactional settings for a specific TransactionalOperator:
您可以指定事务设置(例如传播模式、隔离级别、超时等)为 TransactionalOperator 。默认情况下, TransactionalOperator
实例具有默认的事务设置。以下示例展示了特定 TransactionalOperator: 事务设置的自定义
TransactionManager 1.5.3. 使用TransactionManagerThe following sections explain programmatic usage of imperative and reactive transaction managers.
以下章节解释了命令式和响应式事务管理器的编程使用方法。
PlatformTransactionManager 使用PlatformTransactionManagerFor imperative transactions, you can use a org.springframework.transaction.PlatformTransactionManager directly to
manage your transaction. To do so, pass the implementation of the PlatformTransactionManager you use to your bean
through a bean reference. Then, by using the TransactionDefinition and TransactionStatus objects, you can initiate
transactions, roll back, and commit. The following example shows how to do so:
对于命令式事务,您可以直接使用 org.springframework.transaction.PlatformTransactionManager 来管理您的交易。为此,通过一个
bean 引用传递您使用的 PlatformTransactionManager 的实现到您的 bean 中。然后,通过使用 TransactionDefinition 和
TransactionStatus 对象,您可以启动事务、回滚和提交。以下示例展示了如何操作:
ReactiveTransactionManager 使用ReactiveTransactionManagerWhen working with reactive transactions, you can use a org.springframework.transaction.ReactiveTransactionManager
directly to manage your transaction. To do so, pass the implementation of the ReactiveTransactionManager you use to
your bean through a bean reference. Then, by using the TransactionDefinition and ReactiveTransaction objects, you
can initiate transactions, roll back, and commit. The following example shows how to do so:
当处理反应式事务时,您可以直接使用 org.springframework.transaction.ReactiveTransactionManager 来管理您的交易。为此,通过一个
bean 引用传递您使用的 ReactiveTransactionManager 的实现到您的 bean 中。然后,通过使用 TransactionDefinition 和
ReactiveTransaction 对象,您可以启动事务、回滚和提交。以下示例展示了如何操作:
1.6. 选择程序式和声明式事务管理
Programmatic transaction management is usually a good idea only if you have a small number of transactional
operations.
程序化事务管理通常只有在您有少量事务操作时才是一个好主意。
For example, if you have a web application that requires transactions only for certain update operations, you may not
want to set up transactional proxies by using Spring or any other technology. In this case, using the
TransactionTemplate may be a good approach. Being able to set the transaction name explicitly is also something that
can be done only by using the programmatic approach to transaction management.
例如,如果您有一个仅对某些更新操作需要事务的 Web 应用程序,您可能不想使用 Spring 或其他技术设置事务代理。在这种情况下,使用
TransactionTemplate 可能是一个不错的选择。能够显式设置事务名称也是只能通过使用程序化事务管理方法才能做到的。
On the other hand, if your application has numerous transactional operations, declarative transaction management is
usually worthwhile. It keeps transaction management out of business logic and is not difficult to configure.
另一方面,如果您的应用程序有大量事务操作,声明式事务管理通常是有价值的。它将事务管理从业务逻辑中分离出来,并且配置起来并不困难。
When using the Spring Framework, rather than EJB CMT, the configuration cost of declarative transaction management is
greatly reduced.
使用 Spring 框架时,与 EJB CMT 相比,声明式事务管理的配置成本大大降低。
1.7. 事务绑定事件
As of Spring 4.2, the listener of an event can be bound to a phase of the transaction. The typical example is to handle
the event when the transaction has completed successfully.
截至 Spring 4.2 版本,事件监听器可以绑定到事务的某个阶段。典型例子是在事务成功完成后处理该事件。
Doing so lets events be used with more flexibility when the outcome of the current transaction actually matters to the
listener.
这样做可以让事件在当前事务的结果对听众真正重要时,以更灵活的方式被使用。
You can register a regular event listener by using the @EventListener annotation. If you need to bind it to the
transaction, use @TransactionalEventListener. When you do so, the listener is bound to the commit phase of the
transaction by default.
您可以通过使用 @EventListener 注解来注册一个常规事件监听器。如果您需要将其绑定到事务,请使用
@TransactionalEventListener 。这样做时,监听器默认绑定到事务的提交阶段。
The next example shows this concept. Assume that a component publishes an order-created event and that we want to define
a listener that should only handle that event once the transaction in which it has been published has committed
successfully.
下一个示例展示了这个概念。假设一个组件发布了一个订单创建事件,并且我们想要定义一个监听器,该监听器只在该事件所发布的交易成功提交后处理该事件。
The following example sets up such an event listener:
以下示例设置了一个此类事件监听器:
The @TransactionalEventListener annotation exposes a phase attribute that lets you customize the phase of the
transaction to which the listener should be bound. The valid phases are BEFORE_COMMIT, AFTER_COMMIT (default),
AFTER_ROLLBACK, as well as AFTER_COMPLETION which aggregates the transaction completion (be it a commit or a
rollback).
@TransactionalEventListener 注解公开了一个 phase 属性,允许您自定义监听器应绑定的事务阶段。有效阶段包括
BEFORE_COMMIT , AFTER_COMMIT (默认), AFTER_ROLLBACK ,以及 AFTER_COMPLETION ,它聚合事务完成(无论是提交还是回滚)。
If no transaction is running, the listener is not invoked at all, since we cannot honor the required semantics. You can,
however, override that behavior by setting the fallbackExecution attribute of the annotation to true.
如果没有正在进行的交易,监听器根本不会被调用,因为我们无法遵守所需的语义。然而,您可以通过将注解的 fallbackExecution 属性设置为
true 来覆盖这种行为。
@TransactionalEventListener only works with thread-bound transactions managed by PlatformTransactionManager. A
reactive transaction managed by ReactiveTransactionManager uses the Reactor context instead of thread-local
attributes, so from the perspective of an event listener, there is no compatible active transaction that it can
participate in.
@TransactionalEventListener 仅与由 PlatformTransactionManager 管理的线程绑定事务一起使用。由
ReactiveTransactionManager 管理的响应式事务使用 Reactor 上下文而不是线程局部属性,因此从事件监听器的角度来看,没有兼容的活跃事务可以参与。
1.8. 应用服务器特定集成
Spring’s transaction abstraction is generally application server-agnostic. Additionally, Spring’s
JtaTransactionManager class (which can optionally perform a JNDI lookup for the JTA UserTransaction and
TransactionManager objects) autodetects the location for the latter object, which varies by application server. Having
access to the JTA TransactionManager allows for enhanced transaction semantics — in particular, supporting transaction
suspension. See the
JtaTransactionManager
javadoc for details.
Spring 的事务抽象通常与应用服务器无关。此外,Spring 的 JtaTransactionManager 类(可以可选地执行 JNDI 查找 JTA
UserTransaction 和 TransactionManager 对象)自动检测后者的位置,该位置因应用服务器而异。访问 JTA TransactionManager
允许增强事务语义——特别是支持事务挂起。请参阅 JtaTransactionManager javadoc 以获取详细信息。
Spring’s JtaTransactionManager is the standard choice to run on Java EE application servers and is known to work on
all common servers. Advanced functionality, such as transaction suspension, works on many servers as well (including
GlassFish, JBoss and Geronimo) without any special configuration required.
Spring 的 JtaTransactionManager 是 Java EE 应用服务器的标准选择,并且已知在所有常见服务器上都能运行。高级功能,如事务挂起,在许多服务器上也能运行(包括
GlassFish、JBoss 和 Geronimo),无需任何特殊配置。
However, for fully supported transaction suspension and further advanced integration, Spring includes special adapters
for WebLogic Server and WebSphere. These adapters are discussed in the following sections.
然而,为了完全支持的交易挂起和进一步的深度集成,Spring 包括了针对 WebLogic Server 和 WebSphere 的特殊适配器。这些适配器将在以下章节中讨论。
For standard scenarios, including WebLogic Server and WebSphere, consider using the convenient
<tx:jta-transaction-manager/> configuration element. When configured, this element automatically detects the
underlying server and chooses the best transaction manager available for the platform.
对于标准场景,包括 WebLogic Server 和 WebSphere,建议使用方便的 <tx:jta-transaction-manager/>
配置元素。配置后,此元素将自动检测底层服务器并选择该平台可用的最佳事务管理器。
This means that you need not explicitly configure server-specific adapter classes (as discussed in the following
sections). Rather, they are chosen automatically, with the standard JtaTransactionManager as the default fallback.
这意味着您无需显式配置特定服务器的适配器类(如下文所述章节中讨论的)。相反,它们会自动选择,标准 JtaTransactionManager
作为默认回退。
On WebSphere 6.1.0.9 and above, the recommended Spring JTA transaction manager to use is
WebSphereUowTransactionManager. This special adapter uses IBM’s UOWManager API, which is available in WebSphere
Application Server 6.1.0.9 and later. With this adapter, Spring-driven transaction suspension (suspend and resume as
initiated by PROPAGATION_REQUIRES_NEW) is officially supported by IBM.
在 WebSphere 6.1.0.9 及以上版本中,建议使用的 Spring JTA 事务管理器是 WebSphereUowTransactionManager 。这个特殊适配器使用
IBM 的 UOWManager API,该 API 在 WebSphere Application Server 6.1.0.9 及以后的版本中可用。使用此适配器,Spring 驱动的交易挂起(由
PROPAGATION_REQUIRES_NEW 发起的挂起和恢复)得到 IBM 的官方支持。
On WebLogic Server 9.0 or above, you would typically use the WebLogicJtaTransactionManager instead of the stock
JtaTransactionManager class. This special WebLogic-specific subclass of the normal JtaTransactionManager supports
the full power of Spring’s transaction definitions in a WebLogic-managed transaction environment, beyond standard JTA
semantics. Features include transaction names, per-transaction isolation levels, and proper resuming of transactions in
all cases.
在 WebLogic Server 9.0 及以上版本中,您通常会使用 WebLogicJtaTransactionManager 而不是库存的 JtaTransactionManager
类。这个特殊的 WebLogic 特定子类支持在 WebLogic 管理的交易环境中使用 Spring 的事务定义的全部功能,超越了标准的 JTA
语义。功能包括事务名称、每个事务的隔离级别以及在所有情况下正确恢复事务。
1.9. 常见问题解决方案
This section describes solutions to some common problems.
本节描述了一些常见问题的解决方案。
DataSource
1.9.1. 为特定事务使用错误的交易管理器
Use the correct PlatformTransactionManager implementation based on your choice of transactional technologies and
requirements. Used properly, the Spring Framework merely provides a straightforward and portable abstraction. If you use
global transactions, you must use the org.springframework.transaction.jta.JtaTransactionManager class (or
an application server-specific subclass of it) for all your transactional
operations. Otherwise, the transaction infrastructure tries to perform local transactions on such resources as container
DataSource instances. Such local transactions do not make sense, and a good application server treats them as
errors.
根据您选择的交易技术和要求,使用正确的 PlatformTransactionManager 实现。如果使用全局事务,您必须对所有事务操作使用
org.springframework.transaction.jta.JtaTransactionManager 类(或其特定于应用服务器的子类)。否则,事务基础设施会尝试在容器
DataSource 实例等资源上执行本地事务。这种本地事务没有意义,一个好的应用服务器会将它们视为错误。
For more information about the Spring Framework’s transaction support, see:
有关 Spring 框架事务支持的更多信息,请参阅:
Distributed transactions in Spring, with and without XA
is a JavaWorld presentation in which Spring’s David Syer guides you through seven patterns for distributed
transactions in Spring applications, three of them with XA and four without.
Spring 中的分布式事务,带 XA 和不带 XA,是 Spring 的 David Syer 在 JavaWorld 上的一个演讲,其中他为您介绍了 Spring
应用程序中分布式事务的七种模式,其中三种带有 XA,四种不带。
Java Transaction Design Strategies is a book available
from InfoQ that provides a well-paced introduction to transactions in Java. It also includes
side-by-side examples of how to configure and use transactions with both the Spring Framework and EJB3.
《Java 事务设计策略》是 InfoQ 提供的一本书,它提供了对 Java 事务的循序渐进的介绍。它还包括了如何配置和使用 Spring 框架和
EJB3 进行事务处理的并排示例。