Spring的事务管理

153 阅读4分钟

事务的分类

1.编程式事务

所谓编程式事务指的是通过编码方式实现事务,允许用户在代码中精确定义事务的边界。即类似于JDBC编程实现事务管理。管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。

  1. 声明式事务

管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

在 Spring 事务管理中,为我们定义了如下的隔离级别:

①、ISOLATION_DEFAULT:使用后端数据库默认的隔离级别

②、ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读

③、ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生

④、ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生

⑤、ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的

3. 只读

这是事务的第三个特性,是否为只读事务。如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来进行一些特定的优化。通过将事务设置为只读,你就可以给数据库一个机会,让它应用它认为合适的优化措施。

4. 事务超时

为了使应用程序很好地运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源。事务超时就是事务的一个定时器,在特定时间内事务如果没有执行完毕,那么就会自动回滚,而不是一直等待其结束。

5. 回滚规则

事务五边形的最后一个方面是一组规则,这些规则定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚(这一行为与EJB的回滚行为是一致的) 。但是你可以声明事务在遇到特定的检查型异常时像遇到运行期异常那样回滚。同样,你还可以声明事务遇到特定的异常不回滚,即使这些异常是运行期异常。

以上引用自www.cnblogs.com/ysocean/p/7…

Spring中的事务管理

Spring中事务的配置

  1. 导入jar包(spring-tx.jar)
  2. 在配置文件中配置事务
<!-- 注册c3p0数据源 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"></property>
        <property name="jdbcUrl" value="${jdbc.url}"></property>
        <property name="user" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

<!-- 注册事务管理器 -->
    <bean   id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>


    <!-- 注册事务通知 -->

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes  >
            <!-- isolation:事务隔离级别    propagation:事务传播行为-->
            <tx:method name="open*" propagation="REQUIRED" isolation="DEFAULT" />
            <tx:method name="buy*" propagation="REQUIRED" isolation="DEFAULT" rollback-for="BuyFundException"/>
        </tx:attributes>

    </tx:advice>
    <!-- aop配置 -->

    <aop:config>
        <aop:pointcut expression="execution(* *..service.*.buyFund(..))" id="buyFund"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="buyFund"/>
    </aop:config>

​tx:method标签中的属性:

  • name:方法名、可以使用通配符(*)
  • isolation:事务隔离级别
  • propagation:事务传播行为
  • rollback-for:对于什么异常回滚
  • no-rollback-for:对于异常不回滚
  • timeout:设置超时时限
  • read-only:设置是否只读、会对事务进行优化。

​ 注解式事务管理开发

​ 在方法前加上@Transactional注解,其属性和配置文件中属性配置一致,

@Transactional(rollbackFor=BuyFundException.class)
    public void buyFund(int aid, double payMoney, int fid, int count) throws BuyFundException {
        accountDaoImpl.updateAccount(aid, payMoney);
        if(1==1) {
            throw new BuyFundException("异常");
        }
        fundDaoImpl.updateFund(fid, count);
    }

​ 需要在配置文件中添加注解的扫描驱动

<!-- 事务注解驱动 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>

@Transactional(rollbackFor = Exception.class)注解了解吗?

Exception 分为运行时异常 RuntimeException 和非运行时异常。事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。

当 @Transactional 注解作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。如果类或者方法加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。

在 @Transactional 注解中如果不配置rollbackFor属性,那么事务只会在遇到RuntimeException的时候才会回滚,加上 rollbackFor=Exception.class,可以让事务在遇到非运行时异常时也回滚。