初识事物处理

  业务层的职能不仅仅是调用dao这么简单,事物处理是任何企业级应用开发中不能回避的一个重要问题。意为我们通过在业务中硬编码的方式

进行事物控制,这样的弊端显而易见:事物代码分散在业务方法中难以重用,需要调整时工作量也比较打:复杂事物的编码难度较高,增加了开发

难度等。spring提供了声明事物处理机制,他基于aop实现,无须编写任何事物管理代码,所有的工作全部在配置文件中完成。这意味着与业务代码

完全分离,配置即可用,降低了开发和维护的难度。

定义事物管理器

<bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
        <!-- ref为数据源 -->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

指定的事物管理器设置事物属性

    <!--  事物管理器id为transactionMapper则可以省略 transaction-manager此属性  -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- 定义属性,声明事物规则 -->
        <tx:attributes>
            <!-- propagation属性定义事物传播行为  name属性则是对应的方法 以什么开头的-->
            <tx:method name="find*" propagation="SUPPORTS"/>
            <tx:method name="add*" propagation="REQUIRED"/>
            <tx:method name="del*" propagation="REQUIRED"/>
            <tx:method name="update*" propagation="REQUIRED"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

propagetion:事务传播机制,该属性可选值有以下几种

  1. REQUIRED:默认值,表示如果存在一个事务,则支持当前事务,如果当前没有事务,则开启一个新的事务
  2. REQUIRES_NEW:表示总是开启一个新的事务,如果事物以及存在则将这个存在的事务挂起,开启新的事务执行该方法
  3. MANDATORY:表示如果存在一个事务,则支持当前事务,如果当前没有一个活动的事务,则抛出异常
  4. NESTED:表示如果存在一个活动的事务,则创建一个事务作为当前事务的嵌套事务运行:如果没有当前事务,该取值与REQUIRED相同
  5. SUPPORTS:表示如果存在一个事务,则支持当前事务,如果当前没有事务,则按非事物方式执行
  6. NOT_SUPPORTED:表示总是以非事物方式执行。如果事物已经存在,则将这个存在的事物挂起,然后执行该方法
  7. NEVER:表示总是以非事物方式执行。如果当前存在一个活动的事物,则抛出异常

使用注解实现事务处理

 使用了注解就不需要再声明事物规则

只需要一行就行了如下

<tx:annotation-driven transaction-manager="txManager"/>

剩下的声明事物规则就交给注解处理了如下

在业务类上添加@Transaction注解即可为该类的所有业务方法统一添加事物处理。如果某业务方法需要采用不同的事务规则,可以在该业务方法添加@Transaction注解

单独进行设置。@Transaction注解也可以设置事物属性的值,默认的@Transaction设置如下

  1. 事务传播设置是:REQUIRED
  2. 事务隔离级别是:
  3. 事务是读写
  4. 事务超时默认是依赖于事物系统的,或者事务超时没有被支持
  5. 任何RuntimeException将触发事务回滚,但是任何checked exception将不触发事务回滚

@Transaction注解各属性如下

 

需要注意的点:

@Transactional只能被应用到public方法上,对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.

SOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别

使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应

2. ISOLATION_READ_UNCOMMITTED 未提交读

事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读

3. ISOLATION_READ_COMMITTED 提交读

保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

4. ISOLATION_REPEATABLE_READ 可重复读

 这种事务隔离级别可以防止脏读,不可重复读。但可能出现幻像读。除了保证一个事务不能读取另一个事务未提交的数据外,还保证避免下面的情况产生(不可重复读)

5. ISOLATION_SERIALIZABLE串行读

 花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除防止脏读,不可重复读外,还避免幻像读。

什么是脏数据,脏读,不可重复读,幻觉读?

Dirty reads--读脏数据。

比如事务A的未提交(还依然缓存)的数据被事务B读走,如果事务A失败回滚,会导致事务B所读取的的数据是错误的 

non-repeatable reads--不可重复读。

比如事务A中两处读取数据-total-的值。在第一读的时候,total100,然后事务B就把total的数据改成200,事务A再读一次,结果就发现,total竟然就变成200了,造成事务A数据混乱 

phantom reads--幻象读数据。

这个和non-repeatable reads相似,也是同一个事务中多次读不一致的问题。但是non-repeatable reads的不一致是因为他所要的数据集被改变了(比如total的数据),但是phantom reads所要读的数据的不一致却不是他所要的数据集改变,而是他的条件数据集改变。比如Select account.id where account.name="grace",第一次读去了6个符合条件的id,第二次读取的时候,由于事务b把一个帐号的名字由"dd"改成"grace",结果取出来了7个数据。

不可重复读的重点是修改    同样的条件, 读取过的数据, 再次读取出来发现值不一样。

幻读的重点在于新增或者删除:同样的条件, 1次和第2次读出来的记录数不一样。

而事务的隔离级别会导致读取到非法数据的情况如下表示:

 

Dirty reads

non-repeatable reads

phantom reads

SERIALIZABLE

不会

不会

不会

REPEATABLE_READ

不会

不会

READ_COMMITTED

不会

READ_UNCOMMITTED

 

常用数据库默认事务隔离级别

MySQL默认为REPEATABLE_READ

SQLSERVER:默认为READ_COMMITTED

oracle默认为READ_COMMITTED

 

原文地址:https://www.cnblogs.com/hfx123/p/9706039.html