From f7898951bd0955023667c43088567e640f242972 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 5 Mar 2018 13:40:24 +0100 Subject: [PATCH] Correct description for class-level @Transactional with AspectJ Includes isolation level clarifications. Issue: SPR-16552 Issue: SPR-16463 --- src/asciidoc/data-access.adoc | 75 +++++++++++++++++------------------ 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/src/asciidoc/data-access.adoc b/src/asciidoc/data-access.adoc index 257189ef9e..73fea98cc2 100644 --- a/src/asciidoc/data-access.adoc +++ b/src/asciidoc/data-access.adoc @@ -165,8 +165,7 @@ strategy__. A transaction strategy is defined by the ---- public interface PlatformTransactionManager { - TransactionStatus getTransaction( - TransactionDefinition definition) throws TransactionException; + TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; @@ -200,9 +199,6 @@ execution. The `TransactionDefinition` interface specifies: -* __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? * __Propagation__: Typically, all code executed within a transaction scope will run in that transaction. However, you have the option of specifying the behavior in the event that a transactional method is executed when a transaction context already exists. For @@ -210,6 +206,9 @@ The `TransactionDefinition` interface specifies: the existing transaction can be suspended and a new transaction created. __Spring offers all of the transaction propagation options familiar from EJB CMT__. To read about the semantics of transaction propagation in Spring, see <>. +* __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 rolled back automatically by the underlying transaction infrastructure. * __Read-only status__: A read-only transaction can be used when your code reads but @@ -837,7 +836,7 @@ unhandled `InstrumentNotFoundException`. ---- -When the Spring Framework's transaction infrastructure catches an exception and is +When the Spring Framework's transaction infrastructure catches an exception and it consults configured rollback rules to determine whether to mark the transaction for rollback, the __strongest__ matching rule wins. So in the case of the following configuration, any exception other than an `InstrumentNotFoundException` results in a @@ -1028,17 +1027,17 @@ that are nested within `` and `` tags are summarized | `isolation` | No | DEFAULT -| Transaction isolation level. +| Transaction isolation level. Only applicable to propagation REQUIRED or REQUIRES_NEW. | `timeout` | No | -1 -| Transaction timeout value (in seconds). +| Transaction timeout (seconds). Only applicable to propagation REQUIRED or REQUIRES_NEW. | `read-only` | No | false -| Is this transaction read-only? +| Read/write vs. read-only transaction. Only applicable to REQUIRED or REQUIRES_NEW. | `rollback-for` | No @@ -1162,7 +1161,6 @@ transactional behavior. [TIP] ==== - Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the `@Transactional` annotation, as opposed to annotating interfaces. You certainly can place the `@Transactional` annotation on an interface (or an interface @@ -1308,7 +1306,7 @@ annotation are summarized in the following table: | <> | String -| Optional qualifier specifying the transaction manager to be used. +| Optional qualifier specifying the transaction manager to be used. | <> | enum: `Propagation` @@ -1316,15 +1314,15 @@ annotation are summarized in the following table: | `isolation` | enum: `Isolation` -| Optional isolation level. - -| `readOnly` -| boolean -| Read/write vs. read-only transaction +| Optional isolation level. Only applicable to propagation REQUIRED or REQUIRES_NEW. | `timeout` | int (in seconds granularity) -| Transaction timeout. +| Optional transaction timeout. Only applicable to propagation REQUIRED or REQUIRES_NEW. + +| `readOnly` +| boolean +| Read/write vs. read-only transaction. Only applicable to REQUIRED or REQUIRES_NEW. | `rollbackFor` | Array of `Class` objects, which must be derived from `Throwable.` @@ -1461,8 +1459,8 @@ PROPAGATION_REQUIRED 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. Of -course, in case of standard `PROPAGATION_REQUIRED` behavior, all these scopes will be +transaction scope being logically independent from the inner transaction scope. +Of course, in case of standard `PROPAGATION_REQUIRED` behavior, all these scopes will be 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 (as you would expect it to). @@ -1484,11 +1482,14 @@ image::images/tx_prop_requires_new.png[width=400] PROPAGATION_REQUIRES_NEW -`PROPAGATION_REQUIRES_NEW`, in contrast to `PROPAGATION_REQUIRED`, uses a __completely__ -independent transaction for each affected transaction scope. In that case, the -underlying physical transactions are different and hence can commit or roll back +`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. 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. +status, and with an inner transaction's locks released immediately after its completion. +Such an independent inner transaction may also declare its own isolation level, timeout +and read-only settings, never inheriting an outer transaction's characteristics. [[tx-propagation-nested]] ===== Nested @@ -1585,10 +1586,10 @@ is controlled through the `Ordered` interface. For full details on advice orderi - + - + @@ -1641,14 +1642,14 @@ declarative approach. - __ + - + @@ -1721,7 +1722,7 @@ follows Java's rule that annotations on interfaces are __not inherited__. ==== The `@Transactional` annotation on a class specifies the default transaction semantics -for the execution of any method in the class. +for the execution of any public method in the class. The `@Transactional` annotation on a method within the class overrides the default transaction semantics given by the class annotation (if present). Any method may be @@ -1782,7 +1783,6 @@ a transaction. You then pass an instance of your custom `TransactionCallback` to // use constructor-injection to supply the PlatformTransactionManager public SimpleService(PlatformTransactionManager transactionManager) { - Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); this.transactionTemplate = new TransactionTemplate(transactionManager); } @@ -1849,7 +1849,6 @@ a specific `TransactionTemplate:` private final TransactionTemplate transactionTemplate; public SimpleService(PlatformTransactionManager transactionManager) { - Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); this.transactionTemplate = new TransactionTemplate(transactionManager); // the transaction settings can be set here explicitly if so desired @@ -1943,9 +1942,9 @@ Registering a regular event listener is done via the `@EventListener` annotation to bind it to the transaction use `@TransactionalEventListener`. When you do so, the listener will be bound to the commit phase of the transaction by default. -Let's take an example to illustrate this concept. Assume that a component publish an order +Let's take an example to illustrate this concept. Assume that a component publishes an order created event and we want to define a listener that should only handle that event once the -transaction in which it has been published as committed successfully: +transaction in which it has been published has committed successfully: [source,java,indent=0] [subs="verbatim,quotes"] @@ -1960,8 +1959,8 @@ transaction in which it has been published as committed successfully: } ---- -The `TransactionalEventListener` annotation exposes a `phase` attribute that allows to customize -to which phase of the transaction the listener should be bound to. The valid phases are `BEFORE_COMMIT`, +The `TransactionalEventListener` annotation exposes a `phase` attribute that allows us to customize +which phase of the transaction the listener should be bound to. The valid phases are `BEFORE_COMMIT`, `AFTER_COMMIT` (default), `AFTER_ROLLBACK` and `AFTER_COMPLETION` that aggregates the transaction completion (be it a commit or a rollback). @@ -2997,10 +2996,10 @@ An `update()` convenience method supports the retrieval of primary keys generate database. This support is part of the JDBC 3.0 standard; see Chapter 13.6 of the specification for details. The method takes a `PreparedStatementCreator` as its first argument, and this is the way the required insert statement is specified. The other -argument is a `KeyHolder`, which contains the generated key on successful return from -the update. There is not a standard single way to create an appropriate -`PreparedStatement` (which explains why the method signature is the way it is). The -following example works on Oracle but may not work on other platforms: +argument is a `KeyHolder`, which contains the generated key on successful return from the +update. There is not a standard single way to create an appropriate `PreparedStatement` +(which explains why the method signature is the way it is). The following example works +on Oracle but may not work on other platforms: [source,java,indent=0] [subs="verbatim,quotes"]