基于注解形式的统一事务管理---springboot

一前言

在操作数据库的时候,我们经常对一个service层进行事务设置,在springmvc中都是配置在xml文件中,在springboot中想要进行统一事务配置,在查找了大量的资料后,发现有一个很好,很久之前就用过了,这次加上自己的理解贴出来。

二、基于注解形式的统一事务管理

1)代码:

/**
 * 
 */
package com.zlc.config;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

/**
 * @Description: 基于注解的方式的统一事物处理
 * @Create Date: 2017年9月30日下午8:47:07
 * @Version: V1.00 
 * @Author: 追到乌云的尽头找太阳(Jacob)
 */
@Aspect
@Configuration
public class TxAdviceInterceptor {
	
	// 超时时间 单位秒
	private static final int TX_METHOD_TIMEOUT = 5;
	//  面向切面,通过切面到service层的操作,进行事务统一管理
	//   包名记得一定要改为自己的,不然不生效
    private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.zlc.service.*.*(..))";
 //  service  包下的所有类,所有方法,如果service下还有子包,且这种配置没生效,则可以改为   com.zlc.service.*.*.*(..))
 
    @Autowired
    private PlatformTransactionManager transactionManager;
 
    @Bean
    public TransactionInterceptor txAdvice() {
        NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
         
        // 只读事务,不做更新操作
        RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
        readOnlyTx.setReadOnly(true);
        readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
        // 当前存在事务就使用当前事务,当前不存在事务就创建一个新的事务
        RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
        requiredTx.setRollbackRules(
            Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
        requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        requiredTx.setTimeout(TX_METHOD_TIMEOUT);
        Map<String, TransactionAttribute> txMap = new HashMap<>();
        //  这里是设置什么样的操作对应的事务级别  比如getXXX方法,就是只读
        //  需要和自己的service方法对应上
        txMap.put("add*", requiredTx);
        txMap.put("save*", requiredTx);
        txMap.put("insert*", requiredTx);
        txMap.put("update*", requiredTx);
        txMap.put("delete*", requiredTx);
        txMap.put("get*", readOnlyTx);
        txMap.put("query*", readOnlyTx);
        source.setNameMap( txMap );
        TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
        return txAdvice;
    }
 
    @Bean
    public Advisor txAdviceAdvisor() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }

}

三、说明

通过注解形式的事务统一管理,有方便之处就是省去配置文件那种略显乱的方式,而且通过注解形式编程貌似现在也是一个趋势。缺点也很明显,就是东西写死在代码里了。
2)当上面的面向切面事务管理生效后,比如说你在使用spring data JPA的delete或者uodate方法时,有时会报错,然后查看执行的删除SQL语句,开头居然是 select,这种就是没有事务,一种解决办法就是 加上 @Transactional 以及@Modify这两个注解才能让删除是真的删除。

发布了65 篇原创文章 · 获赞 48 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/chen15369337607/article/details/103503656
今日推荐