您的位置:首页 > 编程语言 > Java开发

通过TransactionDefinition接口来学习spring事务的隔离级别和传播特性(4.3.4版本)

2017-06-15 18:17 519 查看
通过spring官方包中带的原代码来看spring的事务的5中隔离级别和7种传播特性;    

源码如下:

/*
* Copyright 2002-2015 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}.
*
* @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;  //事务传播级别1:当前如果有事务,Spring就会使用该事务;否则会开始一个新事务;(这也是默认设置和定义)

/**
* 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} 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}, a
* Hibernate {@code Session}, 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} with care! In particular, do
* not rely on {@code PROPAGATION_REQUIRED} or {@code PROPAGATION_REQUIRES_NEW}
* <i>within</i> a {@code PROPAGATION_SUPPORTS} 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;//事务传播级别2:如果有事务,Spring就会使用该事务;否则不会开始一个新事务

/**
* 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}
* scope will always be driven by the surrounding transaction.
*/
int PROPAGATION_MANDATORY = 2;  //事务传播级别3:当前如果有事务,Spring就会使用该事务;否则会因为没有事务而抛出异常

/**
* 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} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>A {@code PROPAGATION_REQUIRES_NEW} 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;//事务传播级别4:总是要开启一个新事务。如果当前已经有事务,则将已有事务挂起

/**
* 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} to be
* made available it to it (which is server-specific in standard Java EE).
* <p>Note that transaction synchronization is <i>not</i> available within a
* {@code PROPAGATION_NOT_SUPPORTED} scope. Existing synchronizations
* will be suspended and resumed appropriately.
* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
int PROPAGATION_NOT_SUPPORTED = 4;//事务传播级别5:代码总是在非事务环境下执行,如果当前有事务,则将已有事务挂起,再执行代码,之后恢复事务

/**
* 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} scope.
*/
int PROPAGATION_NEVER = 5; //事务传播级别6:绝对不允许代码在事务中执行。如果当前运行环境有事务存在,则直接抛出异常,结束运行

/**
* 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;//事务传播级别7:该级别支持嵌套事务执行。如果没有父事务存在,那么执行情况与PROPAGATION_REQUIRED一样;典型的应用是批量数据入库,开启父事务对一批数据入库,而对于每条入库的数据

都有一个子事务对应,那么当所有的子事务成功,父事务提交,才算成功,否则,就都失败。

/**
* 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;

//事务隔离级别1:默认的隔离级别,同数据库一样的,如果不做特别设置,mysql默认的是可重复读,而oracle默认的是读提交

/**
* 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;
//事务隔离级别2:读未提交,即一个事务可以读取另外一个事务中未提交的数据,即脏读数据存在,性能最好,但是没啥用。
/**
* 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;
//事务隔离级别3:读提交,即一个事务只能读取到另一个事务提交后的数据,oracle数据库默认隔离级别;存在不可重复读问题,即交叉事务出现,A事务两次读取数据可能会读到B事务提交的修改后的数据,即在同一个事务中读到了不同的数据,也叫不可重复读
/**
* 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 re-reads 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;

//事务隔离级别4:可重复读,即一个事务只能读取到在次事务之前提交的数据,而之后提交不能读取到,不管对方的事务是否提交都读取不到,mysql默认的隔离级别。此隔离级别有可能会遇到幻读现象,但是mysql 基于innodb引擎实现的数据库已经通过多版本控制解决了此问题,所以可以不考虑了。

/**

* 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} condition, a second transaction inserts a row

* that satisfies that {@code WHERE} condition, and the first transaction

* re-reads 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;

//事务隔离级别2:序列化读,每次都是全表锁,性能最差,安全性最高,一般场景不适用,也没有这个必要。
在开发的过程中,用事务最多的方式是通过注解@Transaction来完成的,虽然大多数的业务场景都可以在这一个注解下完成即可。
但是为了适应某些特别的场景比方说只读方法的优化等,通过对@Transaction来添加参数来完成我们想要的事务传播特性和隔离级别,以及是否只对某些异常类做回滚,是否只读方法等。

1)使用propagation 指定事务的传播行为,即当前的事务方法被另外一个事务方法调用时如何使用事务。
默认取值为REQUIRED,即使用调用方法的事务
REQUIRES_NEW:使用自己的事务,调用的事务方法的事务被挂起。
2)使用isolation 指定事务的隔离级别,最常用的取值为READ_COMMITTED
3)默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置。通常情况下,默认值即可。
4)使用readOnly 指定事务是否为只读。 表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务。若真的是一个只读取数据库值得方法,应设置readOnly=true
5)使用timeOut 指定强制回滚之前事务可以占用的时间。
@Transactional(propagation = Propagation.MANDATORY,isolation = Isolation.READ_COMMITTED,noRollbackFor = {特定的异常类对象},readOnly = true,timeout = 3)
其中timeout的单位为秒。多个异常类对象,用逗号分隔即可。


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: