/*
* 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.support;
import java.io.Serializable;
import org.springframework.core.Constants;
import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionDefinition;
Default implementation of the TransactionDefinition
interface, offering bean-style configuration and sensible default values (PROPAGATION_REQUIRED, ISOLATION_DEFAULT, TIMEOUT_DEFAULT, readOnly=false). Base class for both TransactionTemplate
and DefaultTransactionAttribute
.
Author: Juergen Hoeller Since: 08.05.2003
/**
* Default implementation of the {@link TransactionDefinition} interface,
* offering bean-style configuration and sensible default values
* (PROPAGATION_REQUIRED, ISOLATION_DEFAULT, TIMEOUT_DEFAULT, readOnly=false).
*
* <p>Base class for both {@link TransactionTemplate} and
* {@link org.springframework.transaction.interceptor.DefaultTransactionAttribute}.
*
* @author Juergen Hoeller
* @since 08.05.2003
*/
@SuppressWarnings("serial")
public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
Prefix for the propagation constants defined in TransactionDefinition. /** Prefix for the propagation constants defined in TransactionDefinition. */
public static final String PREFIX_PROPAGATION = "PROPAGATION_";
Prefix for the isolation constants defined in TransactionDefinition. /** Prefix for the isolation constants defined in TransactionDefinition. */
public static final String PREFIX_ISOLATION = "ISOLATION_";
Prefix for transaction timeout values in description strings. /** Prefix for transaction timeout values in description strings. */
public static final String PREFIX_TIMEOUT = "timeout_";
Marker for read-only transactions in description strings. /** Marker for read-only transactions in description strings. */
public static final String READ_ONLY_MARKER = "readOnly";
Constants instance for TransactionDefinition. /** Constants instance for TransactionDefinition. */
static final Constants constants = new Constants(TransactionDefinition.class);
private int propagationBehavior = PROPAGATION_REQUIRED;
private int isolationLevel = ISOLATION_DEFAULT;
private int timeout = TIMEOUT_DEFAULT;
private boolean readOnly = false;
@Nullable
private String name;
Create a new DefaultTransactionDefinition, with default settings.
Can be modified through bean property setters.
See Also: - setPropagationBehavior
- setIsolationLevel
- setTimeout
- setReadOnly
- setName
/**
* Create a new DefaultTransactionDefinition, with default settings.
* Can be modified through bean property setters.
* @see #setPropagationBehavior
* @see #setIsolationLevel
* @see #setTimeout
* @see #setReadOnly
* @see #setName
*/
public DefaultTransactionDefinition() {
}
Copy constructor. Definition can be modified through bean property setters.
See Also: - setPropagationBehavior
- setIsolationLevel
- setTimeout
- setReadOnly
- setName
/**
* Copy constructor. Definition can be modified through bean property setters.
* @see #setPropagationBehavior
* @see #setIsolationLevel
* @see #setTimeout
* @see #setReadOnly
* @see #setName
*/
public DefaultTransactionDefinition(TransactionDefinition other) {
this.propagationBehavior = other.getPropagationBehavior();
this.isolationLevel = other.getIsolationLevel();
this.timeout = other.getTimeout();
this.readOnly = other.isReadOnly();
this.name = other.getName();
}
Create a new DefaultTransactionDefinition with the given
propagation behavior. Can be modified through bean property setters.
Params: - propagationBehavior – one of the propagation constants in the
TransactionDefinition interface
See Also:
/**
* Create a new DefaultTransactionDefinition with the given
* propagation behavior. Can be modified through bean property setters.
* @param propagationBehavior one of the propagation constants in the
* TransactionDefinition interface
* @see #setIsolationLevel
* @see #setTimeout
* @see #setReadOnly
*/
public DefaultTransactionDefinition(int propagationBehavior) {
this.propagationBehavior = propagationBehavior;
}
Set the propagation behavior by the name of the corresponding constant in
TransactionDefinition, e.g. "PROPAGATION_REQUIRED".
Params: - constantName – name of the constant
Throws: - IllegalArgumentException – if the supplied value is not resolvable to one of the
PROPAGATION_
constants or is null
See Also:
/**
* Set the propagation behavior by the name of the corresponding constant in
* TransactionDefinition, e.g. "PROPAGATION_REQUIRED".
* @param constantName name of the constant
* @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
*/
public final void setPropagationBehaviorName(String constantName) throws IllegalArgumentException {
if (!constantName.startsWith(PREFIX_PROPAGATION)) {
throw new IllegalArgumentException("Only propagation constants allowed");
}
setPropagationBehavior(constants.asNumber(constantName).intValue());
}
Set the propagation behavior. Must be one of the propagation constants
in the TransactionDefinition interface. Default is PROPAGATION_REQUIRED.
Exclusively designed for use with TransactionDefinition.PROPAGATION_REQUIRED
or TransactionDefinition.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.
Note that a transaction manager that does not support custom isolation levels will throw an exception when given any other level than TransactionDefinition.ISOLATION_DEFAULT
.
Throws: - IllegalArgumentException – if the supplied value is not one of the
PROPAGATION_
constants
See Also:
/**
* Set the propagation behavior. Must be one of the propagation constants
* in the TransactionDefinition interface. Default is PROPAGATION_REQUIRED.
* <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) {
if (!constants.getValues(PREFIX_PROPAGATION).contains(propagationBehavior)) {
throw new IllegalArgumentException("Only values of propagation constants allowed");
}
this.propagationBehavior = propagationBehavior;
}
@Override
public final int getPropagationBehavior() {
return this.propagationBehavior;
}
Set the isolation level by the name of the corresponding constant in
TransactionDefinition, e.g. "ISOLATION_DEFAULT".
Params: - constantName – name of the constant
Throws: - IllegalArgumentException – if the supplied value is not resolvable to one of the
ISOLATION_
constants or is null
See Also:
/**
* Set the isolation level by the name of the corresponding constant in
* TransactionDefinition, e.g. "ISOLATION_DEFAULT".
* @param constantName name of the constant
* @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
*/
public final void setIsolationLevelName(String constantName) throws IllegalArgumentException {
if (!constantName.startsWith(PREFIX_ISOLATION)) {
throw new IllegalArgumentException("Only isolation constants allowed");
}
setIsolationLevel(constants.asNumber(constantName).intValue());
}
Set the isolation level. Must be one of the isolation constants
in the TransactionDefinition interface. Default is ISOLATION_DEFAULT.
Exclusively designed for use with TransactionDefinition.PROPAGATION_REQUIRED
or TransactionDefinition.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.
Note that a transaction manager that does not support custom isolation levels will throw an exception when given any other level than TransactionDefinition.ISOLATION_DEFAULT
.
Throws: - IllegalArgumentException – if the supplied value is not one of the
ISOLATION_
constants
See Also:
/**
* Set the isolation level. Must be one of the isolation constants
* in the TransactionDefinition interface. Default is 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.
* <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) {
if (!constants.getValues(PREFIX_ISOLATION).contains(isolationLevel)) {
throw new IllegalArgumentException("Only values of isolation constants allowed");
}
this.isolationLevel = isolationLevel;
}
@Override
public final int getIsolationLevel() {
return this.isolationLevel;
}
Set the timeout to apply, as number of seconds.
Default is TIMEOUT_DEFAULT (-1).
Exclusively designed for use with TransactionDefinition.PROPAGATION_REQUIRED
or TransactionDefinition.PROPAGATION_REQUIRES_NEW
since it only applies to newly started transactions.
Note that a transaction manager that does not support timeouts will throw an exception when given any other timeout than TransactionDefinition.TIMEOUT_DEFAULT
.
See Also:
/**
* 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) {
if (timeout < TIMEOUT_DEFAULT) {
throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT");
}
this.timeout = timeout;
}
@Override
public final int getTimeout() {
return this.timeout;
}
Set whether to optimize as read-only transaction.
Default is "false".
The read-only flag applies to any transaction context, whether backed by an actual resource transaction (TransactionDefinition.PROPAGATION_REQUIRED
/ TransactionDefinition.PROPAGATION_REQUIRES_NEW
) or operating non-transactionally at the resource level (TransactionDefinition.PROPAGATION_SUPPORTS
). In the latter case, the flag will only apply to managed resources within the application, such as a Hibernate Session
.
This just serves as a hint for the actual transaction subsystem;
it will not necessarily cause failure of write access attempts.
A transaction manager which cannot interpret the read-only hint will
not throw an exception when asked for a read-only transaction.
/**
* 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;
}
@Override
public final boolean isReadOnly() {
return this.readOnly;
}
Set the name of this transaction. Default is none.
This will be used as transaction name to be shown in a
transaction monitor, if applicable (for example, WebLogic's).
/**
* Set the name of this transaction. Default is none.
* <p>This will be used as transaction name to be shown in a
* transaction monitor, if applicable (for example, WebLogic's).
*/
public final void setName(String name) {
this.name = name;
}
@Override
@Nullable
public final String getName() {
return this.name;
}
This implementation compares the toString()
results. See Also:
/**
* This implementation compares the {@code toString()} results.
* @see #toString()
*/
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (other instanceof TransactionDefinition && toString().equals(other.toString())));
}
This implementation returns toString()
's hash code. See Also:
/**
* This implementation returns {@code toString()}'s hash code.
* @see #toString()
*/
@Override
public int hashCode() {
return toString().hashCode();
}
Return an identifying description for this transaction definition.
The format matches the one used by TransactionAttributeEditor
, to be able to feed toString
results into bean properties of type TransactionAttribute
.
Has to be overridden in subclasses for correct equals
and hashCode
behavior. Alternatively, equals
and hashCode
can be overridden themselves.
See Also:
/**
* Return an identifying description for this transaction definition.
* <p>The format matches the one used by
* {@link org.springframework.transaction.interceptor.TransactionAttributeEditor},
* to be able to feed {@code toString} results into bean properties of type
* {@link org.springframework.transaction.interceptor.TransactionAttribute}.
* <p>Has to be overridden in subclasses for correct {@code equals}
* and {@code hashCode} behavior. Alternatively, {@link #equals}
* and {@link #hashCode} can be overridden themselves.
* @see #getDefinitionDescription()
* @see org.springframework.transaction.interceptor.TransactionAttributeEditor
*/
@Override
public String toString() {
return getDefinitionDescription().toString();
}
Return an identifying description for this transaction definition.
Available to subclasses, for inclusion in their toString()
result.
/**
* Return an identifying description for this transaction definition.
* <p>Available to subclasses, for inclusion in their {@code toString()} result.
*/
protected final StringBuilder getDefinitionDescription() {
StringBuilder result = new StringBuilder();
result.append(constants.toCode(this.propagationBehavior, PREFIX_PROPAGATION));
result.append(',');
result.append(constants.toCode(this.isolationLevel, PREFIX_ISOLATION));
if (this.timeout != TIMEOUT_DEFAULT) {
result.append(',');
result.append(PREFIX_TIMEOUT).append(this.timeout);
}
if (this.readOnly) {
result.append(',');
result.append(READ_ONLY_MARKER);
}
return result;
}
}