• spring 事务管理配置


    本篇文章只涉及spring事务的配置,不进行事务的介绍。

    spring通过PlatformTransactionManager接口作为事务管理器来进行事务的管理,它本身并不进行事务的创建以及相关操作,它就相当于事务管理的容器,里面放的是事务。事务使用有编程式事务和声明式事务,现在一般情况下都是使用声明式事务。

    声明式事务使用方法:

    1、在配置的xml文件中使用AOP模式来进行事务声明,如下所示

        <bean id="transactionManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>    
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <tx:attributes>
                <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            </tx:attributes>
        </tx:advice>
        <aop:config>
            <aop:pointcut id="interceptorPointCut"
                          expression="execution(* com.test.service.impl.*.*(..))" />
            <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCut" />
        </aop:config>

    2、使用注解形式进行事务声明,如下所示:

    第一步:在xml配置文件中加入如下配置

    <!-- 启动声明式注解 -->
    <
    tx:annotation-driven transaction-manager="transactionManager" />

    或者在被@configuration注解注释的类上添加@EnableTransactionManagement注解

    第二步:在需要添加事务的类或方法上添加@Transactional注解,注解可以设置value(用来设置数据源)、transactionManager(同value作用相同)、propagation(设置事务的传播行为,使用枚举Propagation来选择值,默认是REQUIRED)、isolation(设置事务的隔离机制,使用枚举Isolation来选择值,默认是底层数据库支持的事务的默认隔离机制)、timeout(设置事务的超时时间,可以使用TransactionDefinition接口提供的值,默认值为-1)、readOnly(布尔值,设置事务为只允许读,不进行修改操作,如果是只有读的操作可以设置为true,官方解释设置为true时,会在运行时进行相应的优化,但是并不能保证进行修改操作会失败)、rollbackFor(设置进行事务回滚的异常类类型)、rollbackForClassName(设置进行事务回滚的异常类类名)、noRollbackFor(设置不会进行事务回滚的异常类类型)、noRollbackForClassName(设置不会进行事务回滚的异常类类名)

    即使没有设置rollbackFor、rollbackForClassName的值,spring框架在我们调用的方法发生运行时异常的时候会进行事务回滚操作。

    3、利用AOP的around类型的advice进行事务声明,如下所示

    @Aspect
    @Component
    public class TransactionalAop {
    
        @Autowired
        PlatformTransactionManager transactionManager;
     
        @Around("execution(* com.test.service.impl.*.*(..))")
        public void aroundMethod(ProceedingJoinPoint  pjp) throws Throwable {//        // 利用spring框架提供的事务模板类进行事务操作
    //        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
    //        transactionTemplate.execute((status) -> {
    //            Object result = null;
    //                try {
    //                    result = pjp.proceed();
    //                } catch (Throwable e) {
    //                    if (e instanceof RuntimeException) {
    //                        throw (RuntimeException)e;
    //                    } 
    //                    if (e instanceof Error) {                        
    //                        throw (Error)e;
    //                    }
    //                    throw new RuntimeException(e);
    //                }
    //                return result;
    //        });
            
            // 手动创建事务(同时开启事务)并根据方法调用结果进行事务回滚或者提交
            TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                pjp.proceed();
            } catch (Throwable e) {
                transactionManager.rollback(transaction);
                throw e;
            }
            transactionManager.commit(transaction);
        }
    }

    如上所示,我们可以利用spring提供的TransactionTemplate类来进行事务的相关操作,但是这里使用有个小缺陷,就是execute(TransactionCallback<T> action)方法里的参数action中的doInTransaction(TransactionStatus status)方法没有显式抛出异常,所以我们只能在doInTransaction(TransactionStatus status)方法中抛出运行时异常或Error来进行事务的回滚。如果是自己手动进行事务开启、提交、回滚就不会存在这个问题,如上所示,利用PlatformTransactionManager接口的getTransaction(@Nullable TransactionDefinition definition)方法来进行事务的开启,最后根据方法的执行结果来进行事务提交或回滚操作。

    综合:

    第一种方法是老式的xml配置文件进行事务配置的方法,需要用到xml配置文件,在如今springboot肆意横行的时代(springboot允许我们加载xml配置文件,但是如果还在使用xml配置文件不是又回去了吗?!),这种配置方式已经算是落伍了。

    第二种方法是基于注解进行事务配置的方法,算是比较方便。优点是:事务管理的粒度比较细,@Transactional既可以用在类上也可以用在方法上;缺点:至少每个业务逻辑的类都要用到@Transactional注解。

    第三种方法是利用aop的动态代理原理,在方法调用之前进行事务开启,根据方法执行结果来进行事务的相关操作。优点:事务统一管理,不在需要每个类或方法上添加@Transactional注解;缺点:事务管理的粒度比较粗。

  • 相关阅读:
    真正VC++.net笔记1系统时间的获取
    真正VC++.net笔记5MessageBox变MessageBoxA?
    Judge Online 系统流程设计
    杂谈1:事情因每个人的参与而不同
    ESX/ESXi 4.1 Update 1 or later 同步NTP
    iSCSI CHAP认证
    JSTL中c:set标签的要点和技巧
    JSTL 判断对象是否为空
    Smartmontools——linux磁盘检测工具
    ECMAScript 对象类型
  • 原文地址:https://www.cnblogs.com/zzw-blog/p/9708822.html
Copyright © 2020-2023  润新知