• Spring事务管理


    Spring事务管理

    本文对Spring事务管理做简单讲解,在学习本文之前请先了解数据库隔离级别与事务的概念。

    在学习之前先了解Spring隔离级别,Spring事务传播。

    一、Spring隔离级别

    ① ISOLATION_DEFAULT:这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应

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

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

    ④ ISOLATION_REPEATABLE_READ:这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。

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

    二、Spring事务传播性

    ① PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是Spring默认的事务的传播。

    ② PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。

    ③ PROPAGATION_MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

    ④ PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

    ⑤ PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    ⑥ PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

    ⑦ PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

    三、核心接口

    image.png 

    四、事务管理器

    Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hibernate或者JTA等持久化机制所提供的相关平台框架的事务来实现。

    Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBCHibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。此接口的内容如下:

    package org.springframework.transaction;
    public interface PlatformTransactionManager {
        TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;
        void commit(TransactionStatus var1) throws TransactionException;
        void rollback(TransactionStatus var1) throws TransactionException;
    }

    1.JDBC事务

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
    </bean>

    2.Hibernete事务

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    3.Java持久化API事务(JPA

    Hibernate多年来一直是事实上的Java持久化标准,但是现在Java持久化API作为真正的Java持久化标准进入大家的视野。如果你计划使用JPA的话,那你需要使用SpringJpaTransactionManager来处理事务。你需要在Spring中这样配置JpaTransactionManager

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    JpaTransactionManager只需要装配一个JPA实体管理工厂(javax.persistence.EntityManagerFactory接口的任意实现)。JpaTransactionManager将与由工厂所产生的JPA EntityManager合作来构建事务。

    4.Java原生API事务

    如果你没有使用以上所述的事务管理,或者是跨越了多个事务管理源(比如两个或者是多个不同的数据源),你就需要使用JtaTransactionManager

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionManagerName" value="java:/TransactionManager" />
    </bean>

    JtaTransactionManager将事务管理的责任委托给javax.transaction.UserTransactionjavax.transaction.TransactionManager对象,其中事务成功完成通过UserTransaction.commit()方法提交,事务失败通过UserTransaction.rollback()方法回滚。

    五、事务管理方式配置

    配置了事务管理器后,事务当然还是得我们自己去操作,Spring提供了两种事务管理的方式:编程式事务管理和声明式事务管理,让我们分别看看它们是怎么做的吧。

    1. 编程式事务管理

    编程式事务管理我们可以通过PlatformTransactionManager实现来进行事务管理,同样的Spring也为我们提供了模板类TransactionTemplate进行事务管理,下面主要介绍模板类,我们需要在配置文件中配置

    <!--配置事务管理的模板-->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager"></property>
            <!--定义事务隔离级别,-1表示使用数据库默认级别-->
            <property name="isolationLevelName" value="ISOLATION_DEFAULT"></property>
            <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"></property>
    </bean>

    测试代码

    package com.gray;
     
    import com.gray.service.BaseSevice;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.transaction.TransactionStatus;
    import org.springframework.transaction.support.TransactionCallbackWithoutResult;
    import org.springframework.transaction.support.TransactionTemplate;
     
    import javax.annotation.Resource;
     
    /**
     * Created by gray on 2017/4/8.
     */
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring-test.xml"})
    public class TransactionTest{
        @Resource
        private TransactionTemplate transactionTemplate;
        @Autowired
        private BaseSevice baseSevice;
     
        @Test
        public void transTest() {
            System.out.println("before transaction");
            Integer sum1 = baseSevice.sum();
            System.out.println("before transaction sum: "+sum1);
            System.out.println("transaction....");
            transactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    try{
                        baseSevice.insert("INSERT INTO tbl_account VALUES (100);",false);
                        baseSevice.insert("INSERT INTO tbl_account VALUES (100);",false);
                    } catch (Exception e){
                        //对于抛出Exception类型的异常且需要回滚时,需要捕获异常并通过调用status对象的setRollbackOnly()方法告知事务管理器当前事务需要回滚
                        status.setRollbackOnly();
                        e.printStackTrace();
                    }
               }
            });
            System.out.println("after transaction");
            Integer sum2 = baseSevice.sum();
            System.out.println("after transaction sum: "+sum2);
        }
    }

    2. 声明式事务管理

    声明式事务管理有两种常用的方式,一种是基于txaop命名空间的xml配置文件,一种是基于@Transactional注解,随着SpringJava的版本越来越高,大家越趋向于使用注解的方式,下面我们两个都说。

    1.基于txaop命名空间的xml配置文件

    配置文件

        <tx:advice id="advice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="insert" propagation="REQUIRED" read-only="false"  rollback-for="Exception"/>
            </tx:attributes>
        </tx:advice>
     
        <aop:config>
            <aop:pointcut id="pointCut" expression="execution (* com.gray.service.*.*(..))"/>
            <aop:advisor advice-ref="advice" pointcut-ref="pointCut"/>
        </aop:config>

    3. 基于@Transactional注解

    这种方式最简单,也是最为常用的,只需要在配置文件中开启对注解事务管理的支持。

    <!-- 声明式事务管理 配置事物的注解方式注入-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

    然后在需要事务管理的地方加上@Transactional注解,如:

    @Transactional(rollbackFor=Exception.class)
    public void insert(String sql, boolean flag) throws Exception {
            dao.insertSql(sql);
            // 如果flag 为 true ,抛出异常
            if (flag){
                throw new Exception("has exception!!!");
            }
    }

     

     




    查看原文:http://www.coder306.cn/?p=113
  • 相关阅读:
    常用正则表达式
    java中的异或运算
    Eclipse 中,web项目在Tomcat运行时填写不了Server name
    错误: 找不到或无法加载主类 tomcat-juli.jar
    Hadoop学习之Ubuntu12.04 Hadoop 环境搭建笔记
    ubuntu安装 cober 笔记
    Ubuntu中安装JDK
    对象调用很容易忽视的地址问题
    2018.09.27_练习时的tips
    网页的组成(一)
  • 原文地址:https://www.cnblogs.com/coder306/p/13087714.html
Copyright © 2020-2023  润新知