spring管理事務管理1----------編程式(如下源碼均爲spring2.5.6)

    Spring事務策略,有一個接口"PlatformTransactionManager"。        
/* 
 * 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; 
  
}
1、編程式
       編程式有兩種方式:使用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;
	}

}
相關文章
相關標籤/搜索