Spring事务编写

来源:互联网 发布:nginx 目录配置 编辑:程序博客网 时间:2024/06/05 07:39

        提到事务大家可能都比较熟悉了,日常项目中也会经常的用到。在Spring相关的应用中,调用Spring集成的接口,就可以完成事务程序的编写。虽然编写过一些事务应用,但对Spring事务的结构,JDBC以及数据库层面的支撑有些生疏,抽时间整理了一下。

         持久层支持

         业务事务的实现最终还是需要依赖数据库对事务的支撑。事务具有四大特性:原子性、一致性、隔离性、持久性(ACID)。原子性、一致性、持久性在各数据库中定义和支持差别不大。针对隔离性,不同数据库产品对其支持不同。

         事务隔离级别

         标准的SQL定义四种事务隔离级别,以及每种隔离级别导致的问题如下:

未提交读 - ReadUncommitted   - 脏读

提交读    - Read Committed      - 不可重复读

重复读    - Repeatable Read     - 幻想读

序列化    - Serializable

        各大数据库对这些事务的支持各不相同:

        SQL SERVER以上四种全部支持。

  Oracle数据库不支持ReadUncommitted和Repeatable Read。Oracle的默认隔离级别是Read Committed, 不完全满足隔离性的要求。

MySql InnoDB引擎以上四种全部支持,默认支持的隔离级别是Repeatable Read。但是,InnoDB 在保证Repeatable Read的前提下,用Next-key locking算法(相对谓词锁,锁定的是范围而不是条件),同时避免了幻想读。因此,InnoDB默认的隔离级别能够完全保证事务的隔离性要求。

         事务分类

事务主要分为以下几类:扁平事务、带有保存点的扁平事务、链事务、嵌套事务、分布式事务

扁平事务:实际使用中最常见的事务,由begin/rollback/commit等组成。其间的操作作为原子操作,要么全部执行,要么全部回滚。

带有保存点的扁平事务:可以在事务执行的过程中设定标志位,在需要回滚时,可以指定相应的标志位进行部分回滚。

链事务:可以看做一个有约束的带有保存点的扁平事务,它不能随意的回滚到某个点,只能回滚到最近的保存点。

嵌套事务:在事务中嵌入事务,外部的称为父事务,内部的称为子事务。子事务的提交并不能立即生效,只有等最外层的父事务提交之后才能生效。父事务的回滚会同样会导致子事务的回滚。

分布式事务:是指在分布式环境下的扁平事务。使用分布式事务InnoDB引擎的隔离级别必须设定为Serializable。

SQL代码块

start transaction; commit和rollback


JDBC驱动接口

JDBC中提供了相应的接口供相关事务的操作,这些接口定义在java.sql.Connection中:

首先,如果想主动控制事务的提交,必须把自动提交设定为false.

connection.setAutoCommit(false);

在将auto commit设定成false,在事务提交或者回滚之前会锁定相应的数据,因此需要及时提交或者回滚,尤其是在发生异常事。否则可能因为未处理异常导致数据长时间锁定,发生死锁。

需要进行带有保存点的事务时,设定保存点:

Savepoint  setSavepoint(),

Savepoint  setSavepoint(String name),

同样释放保存点:

releaseSavepoint(Savepointsavepoint)

当需要回滚或者回滚到某个保存点时:

rollback() //回滚整个事务

rollback(Savepointsavepoint) //回滚到特定保存点

正确执行后提交:

commit()

设定事务隔离级别:

setTransactionIsolation(intlevel)。

事务隔离级别就是在前面提及到Read Uncommitted,Read Committed,Repeatable Read,Serializable。具体要根据底层数据库的支持来设定值。例如Oracle就不支持Read Uncommitted,Repeatable Read。


Spring事务处理

Spring事务处理模块在org.springframework.transaction包中。

有三个重要的接口。PlatformTransactionManager、TransactionDefinition、TransactionStatus

PlatformTransactionManager

PlatformTransactionManager是事务管理器的基础,不管是声明式的还是编程式的事务管理都需要此抽象来完成。常见的事务管理器根据数据源DataSource的不同有以下几种常见管理器:

DataSourceTransactionManager:适用于直接通过JDBC驱动连接的数据源。

HibernateTransactionManager:适用于通过Hibernate持久层框架连接的数据源。DataSource为Hibernate SessionFactory。

JpaTransactionManager:JPA是JavaPersistence API,通过注解的形式进行实体持久化标记,结合Hibernate等ORM框架一起使用。从JDK.50开始支持。Spring 引入JpaTransactionManager来支持JPA。DataSource为EntityManager.


TransactionDefinition

TransactionDefinition接口,定义了事务的隔离级别和传播行为,超时时间。

Spring事务传播行为:

PROPAGATION_REQUIRED:

必须有一个事务:如果当前存在事务、则使用当前事务,否则创建新的事务。

PROPAGATION_SUPPORTS

事务可有可无:如果当前存在事务,则使用当前事务,否则不在事务中执行

PROPAGATION_MANDATORY

必须在当前事务执行,否则报错

PROPAGATION_REQUIRES_NEW

不管当前有无事务,均创建一个新的事务执行

PROPAGATION_NOT_SUPPORTED

不在事务中运行,开启新的连接,不使用事务

PROPAGATION_NEVER

不在事务中执行,如果存在当前事务则抛出异常

PROPAGATION_NESTED

如果当前存在事务,则应运行于嵌套事务中。

Spring事务隔离级别:

Spring事务隔离级别定义,与标准SQL定义一致,但需要注意底层数据库的支持。

TransactionStatus

TransactionStatus代表了开启后的事务状态。包括是否是新事务,是否有保存点,是否完成或回滚,设定回滚标识等。


 Spring编写事务应用

Spring提供了两种编写事务处理应用的方式:声明式和编程式。下面主要介绍下编程式事务编写:

使用TransactionTemplate来进行编写事务,TransactionTemplate继承了DefaultTransactionDefinition。


1、TransactionTemplate中需传入transactionManager,来进行事务操作:创建、提交、回滚。

2、execute方法来执行业务事务。该方法接收TransactionCallback接口作为参数。此处使用回调设计模式:即被调用方也可以调用对方接口。TransactionCallback通常作为匿名类来使用,只有一个方法doInTransaction,用于定义事务执行的主体。execute代码如下所示:


编程示例代码如下:

主要有以下几部分:DataSource、TransactionManager、TransactionTemplate、事务执行主体

<span style="white-space:pre"></span>//定义事务管理器
<span style="white-space:pre"></span><bean id="aaTransactionManager"<span style="white-space:pre"></span>class="org.springframework.jdbc.datasource.DataSourceTransactionManager">            <property name="dataSource">            <span style="white-space:pre"></span><ref local="**" />            </property>       </bean>
       //定义事务执行模板       <bean id="bbTransactionTemplate"   <span style="white-space:pre"></span>class="org.springframework.transaction.support.TransactionTemplate">          <property name="transactionManager">             <ref local="aaTransactionManager" />          </property>       </bean><span style="white-space:pre"></span>//事务业务逻辑代码如下:<span style="white-space:pre"></span>return bbTransactionTemplate.execute(                new TransactionCallback() {                    public Object doInTransaction(TransactionStatus status) {                        ***                        try {                            ****                        } catch (Exception e) {                            status.setRollbackOnly();                            log.error("**");                                                    }                        return obj;                    }        });

0 0
原创粉丝点击