Browse Source

Explicit notes on isolation level handling in participating transactions

Issue: SPR-16463

(cherry picked from commit 0ac117f)
pull/1723/head
Juergen Hoeller 8 years ago
parent
commit
cc77b4b995
  1. 33
      spring-tx/src/main/java/org/springframework/transaction/TransactionDefinition.java
  2. 16
      spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java
  3. 6
      spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java
  4. 45
      spring-tx/src/main/java/org/springframework/transaction/support/DefaultTransactionDefinition.java

33
spring-tx/src/main/java/org/springframework/transaction/TransactionDefinition.java

@ -203,21 +203,29 @@ public interface TransactionDefinition { @@ -203,21 +203,29 @@ public interface TransactionDefinition {
/**
* Return the isolation level.
* <p>Must return one of the {@code ISOLATION_XXX} constants
* defined on {@link TransactionDefinition this interface}.
* <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
* or {@link #PROPAGATION_REQUIRES_NEW}.
* <p>Must return one of the {@code ISOLATION_XXX} constants defined on
* {@link TransactionDefinition this interface}. Those constants are designed
* to match the values of the same constants on {@link java.sql.Connection}.
* <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
* <p>Note that a transaction manager that does not support custom isolation levels
* will throw an exception when given any other level than {@link #ISOLATION_DEFAULT}.
* @return the isolation level
* @see #ISOLATION_DEFAULT
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
*/
int getIsolationLevel();
/**
* Return the transaction timeout.
* <p>Must return a number of seconds, or {@link #TIMEOUT_DEFAULT}.
* <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
* or {@link #PROPAGATION_REQUIRES_NEW}.
* <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions.
* <p>Note that a transaction manager that does not support timeouts will throw
* an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
* @return the transaction timeout
@ -226,13 +234,12 @@ public interface TransactionDefinition { @@ -226,13 +234,12 @@ public interface TransactionDefinition {
/**
* Return whether to optimize as a read-only transaction.
* <p>The read-only flag applies to any transaction context, whether
* backed by an actual resource transaction
* ({@link #PROPAGATION_REQUIRED}/{@link #PROPAGATION_REQUIRES_NEW}) or
* operating non-transactionally at the resource level
* ({@link #PROPAGATION_SUPPORTS}). In the latter case, the flag will
* only apply to managed resources within the application, such as a
* Hibernate {@code Session}.
* <p>The read-only flag applies to any transaction context, whether backed
* by an actual resource transaction ({@link #PROPAGATION_REQUIRED}/
* {@link #PROPAGATION_REQUIRES_NEW}) or operating non-transactionally at
* the resource level ({@link #PROPAGATION_SUPPORTS}). In the latter case,
* the flag will only apply to managed resources within the application,
* such as a Hibernate {@code Session}.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will

16
spring-tx/src/main/java/org/springframework/transaction/annotation/Transactional.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -86,19 +86,30 @@ public @interface Transactional { @@ -86,19 +86,30 @@ public @interface Transactional {
/**
* The transaction isolation level.
* <p>Defaults to {@link Isolation#DEFAULT}.
* <p>Exclusively designed for use with {@link Propagation#REQUIRED} or
* {@link Propagation#REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setValidateExistingTransaction
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction.
* <p>Defaults to the default timeout of the underlying transaction system.
* <p>Exclusively designed for use with {@link Propagation#REQUIRED} or
* {@link Propagation#REQUIRES_NEW} since it only applies to newly started
* transactions.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* {@code true} if the transaction is read-only.
* A boolean flag that can be set to {@code true} if the transaction is
* effectively read-only, allowing for corresponding optimizations at runtime.
* <p>Defaults to {@code false}.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
@ -106,6 +117,7 @@ public @interface Transactional { @@ -106,6 +117,7 @@ public @interface Transactional {
* <i>not</i> throw an exception when asked for a read-only transaction
* but rather silently ignore the hint.
* @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
*/
boolean readOnly() default false;

6
spring-tx/src/main/java/org/springframework/transaction/support/AbstractPlatformTransactionManager.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -214,6 +214,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran @@ -214,6 +214,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* <p>Default is "false", leniently ignoring inner transaction settings,
* simply overriding them with the outer transaction's characteristics.
* Switch this flag to "true" in order to enforce strict validation.
* @since 2.5.1
*/
public final void setValidateExistingTransaction(boolean validateExistingTransaction) {
this.validateExistingTransaction = validateExistingTransaction;
@ -222,6 +223,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran @@ -222,6 +223,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
/**
* Return whether existing transactions should be validated before participating
* in them.
* @since 2.5.1
*/
public final boolean isValidateExistingTransaction() {
return this.validateExistingTransaction;
@ -284,6 +286,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran @@ -284,6 +286,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
* boundary. This allows, for example, to continue unit tests even after an
* operation failed and the transaction will never be completed. All transaction
* managers will only fail earlier if this flag has explicitly been set to "true".
* @since 2.0
* @see org.springframework.transaction.UnexpectedRollbackException
*/
public final void setFailEarlyOnGlobalRollbackOnly(boolean failEarlyOnGlobalRollbackOnly) {
@ -293,6 +296,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran @@ -293,6 +296,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
/**
* Return whether to fail early in case of the transaction being globally marked
* as rollback-only.
* @since 2.0
*/
public final boolean isFailEarlyOnGlobalRollbackOnly() {
return this.failEarlyOnGlobalRollbackOnly;

45
spring-tx/src/main/java/org/springframework/transaction/support/DefaultTransactionDefinition.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -108,7 +108,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -108,7 +108,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
* Set the propagation behavior by the name of the corresponding constant in
* TransactionDefinition, e.g. "PROPAGATION_REQUIRED".
* @param constantName name of the constant
* @exception IllegalArgumentException if the supplied value is not resolvable
* @throws IllegalArgumentException if the supplied value is not resolvable
* to one of the {@code PROPAGATION_} constants or is {@code null}
* @see #setPropagationBehavior
* @see #PROPAGATION_REQUIRED
@ -123,8 +123,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -123,8 +123,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
/**
* Set the propagation behavior. Must be one of the propagation constants
* in the TransactionDefinition interface. Default is PROPAGATION_REQUIRED.
* @exception IllegalArgumentException if the supplied value is not
* one of the {@code PROPAGATION_} constants
* <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
* <p>Note that a transaction manager that does not support custom isolation levels
* will throw an exception when given any other level than {@link #ISOLATION_DEFAULT}.
* @throws IllegalArgumentException if the supplied value is not one of the
* {@code PROPAGATION_} constants
* @see #PROPAGATION_REQUIRED
*/
public final void setPropagationBehavior(int propagationBehavior) {
@ -143,7 +151,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -143,7 +151,7 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
* Set the isolation level by the name of the corresponding constant in
* TransactionDefinition, e.g. "ISOLATION_DEFAULT".
* @param constantName name of the constant
* @exception IllegalArgumentException if the supplied value is not resolvable
* @throws IllegalArgumentException if the supplied value is not resolvable
* to one of the {@code ISOLATION_} constants or is {@code null}
* @see #setIsolationLevel
* @see #ISOLATION_DEFAULT
@ -158,8 +166,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -158,8 +166,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
/**
* Set the isolation level. Must be one of the isolation constants
* in the TransactionDefinition interface. Default is ISOLATION_DEFAULT.
* @exception IllegalArgumentException if the supplied value is not
* one of the {@code ISOLATION_} constants
* <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions. Consider switching the "validateExistingTransactions" flag to
* "true" on your transaction manager if you'd like isolation level declarations
* to get rejected when participating in an existing transaction with a different
* isolation level.
* <p>Note that a transaction manager that does not support custom isolation levels
* will throw an exception when given any other level than {@link #ISOLATION_DEFAULT}.
* @throws IllegalArgumentException if the supplied value is not one of the
* {@code ISOLATION_} constants
* @see #ISOLATION_DEFAULT
*/
public final void setIsolationLevel(int isolationLevel) {
@ -177,6 +193,11 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -177,6 +193,11 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
/**
* Set the timeout to apply, as number of seconds.
* Default is TIMEOUT_DEFAULT (-1).
* <p>Exclusively designed for use with {@link #PROPAGATION_REQUIRED} or
* {@link #PROPAGATION_REQUIRES_NEW} since it only applies to newly started
* transactions.
* <p>Note that a transaction manager that does not support timeouts will throw
* an exception when given any other timeout than {@link #TIMEOUT_DEFAULT}.
* @see #TIMEOUT_DEFAULT
*/
public final void setTimeout(int timeout) {
@ -194,6 +215,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri @@ -194,6 +215,16 @@ public class DefaultTransactionDefinition implements TransactionDefinition, Seri
/**
* Set whether to optimize as read-only transaction.
* Default is "false".
* <p>The read-only flag applies to any transaction context, whether backed
* by an actual resource transaction ({@link #PROPAGATION_REQUIRED}/
* {@link #PROPAGATION_REQUIRES_NEW}) or operating non-transactionally at
* the resource level ({@link #PROPAGATION_SUPPORTS}). In the latter case,
* the flag will only apply to managed resources within the application,
* such as a Hibernate {@code Session}.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* <i>not</i> throw an exception when asked for a read-only transaction.
*/
public final void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;

Loading…
Cancel
Save