Document that @Transactional does not propagate to new threads

Closes gh-25439
This commit is contained in:
Juergen Hoeller 2020-11-17 14:43:17 +01:00
parent b56dbd2aa8
commit 2ee231dee2
3 changed files with 57 additions and 37 deletions

View File

@ -38,16 +38,25 @@ import org.springframework.transaction.TransactionDefinition;
* {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute} * {@link org.springframework.transaction.interceptor.RuleBasedTransactionAttribute}
* class, and in fact {@link AnnotationTransactionAttributeSource} will directly * class, and in fact {@link AnnotationTransactionAttributeSource} will directly
* convert the data to the latter class, so that Spring's transaction support code * convert the data to the latter class, so that Spring's transaction support code
* does not have to know about annotations. If no rules are relevant to the exception, * does not have to know about annotations. If no custom rollback rules apply,
* it will be treated like * the transaction will roll back on {@link RuntimeException} and {@link Error}
* {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute} * but not on checked exceptions.
* (rolling back on {@link RuntimeException} and {@link Error} but not on checked
* exceptions).
* *
* <p>For specific information about the semantics of this annotation's attributes, * <p>For specific information about the semantics of this annotation's attributes,
* consult the {@link org.springframework.transaction.TransactionDefinition} and * consult the {@link org.springframework.transaction.TransactionDefinition} and
* {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs. * {@link org.springframework.transaction.interceptor.TransactionAttribute} javadocs.
* *
* <p>This annotation commonly works with thread-bound transactions managed by
* {@link org.springframework.transaction.PlatformTransactionManager}, exposing a
* transaction to all data access operations within the current execution thread.
* <b>Note: This does NOT propagate to newly started threads within the method.</b>
*
* <p>Alternatively, this annotation may demarcate a reactive transaction managed
* by {@link org.springframework.transaction.ReactiveTransactionManager} which
* 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.
*
* @author Colin Sampaleanu * @author Colin Sampaleanu
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Sam Brannen * @author Sam Brannen

View File

@ -28,7 +28,7 @@ import org.springframework.lang.Nullable;
/** /**
* TransactionAttribute implementation that works out whether a given exception * TransactionAttribute implementation that works out whether a given exception
* should cause transaction rollback by applying a number of rollback rules, * should cause transaction rollback by applying a number of rollback rules,
* both positive and negative. If no rules are relevant to the exception, it * both positive and negative. If no custom rollback rules apply, this attribute
* behaves like DefaultTransactionAttribute (rolling back on runtime exceptions). * behaves like DefaultTransactionAttribute (rolling back on runtime exceptions).
* *
* <p>{@link TransactionAttributeEditor} creates objects of this class. * <p>{@link TransactionAttributeEditor} creates objects of this class.

View File

@ -566,7 +566,7 @@ abstractions mentioned earlier.
[[transaction-declarative]] [[transaction-declarative]]
=== Declarative transaction management === Declarative Transaction Management
NOTE: Most Spring Framework users choose declarative transaction management. This option has NOTE: 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 the least impact on application code and, hence, is most consistent with the ideals of a
@ -637,7 +637,7 @@ around method invocations.
NOTE: Spring AOP is covered in <<core.adoc#aop, the AOP section>>. NOTE: Spring AOP is covered in <<core.adoc#aop, the AOP section>>.
Spring Frameworks's `TransactionInterceptor` provides transaction management for Spring Framework's `TransactionInterceptor` provides transaction management for
imperative and reactive programming models. The interceptor detects the desired flavor of imperative and reactive programming models. The interceptor detects the desired flavor of
transaction management by inspecting the method return type. Methods returning a reactive 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 type such as `Publisher` or Kotlin `Flow` (or a subtype of those) qualify for reactive
@ -648,6 +648,18 @@ Transaction management flavors impact which transaction manager is required. Imp
transactions require a `PlatformTransactionManager`, while reactive transactions use transactions require a `PlatformTransactionManager`, while reactive transactions use
`ReactiveTransactionManager` implementations. `ReactiveTransactionManager` implementations.
[NOTE]
====
`@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.
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.
====
The following image shows a conceptual view of calling a method on a transactional proxy: The following image shows a conceptual view of calling a method on a transactional proxy:
image::images/tx.png[] image::images/tx.png[]
@ -2844,30 +2856,29 @@ specific to each technology.
Spring provides a convenient translation from technology-specific exceptions, such as Spring provides a convenient translation from technology-specific exceptions, such as
`SQLException` to its own exception class hierarchy, which has `DataAccessException` as `SQLException` to its own exception class hierarchy, which has `DataAccessException` as
the root exception. These exceptions wrap the original exception so that there is never any the root exception. These exceptions wrap the original exception so that there is never
risk that you might lose any information about what might have gone wrong. any risk that you might lose any information about what might have gone wrong.
In addition to JDBC exceptions, Spring can also wrap JPA- and Hibernate-specific exceptions, In addition to JDBC exceptions, Spring can also wrap JPA- and Hibernate-specific exceptions,
converting them to a set of focused runtime exceptions. converting them to a set of focused runtime exceptions. This lets you handle most
This lets you handle most non-recoverable persistence exceptions non-recoverable persistence exceptions in only the appropriate layers, without having
in only the appropriate layers, without having annoying boilerplate annoying boilerplate catch-and-throw blocks and exception declarations in your DAOs.
catch-and-throw blocks and exception declarations in your DAOs. (You can still trap (You can still trap and handle exceptions anywhere you need to though.) As mentioned above,
and handle exceptions anywhere you need to though.) As mentioned above, JDBC JDBC exceptions (including database-specific dialects) are also converted to the same
exceptions (including database-specific dialects) are also converted to the same
hierarchy, meaning that you can perform some operations with JDBC within a consistent hierarchy, meaning that you can perform some operations with JDBC within a consistent
programming model. programming model.
The preceding discussion holds true for the various template classes in Spring's support for various ORM The preceding discussion holds true for the various template classes in Spring's support
frameworks. If you use the interceptor-based classes, the application must care for various ORM frameworks. If you use the interceptor-based classes, the application must
about handling `HibernateExceptions` and `PersistenceExceptions` itself, preferably by care about handling `HibernateExceptions` and `PersistenceExceptions` itself, preferably by
delegating to the `convertHibernateAccessException(..)` or delegating to the `convertHibernateAccessException(..)` or `convertJpaAccessException(..)`
`convertJpaAccessException()` methods, respectively, of `SessionFactoryUtils`. These methods convert the exceptions methods, respectively, of `SessionFactoryUtils`. These methods convert the exceptions
to exceptions that are compatible with the exceptions in the `org.springframework.dao` to exceptions that are compatible with the exceptions in the `org.springframework.dao`
exception hierarchy. As `PersistenceExceptions` are unchecked, they can get exception hierarchy. As `PersistenceExceptions` are unchecked, they can get thrown, too
thrown, too (sacrificing generic DAO abstraction in terms of exceptions, though). (sacrificing generic DAO abstraction in terms of exceptions, though).
The following image shows the exception hierarchy that Spring provides. (Note that the The following image shows the exception hierarchy that Spring provides.
class hierarchy detailed in the image shows only a subset of the entire (Note that the class hierarchy detailed in the image shows only a subset of the entire
`DataAccessException` hierarchy.) `DataAccessException` hierarchy.)
image::images/DataAccessException.png[] image::images/DataAccessException.png[]
@ -4232,14 +4243,14 @@ interface that wraps a single `Connection` that is not closed after each use.
This is not multi-threading capable. This is not multi-threading capable.
If any client code calls `close` on the assumption of a pooled connection (as when using If any client code calls `close` on the assumption of a pooled connection (as when using
persistence tools), you should set the `suppressClose` property to `true`. This setting returns a persistence tools), you should set the `suppressClose` property to `true`. This setting
close-suppressing proxy that wraps the physical connection. Note that you can no longer returns a close-suppressing proxy that wraps the physical connection. Note that you can
cast this to a native Oracle `Connection` or a similar object. no longer cast this to a native Oracle `Connection` or a similar object.
`SingleConnectionDataSource` is primarily a test class. For example, it enables easy testing of code outside an `SingleConnectionDataSource` is primarily a test class. It typically enables easy testing
application server, in conjunction with a simple JNDI environment. In contrast to of code outside an application server, in conjunction with a simple JNDI environment.
`DriverManagerDataSource`, it reuses the same connection all the time, avoiding In contrast to `DriverManagerDataSource`, it reuses the same connection all the time,
excessive creation of physical connections. avoiding excessive creation of physical connections.
@ -8810,8 +8821,8 @@ can do so by using the following `applicationContext.xml`:
---- ----
This application context uses XStream, but we could have used any of the other marshaller This application context uses XStream, but we could have used any of the other marshaller
instances described later in this chapter. Note that, by default, XStream does not require any further instances described later in this chapter. Note that, by default, XStream does not require
configuration, so the bean definition is rather simple. Also note that the any further configuration, so the bean definition is rather simple. Also note that the
`XStreamMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the `XStreamMarshaller` implements both `Marshaller` and `Unmarshaller`, so we can refer to the
`xstreamMarshaller` bean in both the `marshaller` and `unmarshaller` property of the `xstreamMarshaller` bean in both the `marshaller` and `unmarshaller` property of the
application. application.
@ -8829,8 +8840,8 @@ This sample application produces the following `settings.xml` file:
[[oxm-schema-based-config]] [[oxm-schema-based-config]]
=== XML Configuration Namespace === XML Configuration Namespace
You can configure marshallers more concisely by using tags from the OXM namespace. To You can configure marshallers more concisely by using tags from the OXM namespace.
make these tags available, you must first reference the appropriate schema in the To make these tags available, you must first reference the appropriate schema in the
preamble of the XML configuration file. The following example shows how to do so: preamble of the XML configuration file. The following example shows how to do so:
[source,xml,indent=0] [source,xml,indent=0]
@ -9073,7 +9084,7 @@ vulnerabilities do not get invoked.
NOTE: Note that XStream is an XML serialization library, not a data binding library. NOTE: Note that XStream is an XML serialization library, not a data binding library.
Therefore, it has limited namespace support. As a result, it is rather unsuitable for usage Therefore, it has limited namespace support. As a result, it is rather unsuitable for usage
within Web services. within Web Services.