spring事务一

来源:互联网 发布:json数组添加对象 编辑:程序博客网 时间:2024/05/20 15:56

 spring事务

1.先讲讲简单的JDBC事务管理:

Spring提供编程式的事务管理和声明式的事务管理两种方式。编程式的是利用相关事务代码直接嵌入到业务程序中,耦合性较高;而声明式事务管理则是利用springAOP以配置文件方式设置,以后如果不再需要事务管理,可以直接在bean定义文件中修改配置即可。因此声明式事务管理的耦合性被大大降低,且操作方便,无需修改大量代码。

 

事务是一组原子Atomic操作的工作单元,这一组SQL指令,必须全部执行成功,若是因为其中某个原因未全部执行成功,则先前该组所有执行的sql指令都会被撤销。同时事务还要满足一致性consistent,可持续性DURable,隔离性Isolated。也就是ACID.

 

对于JDBC如何使用事务:

(1)  操作connection的setAutoCommit()方法,设定false参数,执行手动提交;

(2)  下达一连串的sql语句,并执行connection.commit()提交;

(3)  如果中间发生错误,则执行rollback()来撤销该事务所有的操作执行。

Try{

    ……

    Connection.setAutoCommit(false);//关闭自动提交开关

    ……

    Sql操作

    Connection.commit();//提交

}catch(SQLExceptione)

{

    Connection.rollback;//撤销

}

---------------------------------------------摘自《spring2.0技术手册》林信良著

 

Spring中对于jdbc的事务管理加以封装,spring事务管理的抽象关键在于org.springframework.transaction.PlatformTransactionManager接口的实现,通过阅读spring3.2.4其中相关源码,我们可以看到:

该接口是spring的事务基础的核心接口。虽然可以直接使用它的实现,但是通常应用是使用的或者是TransactionTemplate或者是声明式事务管理(声明式事务管理是通过AOP实现的)

对于该接口的实现,可以继承org.springframework.transaction.support.AbstractPlatformTransactionManager类,该类预实现了propagation行为,同时对于事务同步处理进行了定义。其实现的子类需要对于事务的其他专有状态实现其模板方法,(专有状态有:begin,suspend,resume,commit)。

其他实现platformTransactionManager接口的有JTAtransactionManager,datasourcetransactionmanager等,可以参考他们对于其他事务策略的实现,以此作为指导。

platformTransactionManager接口中有三个方法:

#1:返回一个活的的事务或者是创建一个新的,根据是指定的传输行为

TransactionStatusgetTransaction(TransactionDefinition)throws TransactionException

#2

Voidcommit(TransactionStatus) throws TransactionException;

#3

Voidrollback(TransactionStatus) throws TransactionException

 

其中用到了TransactionStatus,它表示事务的状态。可以通过它来获得状态信息,可以以编程方式请求回滚(代替以抛出异常,进行隐形回滚方式)。它继承自savepointManager接口,可以访问savepoint的内容。这里需要注意只有事务管理器支持savepoint,这里他才是可用的。

该接口TransactionStatus的实例定义了:

isNewTransaction()是否是新事务;

hasSavepoint()

setRollbackOnly();

isRollbackOnly()

flush()

isCompleted();

SavepointManager接口用于编程式事务管理中,而且是当前正在活动的事务方法方可(且事务管理器支持),它是高级的应用,如果没有此高级需求的话,可以用PROPAGETION_NESTED.它的方法由

创建保存点createSavepoint()

回滚到保存点:rollbackToSavepoint()

释放保存点:releaseSavepoint();

 

另外还有TransactionDefinition接口定义事务的各种传播行为、隔离层级、只读提示、事务超时期间等。

其代码中给出的注释:该接口定义了spring(委屈)的事务属性。

注意:只有新事务才可设置隔离级别和超时属性,其它情况下的设置将无效,只有PROPAGETION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED状态能够设置,其他情况的隔离和超时属性无效。

并不是所有的事务管理器都支持这些高级特性,如果设置了非默认的值遇到不支持该特定的情况将会爬出异常。

只读标记应用于任何事务的上下文,无论是资源级事务,还是操作非事务的在资源级上。后者,该标记仅仅用来管理该应用的资源,如hibernate。这里的an actual resourcetransaction ,operating non-transactionally at the resource level 需要进一步理解。

 

TransactionDefiniton中的属性:

(1)  传播行为Propagation behavior:传播行为定义了事务应用于方法之上的边界,它告知何时该开始一个新事务,何时事务该被停止,或方法是否要在事务中进行。

(a)  PROPAGATION_REQUIRED:支持现在的事务,如果没有就创建他

(b)  PROPAGATION_SUPPORTS:支持现有的事务,如果没有就以非事务执行它;

(c)  PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务抛出异常

(d)  PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在一个事务则被暂停

(e)  PROPAGATION_NOT_SUPPORTED:不支持当前事务,指出不应该在当前事务中执行,如果有的话暂停现存事务

(f)  PROPAGATION_NEVER:指出不应在当前事务中进行,如果有的话抛异常。

(g)  PROPAGATION_NESTED:在一个嵌入的事务中执行。

这里感觉好笼统。

(2)  隔离层级:在一个应用程序中,可能有多个事务同时在进行,这些事务应当彼此之间互相不知道另外一个事务的存在。这样会产生一些问题。如脏读:前一个事务已经更新了一份数据,另一个事务在此时读取了同一份数据,由于一些原因,前一个执行了rollback操作,则后一个事务所读取的数据就会不正确。Non-repeatableread在一个事务中两次查询之中的数据不一致,可能是因为两次查询之中插入了一个事务更新了原来的数据。Phantom read 在一个事务的两次查询中数据笔数不一致,两次查询间有其他事务插入数据导致查询数据多出了新的插入的。

为了避免以上等问题,需要在事务处理过程中锁定正在更新或者查询的数据字段,直到该事务完成。这样如果该事务锁定了当前某些字段,而下一个事务有需要进行等待前面事务解锁定,这样会影响数据库操作的效率。根据现实情况可以根据需求设置相应的隔离等级。

(a)  ISOLATION_DEFAULT :使用底层数据库默认的隔离等级

(b)  ISOLATION_READ_UNCOMMITTED:不解决脏读、不可重复读、读取数据数不一致问题(也就是一个事务操作了一行,但是在可以再所有改变都被提交之前由另外事务读取的情况,允许)

(c)  ISOLATION_READ_COMMITTED:禁止以下行为的发生,一个事务执行了一下行为,但是没有提交前,不允许另一个事务进行读取。(解决脏读、不可重复读、读取数据数不一致的问题)

(d)  ISOLATION_REPEATABLE_READ:禁止该行数据发生了改变但是未提交,另一个事务不能读;它也解决NON-REPEATABLE-READ的问题,同一事务两次读取数据数不一致的问题。

(e)  ISOLATION_SERIALIZABLE:该级别包含ISOLATION_REPEATABLE_READ的情形,同时也禁止下面这种情形一个事务读取了所有行数,这是第二个事务却向其中添加了一行新数据,事务一(相同事务)再读取所有行数时,数据和之前数据不一致。完整的隔离层级,会锁定对应的数据表格,因而又效率问题。

(3)  只读提示Read-only 如果事务只进行读取动作,可以利用底层数据库在只读操作时发生的一些最佳化动作。因为必须在事务中才有效,需要配合传播行为PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW ,PROPAGATION_NESTED.

(4)  事务超时期间:对于过长的事务操作需要考虑回滚,并重新操作,而不是无线时的等待。

可以设置TIMEOUT,如TIMEOUT_DEFAULT :默认事务系统的超时设置。设置的事务超时期间,计时是从事务开始时,它也必须搭配传播行为PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED来设置。

 

0 0
原创粉丝点击