Loading

Spring学习--Spring事务相关速记

数据库事务

事务特性:

  1. 原子性,事务是不可分割的最小工作单元,事务内的操作要么全做,要么全不做
  2. 一致性,在事务执行前数据库的数据处于正确的状态,而事务执行完成后数据库的数据还是处于正确的状态
  3. 隔离性,并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性
  4. 持久性,事务一旦执行成功,它对数据库的数据的改变必须是永久的,不会造成数据不一致或丢失

数据库常见问题:

  1. 脏读:一个事务看到了另一个事务未提交的更新数据
  2. 不可重复读:在同一事务中,多次读取同一数据却返回不同的结果;也就是有其他事务更改了这些数据
  3. 幻读:一个事务在执行过程中读取到了另一个事务已提交的插入数据;即在第一个事务开始时读取到一批数据,但此后另一个事务又插入了新数据并提交,此时第一个事务又读取这批数据但发现多了一条,即好像发生幻觉一样。

数据库隔离级

  1. 未提交读(RU Read Uncommitted):最低隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现脏读、不可重复读、幻读
  2. 提交读(RC Read Committed):一个事务能读取到别的事务提交的更新数据,不能看到未提交的更新数据,不会出现脏读,但可能出现不可重复读、幻读
  3. 可重复读(RR Repeatable Read):保证同一事务中先后执行的多次查询将返回同一结果,不受其他事务影响,不会出现脏读、不可重复读,但可能出现幻读;
  4. 序列化(Serializable):最高隔离级别,不允许事务并发执行,而必须串行化执行,最安全,不会出现脏读、不可重复读、幻读。

Spring提供的事务管理

Spring框架最核心功能之一就是事务管理,Spring支持声明式事务和编程式事务事务类型,这能帮助我们:

  1. 提供一致的编程式事务管理API,不管使用Spring JDBC框架还是集成第三方框架使用该API进行事务编程;
  2. 无侵入式的声明式事务支持。

Spring框架支持事务管理的核心是事务管理器抽象,通过定义接口 PlatformTransactionManager 让不同数据访问框架来实现,

public interface PlatformTransactionManager {  
       TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;  
       void commit(TransactionStatus status) throws TransactionException;  
       void rollback(TransactionStatus status) throws TransactionException;  
}  

getTransaction():返回一个已经激活的事务或创建一个新的事务(根据给定的TransactionDefinition类型参数定义的事务属性),返回的是TransactionStatus对象代表了当前事务的状态,其中该方法抛出TransactionException(未检查异常)表示事务由于某种原因失败。
commit():用于提交TransactionStatus参数代表的事务
rollback():用于回滚TransactionStatus参数代表的事务

TransactionDefinition接口

public interface TransactionDefinition {  
       int getPropagationBehavior();  
       int getIsolationLevel();  
       int getTimeout();  
       boolean isReadOnly();  
       String getName();  
}  

getPropagationBehavior():返回定义的事务传播行为;
getIsolationLevel():返回定义的事务隔离级别;
getTimeout():返回定义的事务超时时间;
isReadOnly():返回定义的事务是否是只读的;
getName():返回定义的事务名字。

事务传播行为

PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。

编程式事务

配置文件

    <bean id="dataSource" parent="dataSourceParent">
        <property name="url" value="jdbc:mysql://dbm.***.me:3306" />
        <property name="username" value="root" />
        <property name="password" value="123456" />
    </bean>
        <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);  
    TransactionStatus status = txManager.getTransaction(def);  
    jdbcTemplate.execute(CREATE_TABLE_SQL);  
    try {  
        jdbcTemplate.update(INSERT_SQL, "test");  
        txManager.commit(status);  ![](http://images2015.cnblogs.com/blog/1071030/201706/1071030-20170608143321590-1214373007.png)


    } catch (RuntimeException e) {  
        txManager.rollback(status);  
    }  

声明式事务

<tx:advice id="txAdvice" transaction-manager="txManager">  
    <tx:attributes>  
        <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED"/>  
        <tx:method name="*" propagation="REQUIRED" isolation="READ_COMMITTED" read-only="true"/>  
    </tx:attributes>  
</tx:advice>  

<aop:config>
    <aop:pointcut id="daoMethod" expression="execution(* com.dao.*.*(..))"/>
    <aop:advisor pointcut-ref="daoMethod" advice-ref="txadvice"/>
</aop:config>

tx:advice:事务通知定义,用于指定事务属性,其中“transaction-manager”属性指定事务管理器,并通过tx:attributes指定具体需要拦截的方法;
aop:pointcut/:切入点定义 其中第一个代表返回值,第二代表dao下子包,第三个*代表方法名,“(..)”代表方法参数。
aop:advisor:Advisor定义,其中切入点为daoMethod,通知为txAdvice。

不能被事务增强的方法

posted @ 2017-02-06 15:42  JavaNoob  阅读(436)  评论(0编辑  收藏  举报