Spring事务策略,有一个接口"PlatformTransactionManager"。
编程式有两种方式:使用TransactionTemplate 直接使用PlatformTransactionManager。
1. 使用TransactionTemplate
相关源码:
<1> TransactionTemplate.java 源码
<2> 有参构造方法需要的两个类(接口)
PlatformTransactionManager.java源码:
TransactionDefinition.java源码:
TransactionCallback.java 源码
实际应用。
<1> hibernate.cfg.xml文件中spring事务配置
<2> TransactionCallback.java接口实现类
2. 直接使用PlatformTransactionManager
BankAccountDaoImpl.Java
/*
* Copyright 2002-2008 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
*
* http://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;
/**
* This is the central interface in Spring's transaction infrastructure.
* Applications can use this directly, but it is not primarily meant as API:
* Typically, applications will work with either TransactionTemplate or
* declarative transaction demarcation through AOP.
*
* <p>For implementors, it is recommended to derive from the provided
* {@link org.springframework.transaction.support.AbstractPlatformTransactionManager}
* class, which pre-implements the defined propagation behavior and takes care
* of transaction synchronization handling. Subclasses have to implement
* template methods for specific states of the underlying transaction,
* for example: begin, suspend, resume, commit.
*
* <p>The default implementations of this strategy interface are
* {@link org.springframework.transaction.jta.JtaTransactionManager} and
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},
* which can serve as an implementation guide for other transaction strategies.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 16.05.2003
* @see org.springframework.transaction.support.TransactionTemplate
* @see org.springframework.transaction.interceptor.TransactionInterceptor
* @see org.springframework.transaction.interceptor.TransactionProxyFactoryBean
*/
public interface PlatformTransactionManager {
/**
* Return a currently active transaction or create a new one, according to
* the specified propagation behavior.
* <p>Note that parameters like isolation level or timeout will only be applied
* to new transactions, and thus be ignored when participating in active ones.
* <p>Furthermore, not all transaction definition settings will be supported
* by every transaction manager: A proper transaction manager implementation
* should throw an exception when unsupported settings are encountered.
* <p>An exception to the above rule is the read-only flag, which should be
* ignored if no explicit read-only mode is supported. Essentially, the
* read-only flag is just a hint for potential optimization.
* @param definition TransactionDefinition instance (can be <code>null</code> for defaults),
* describing propagation behavior, isolation level, timeout etc.
* @return transaction status object representing the new or current transaction
* @throws TransactionException in case of lookup, creation, or system errors
* @throws IllegalTransactionStateException if the given transaction definition
* cannot be executed (for example, if a currently active transaction is in
* conflict with the specified propagation behavior)
* @see TransactionDefinition#getPropagationBehavior
* @see TransactionDefinition#getIsolationLevel
* @see TransactionDefinition#getTimeout
* @see TransactionDefinition#isReadOnly
*/
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
/**
* Commit the given transaction, with regard to its status. If the transaction
* has been marked rollback-only programmatically, perform a rollback.
* <p>If the transaction wasn't a new one, omit the commit for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after committing the new one.
* <p>Note that when the commit call completes, no matter if normally or
* throwing an exception, the transaction must be fully completed and
* cleaned up. No rollback call should be expected in such a case.
* <p>If this method throws an exception other than a TransactionException,
* then some before-commit error caused the commit attempt to fail. For
* example, an O/R Mapping tool might have tried to flush changes to the
* database right before commit, with the resulting DataAccessException
* causing the transaction to fail. The original exception will be
* propagated to the caller of this commit method in such a case.
* @param status object returned by the <code>getTransaction</code> method
* @throws UnexpectedRollbackException in case of an unexpected rollback
* that the transaction coordinator initiated
* @throws HeuristicCompletionException in case of a transaction failure
* caused by a heuristic decision on the side of the transaction coordinator
* @throws TransactionSystemException in case of commit or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
* @see TransactionStatus#setRollbackOnly
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* Perform a rollback of the given transaction.
* <p>If the transaction wasn't a new one, just set it rollback-only for proper
* participation in the surrounding transaction. If a previous transaction
* has been suspended to be able to create a new one, resume the previous
* transaction after rolling back the new one.
* <p><b>Do not call rollback on a transaction if commit threw an exception.</b>
* The transaction will already have been completed and cleaned up when commit
* returns, even in case of a commit exception. Consequently, a rollback call
* after commit failure will lead to an IllegalTransactionStateException.
* @param status object returned by the <code>getTransaction</code> method
* @throws TransactionSystemException in case of rollback or system errors
* (typically caused by fundamental resource failures)
* @throws IllegalTransactionStateException if the given transaction
* is already completed (that is, committed or rolled back)
*/
void rollback(TransactionStatus status) throws TransactionException;
}
一、编程式
编程式有两种方式:使用TransactionTemplate 直接使用PlatformTransactionManager。
1. 使用TransactionTemplate
相关源码:
<1> TransactionTemplate.java 源码
/*
* Copyright 2002-2007 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
*
* http://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 org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.TransactionSystemException;
/**
* Template class that simplifies programmatic transaction demarcation and
* transaction exception handling.
*
* <p>The central method is {@link #execute}, supporting transactional code that
* implements the {@link TransactionCallback} interface. This template handles
* the transaction lifecycle and possible exceptions such that neither the
* TransactionCallback implementation nor the calling code needs to explicitly
* handle transactions.
*
* <p>Typical usage: Allows for writing low-level data access objects that use
* resources such as JDBC DataSources but are not transaction-aware themselves.
* Instead, they can implicitly participate in transactions handled by higher-level
* application services utilizing this class, making calls to the low-level
* services via an inner-class callback object.
*
* <p>Can be used within a service implementation via direct instantiation with
* a transaction manager reference, or get prepared in an application context
* and passed to services as bean reference. Note: The transaction manager should
* always be configured as bean in the application context: in the first case given
* to the service directly, in the second case given to the prepared template.
*
* <p>Supports setting the propagation behavior and the isolation level by name,
* for convenient configuration in context definitions.
*
* @author Juergen Hoeller
* @since 17.03.2003
* @see #execute
* @see #setTransactionManager
* @see org.springframework.transaction.PlatformTransactionManager
*/
public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
private PlatformTransactionManager transactionManager;
/**
* Construct a new TransactionTemplate for bean usage.
* <p>Note: The PlatformTransactionManager needs to be set before
* any <code>execute</code> calls.
* @see #setTransactionManager
*/
public TransactionTemplate() {
}
/**
* Construct a new TransactionTemplate using the given transaction manager.
* @param transactionManager the transaction management strategy to be used
*/
public TransactionTemplate(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Construct a new TransactionTemplate using the given transaction manager,
* taking its default settings from the given transaction definition.
* @param transactionManager the transaction management strategy to be used
* @param transactionDefinition the transaction definition to copy the
* default settings from. Local properties can still be set to change values.
*/
public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
super(transactionDefinition);
this.transactionManager = transactionManager;
}
/**
* Set the transaction management strategy to be used.
*/
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Return the transaction management strategy to be used.
*/
public PlatformTransactionManager getTransactionManager() {
return this.transactionManager;
}
public void afterPropertiesSet() {
if (this.transactionManager == null) {
throw new IllegalArgumentException("Property 'transactionManager' is required");
}
}
public Object execute(TransactionCallback action) throws TransactionException {
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
TransactionStatus status = this.transactionManager.getTransaction(this);
Object result = null;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// Transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
this.transactionManager.commit(status);
return result;
}
}
/**
* Perform a rollback, handling rollback exceptions properly.
* @param status object representing the transaction
* @param ex the thrown application exception or error
* @throws TransactionException in case of a rollback error
*/
private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
logger.debug("Initiating transaction rollback on application exception", ex);
try {
this.transactionManager.rollback(status);
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
}
}
<2> 有参构造方法需要的两个类(接口)
PlatformTransactionManager.java源码:
TransactionDefinition.java源码:
/*
* Copyright 2002-2006 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
*
* http://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;
import java.sql.Connection;
/**
* Interface that defines Spring-compliant transaction properties.
* Based on the propagation behavior definitions analogous to EJB CMT attributes.
*
* <p>Note that isolation level and timeout settings will not get applied unless
* an actual new transaction gets started. As only {@link #PROPAGATION_REQUIRED},
* {@link #PROPAGATION_REQUIRES_NEW} and {@link #PROPAGATION_NESTED} can cause
* that, it usually doesn't make sense to specify those settings in other cases.
* Furthermore, be aware that not all transaction managers will support those
* advanced features and thus might throw corresponding exceptions when given
* non-default values.
*
* <p>The {@link #isReadOnly() read-only flag} applies to any transaction context,
* whether backed by an actual resource transaction or operating non-transactionally
* at the resource level. In the latter case, the flag will only apply to managed
* resources within the application, such as a Hibernate <code>Session</code>.
*
* @author Juergen Hoeller
* @since 08.05.2003
* @see PlatformTransactionManager#getTransaction(TransactionDefinition)
* @see org.springframework.transaction.support.DefaultTransactionDefinition
* @see org.springframework.transaction.interceptor.TransactionAttribute
*/
public interface TransactionDefinition {
/**
* Support a current transaction; create a new one if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p>This is typically the default setting of a transaction definition,
* and typically defines a transaction synchronization scope.
*/
int PROPAGATION_REQUIRED = 0;
/**
* Support a current transaction; execute non-transactionally if none exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> For transaction managers with transaction synchronization,
* <code>PROPAGATION_SUPPORTS</code> is slightly different from no transaction
* at all, as it defines a transaction scope that synchronization might apply to.
* As a consequence, the same resources (a JDBC <code>Connection</code>, a
* Hibernate <code>Session</code>, etc) will be shared for the entire specified
* scope. Note that the exact behavior depends on the actual synchronization
* configuration of the transaction manager!
* <p>In general, use <code>PROPAGATION_SUPPORTS</code> with care! In particular, do
* not rely on <code>PROPAGATION_REQUIRED</code> or <code>PROPAGATION_REQUIRES_NEW</code>
* <i>within</i> a <code>PROPAGATION_SUPPORTS</code> scope (which may lead to
* synchronization conflicts at runtime). If such nesting is unavoidable, make sure
* to configure your transaction manager appropriately (typically switching to
* "synchronization on actual transaction").
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#SYNCHRONIZATION_ON_ACTUAL_TRANSACTION
*/
int PROPAGATION_SUPPORTS = 1;
/**
* Support a current transaction; throw an exception if no current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization within a <code>PROPAGATION_MANDATORY</code>
* scope will always be driven by the surrounding transaction.
*/
int PROPAGATION_MANDATORY = 2;
/**
* Create a new transaction, suspending the current transaction if one exists.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the <code>javax.transaction.TransactionManager</code>
* to be made available it to it (which is server-specific in standard J2EE).
* <p>A <code>PROPAGATION_REQUIRES_NEW</code> scope always defines its own
* transaction synchronizations. Existing synchronizations will be suspended
* and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_REQUIRES_NEW = 3;
/**
* Do not support a current transaction; rather always execute non-transactionally.
* Analogous to the EJB transaction attribute of the same name.
* <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
* on all transaction managers. This in particular applies to
* {@link org.springframework.transaction.jta.JtaTransactionManager},
* which requires the <code>javax.transaction.TransactionManager</code>
* to be made available it to it (which is server-specific in standard J2EE).
* <p>Note that transaction synchronization is <i>not</i> available within a
* <code>PROPAGATION_NOT_SUPPORTED</code> scope. Existing synchronizations
* will be suspended and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4;
/**
* Do not support a current transaction; throw an exception if a current transaction
* exists. Analogous to the EJB transaction attribute of the same name.
* <p>Note that transaction synchronization is <i>not</i> available within a
* <code>PROPAGATION_NEVER</code> scope.
*/
int PROPAGATION_NEVER = 5;
/**
* Execute within a nested transaction if a current transaction exists,
* behave like {@link #PROPAGATION_REQUIRED} else. There is no analogous
* feature in EJB.
* <p><b>NOTE:</b> Actual creation of a nested transaction will only work on specific
* transaction managers. Out of the box, this only applies to the JDBC
* {@link org.springframework.jdbc.datasource.DataSourceTransactionManager}
* when working on a JDBC 3.0 driver. Some JTA providers might support
* nested transactions as well.
* @see org.springframework.jdbc.datasource.DataSourceTransactionManager
*/
int PROPAGATION_NESTED = 6;
/**
* Use the default isolation level of the underlying datastore.
* All other levels correspond to the JDBC isolation levels.
* @see java.sql.Connection
*/
int ISOLATION_DEFAULT = -1;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* can occur.
* <p>This level allows a row changed by one transaction to be read by
* another transaction before any changes in that row have been committed
* (a "dirty read"). If any of the changes are rolled back, the second
* transaction will have retrieved an invalid row.
* @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
*/
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
/**
* Indicates that dirty reads are prevented; non-repeatable reads and
* phantom reads can occur.
* <p>This level only prohibits a transaction from reading a row
* with uncommitted changes in it.
* @see java.sql.Connection#TRANSACTION_READ_COMMITTED
*/
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
/**
* Indicates that dirty reads and non-repeatable reads are prevented;
* phantom reads can occur.
* <p>This level prohibits a transaction from reading a row with
* uncommitted changes in it, and it also prohibits the situation
* where one transaction reads a row, a second transaction alters
* the row, and the first transaction rereads the row, getting
* different values the second time (a "non-repeatable read").
* @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
*/
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
/**
* Indicates that dirty reads, non-repeatable reads and phantom reads
* are prevented.
* <p>This level includes the prohibitions in
* {@link #ISOLATION_REPEATABLE_READ} and further prohibits the
* situation where one transaction reads all rows that satisfy a
* <code>WHERE</code> condition, a second transaction inserts a
* row that satisfies that <code>WHERE</code> condition, and the
* first transaction rereads for the same condition, retrieving
* the additional "phantom" row in the second read.
* @see java.sql.Connection#TRANSACTION_SERIALIZABLE
*/
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
/**
* Use the default timeout of the underlying transaction system,
* or none if timeouts are not supported.
*/
int TIMEOUT_DEFAULT = -1;
/**
* Return the propagation behavior.
* <p>Must return one of the <code>PROPAGATION_XXX</code> constants
* defined on {@link TransactionDefinition this interface}.
* @return the propagation behavior
* @see #PROPAGATION_REQUIRED
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive()
*/
int getPropagationBehavior();
/**
* Return the isolation level.
* <p>Must return one of the <code>ISOLATION_XXX</code> constants
* defined on {@link TransactionDefinition this interface}.
* <p>Only makes sense in combination with {@link #PROPAGATION_REQUIRED}
* or {@link #PROPAGATION_REQUIRES_NEW}.
* <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
*/
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>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
*/
int getTimeout();
/**
* 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</code>.
* <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 that cannot interpret the read-only hint will
* <i>not</i> throw an exception when asked for a read-only transaction.
* @return <code>true</code> if the transaction is to be optimized as read-only
* @see org.springframework.transaction.support.TransactionSynchronization#beforeCommit(boolean)
* @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
*/
boolean isReadOnly();
/**
* Return the name of this transaction. Can be <code>null</code>.
* <p>This will be used as the transaction name to be shown in a
* transaction monitor, if applicable (for example, WebLogic's).
* <p>In case of Spring's declarative transactions, the exposed name
* must (and will) be the
* <code>fully-qualified class name + "." + method name</code>
* (by default).
* @return the name of this transaction
* @see org.springframework.transaction.interceptor.TransactionAspectSupport
* @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionName()
*/
String getName();
}
<3> execute方法参数:
TransactionCallback.java 源码
/*
* Copyright 2002-2007 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
*
* http://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 org.springframework.transaction.TransactionStatus;
/**
* Callback interface for transactional code. Used with {@link TransactionTemplate}'s
* <code>execute</code> method, often as anonymous class within a method implementation.
*
* <p>Typically used to assemble various calls to transaction-unaware data access
* services into a higher-level service method with transaction demarcation. As an
* alternative, consider the use of declarative transaction demarcation (e.g. through
* Spring's {@link org.springframework.transaction.annotation.Transactional} annotation).
*
* @author Juergen Hoeller
* @since 17.03.2003
* @see TransactionTemplate
* @see CallbackPreferringPlatformTransactionManager
*/
public interface TransactionCallback {
/**
* Gets called by {@link TransactionTemplate#execute} within a transactional context.
* Does not need to care about transactions itself, although it can retrieve
* and influence the status of the current transaction via the given status
* object, e.g. setting rollback-only.
*
* <p>Allows for returning a result object created within the transaction, i.e.
* a domain object or a collection of domain objects. A RuntimeException thrown
* by the callback is treated as application exception that enforces a rollback.
* An exception gets propagated to the caller of the template.
*
* @param status associated transaction status
* @return a result object, or <code>null</code>
* @see TransactionTemplate#execute
* @see CallbackPreferringPlatformTransactionManager#execute
*/
Object doInTransaction(TransactionStatus status);
}
TransactionStatus.java 源码
/*
* Copyright 2002-2007 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
*
* http://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;
/**
* Representation of the status of a transaction.
*
* <p>Transactional code can use this to retrieve status information,
* and to programmatically request a rollback (instead of throwing
* an exception that causes an implicit rollback).
*
* <p>Derives from the SavepointManager interface to provide access
* to savepoint management facilities. Note that savepoint management
* is only available if supported by the underlying transaction manager.
*
* @author Juergen Hoeller
* @since 27.03.2003
* @see #setRollbackOnly()
* @see PlatformTransactionManager#getTransaction
* @see org.springframework.transaction.support.TransactionCallback#doInTransaction
* @see org.springframework.transaction.interceptor.TransactionInterceptor#currentTransactionStatus()
*/
public interface TransactionStatus extends SavepointManager {
/**
* Return whether the present transaction is new (else participating
* in an existing transaction, or potentially not running in an
* actual transaction in the first place).
*/
boolean isNewTransaction();
/**
* Return whether this transaction internally carries a savepoint,
* that is, has been created as nested transaction based on a savepoint.
* <p>This method is mainly here for diagnostic purposes, alongside
* {@link #isNewTransaction()}. For programmatic handling of custom
* savepoints, use SavepointManager's operations.
* @see #isNewTransaction()
* @see #createSavepoint
* @see #rollbackToSavepoint(Object)
* @see #releaseSavepoint(Object)
*/
boolean hasSavepoint();
/**
* Set the transaction rollback-only. This instructs the transaction manager
* that the only possible outcome of the transaction may be a rollback, as
* alternative to throwing an exception which would in turn trigger a rollback.
* <p>This is mainly intended for transactions managed by
* {@link org.springframework.transaction.support.TransactionTemplate} or
* {@link org.springframework.transaction.interceptor.TransactionInterceptor},
* where the actual commit/rollback decision is made by the container.
* @see org.springframework.transaction.support.TransactionCallback#doInTransaction
* @see org.springframework.transaction.interceptor.TransactionAttribute#rollbackOn
*/
void setRollbackOnly();
/**
* Return whether the transaction has been marked as rollback-only
* (either by the application or by the transaction infrastructure).
*/
boolean isRollbackOnly();
/**
* Return whether this transaction is completed, that is,
* whether it has already been committed or rolled back.
* @see PlatformTransactionManager#commit
* @see PlatformTransactionManager#rollback
*/
boolean isCompleted();
}
实际应用。
<1> hibernate.cfg.xml文件中spring事务配置
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="dataSourceTest" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 数据库链接 -->
<property name="user" value="root"></property>
<property name="password" value="test"></property>
<property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521:tran"></property>
<property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property>
<!-- 连接池配置 -->
<property name="initialPoolSize" value="10"></property>
<property name="maxIdleTime" value="20"></property>
<property name="checkoutTimeout" value="2000"></property>
<property name="maxStatementsPerConnection" value="30"></property>
</bean>
<!-- sessionFactoryTest -->
<bean id="sessionFactoryTest"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSourceTest" />
</property>
<property name="mappingResources">
<list>
<value>com/lxh/transaction8/BankAccount.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.OracleDialect
</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<!-- 事务相关 -->
<!-- <prop key="current_session_context_class">thread</prop> -->
<!-- <prop key="connection.release_mode">auto</prop> -->
<!-- <prop key="transaction.auto_close_session">false</prop> -->
<prop key="connection.autocommit">false</prop>
<!-- 二级缓存 -->
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
</props>
</property>
</bean>
<!-- JdbcTemplate -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref local="dataSourceTest" />
</property>
</bean>
<!-- spring事务管理 -->
<bean id="transactinManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref bean="dataSourceTest" />
</property>
</bean>
</beans>
<2> TransactionCallback.java接口实现类
package com.lxh.transaction8;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
public class TransactionCallbackImpl implements TransactionCallback {
// 执行语句和JdbcTemplate
private String sql[];
private JdbcTemplate jt;
// constructor
public TransactionCallbackImpl(String sql[],JdbcTemplate jt){
this.sql = sql;
this.jt = jt;
}
@Override
public Object doInTransaction(TransactionStatus arg0) {
return this.jt.batchUpdate(sql);
}
}
<3> BankAccountDaoImpl.Java与dao.xml文件
package com.lxh.transaction8;
import java.io.Serializable;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
public class BankAccountDaoImpl extends HibernateDaoSupport implements
BankAccountDao {
// 日志
private final static Logger logger = Logger
.getLogger(BankAccountDaoImpl.class);
// 属性
private JdbcTemplate jt;
private PlatformTransactionManager transactionManager;
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
public JdbcTemplate getJt() {
return jt;
}
public PlatformTransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
// 查询用户余额
public int getUserBalanceById(Serializable id) {
int balance = 0;
//
try {
// 查询语句
balance = Integer.parseInt(this.jt.queryForObject(
"select ba.balance from BankAccount ba where ba.id = '"
+ id + "'", String.class).toString());
} catch (Exception e) {
logger.error("" + e.getMessage());
}
// 返回
return balance;
}
// 转账
public boolean transferMoney(Serializable fromId, Serializable toId,
int tradeMoney) {
// 标识
boolean flag = false;
//
String sql[] = new String[2];
sql[0] = "update BankAccount ba set ba.balance = ba.balance - "
+ tradeMoney + " where ba.id='" + fromId + "'";
sql[1] = "update BankAccount ba set ba.balance = ba.balance + "
+ tradeMoney + " where ba.id='" + toId + "'";
// 执行结果
int result[] = new int[sql.length];
// spring 事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
TransactionTemplate tt = new TransactionTemplate(transactionManager,
def);// TransactionTemplate 可以采用setter方法注入得到。
TransactionCallbackImpl tci = new TransactionCallbackImpl(sql, jt);
result = (int[]) tt.execute(tci);
// 是否提交事务
boolean commit = true;
for (int j = 0; j < result.length; j++) {
if (result[j] == 0) { // 未正常执行
commit = false;
transactionManager.rollback(status);
break;
}
}
// 成功才提交事务
if (commit) {
transactionManager.commit(status);
flag = true;
}
// 返回
return flag;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- bankAccountDao -->
<bean id="bankAccountDao" class="com.lxh.transaction8.BankAccountDaoImpl"
singleton="false">
<property name="sessionFactory" ref="sessionFactoryTest"></property>
<property name="jt" ref="jdbcTemplate" />
<property name="transactionManager" ref="transactinManager" />
</bean>
</beans>
2. 直接使用PlatformTransactionManager
BankAccountDaoImpl.Java
package com.lxh.transaction8;
import java.io.Serializable;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
public class BankAccountDaoImpl extends HibernateDaoSupport implements
BankAccountDao {
// 日志
private final static Logger logger = Logger
.getLogger(BankAccountDaoImpl.class);
// 属性
private JdbcTemplate jt;
private PlatformTransactionManager transactionManager;
public void setJt(JdbcTemplate jt) {
this.jt = jt;
}
public JdbcTemplate getJt() {
return jt;
}
public PlatformTransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
// 查询用户余额
public int getUserBalanceById(Serializable id) {
int balance = 0;
//
try {
// 查询语句
balance = Integer.parseInt(this.jt.queryForObject(
"select ba.balance from BankAccount ba where ba.id = '"
+ id + "'", String.class).toString());
} catch (Exception e) {
logger.error("" + e.getMessage());
}
// 返回
return balance;
}
// 转账
public boolean transferMoney(Serializable fromId, Serializable toId,
int tradeMoney) {
// 标识
boolean flag = false;
//
String sql[] = new String[2];
sql[0] = "update BankAccount ba set ba.balance = ba.balance - "
+ tradeMoney + " where ba.id='" + fromId + "'";
sql[1] = "update BankAccount ba set ba.balance = ba.balance + "
+ tradeMoney + " where ba.id='" + toId + "'";
// 执行结果
int result[] = new int[sql.length];
// spring 事务
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
result = this.jt.batchUpdate(sql);
// 是否提交事务
boolean commit = true;
for (int j = 0; j < result.length; j++) {
if (result[j] == 0) { // 错误执行
commit = false;
transactionManager.rollback(status);
break;
}
}
// 成功才提交事务
if (commit) {
transactionManager.commit(status);
flag = true;
}
// 返回
return flag;
}
}
来源:oschina
链接:https://my.oschina.net/u/1989867/blog/548899