编程知识 cdmana.com

Spring boot global transaction configuration

I found a lot of open source springBoot project , The use of transactions is Use it directly Business note . There is no global transaction configured .
In fact, at present, not new programmers think Transactions can only be controlled by adding solutions . Never heard of global transaction configuration .
Many global affairs on the Internet are not good enough . It's all copied back and forth . I really don't know if it can be used .
In fact, this is not good .

  1. When you write code, if you omit to add transaction annotations , It's terrible not to roll back that exception
  2. If you need to manually annotate when you write code , It's a lot of trouble . It's much easier to configure global transaction annotations .

Configuration code


package com.door.config;

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.*;

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

/**  Global transaction control , Prevent omission   Business note , In other words, there is no need to add transaction annotation in development  */
@Configuration
@Aspect
public class TransactionConfig {
  private static final int TX_METHOD_TIMEOUT = 60;

  private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.door..service..*(..))";

  @Autowired private PlatformTransactionManager transactionManager;

  @Bean
  public TransactionInterceptor txAdvice() {
    NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();

    RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
    readOnly.setReadOnly(true);
    readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

    //  Don't use this kind of  . This can lead to   Read only transactions do not work . and   Sure   In the code   Commit transaction 
    //    readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);

    RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
    required.setRollbackRules(
        Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
    required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

    //  The unit is   second 
    required.setTimeout(TX_METHOD_TIMEOUT);
    Map<String, TransactionAttribute> txMap = new HashMap<>(50);
    txMap.put("add*", required);
    txMap.put("save*", required);
    txMap.put("insert*", required);
    txMap.put("update*", required);
    txMap.put("delete*", required);
    txMap.put("create*", required);
    txMap.put("init*", required);
    txMap.put("submit*", required);
    txMap.put("remove*", required);
    txMap.put("edit*", required);
    txMap.put("modify*", required);
    txMap.put("batch*", required);
    txMap.put("mass*", required);
    txMap.put("handle*", required);
    txMap.put("exec*", required);
    txMap.put("import*", required);
    txMap.put("set*", required);

    txMap.put("get*", readOnly);
    txMap.put("select*", readOnly);
    txMap.put("list*", readOnly);
    txMap.put("query*", readOnly);
    txMap.put("find*", readOnly);
    txMap.put("count*", readOnly);
    txMap.put("page*", readOnly);
    txMap.put("all*", readOnly);
    txMap.put("*", readOnly);

    source.setNameMap(txMap);
    return new TransactionInterceptor(transactionManager, source);
  }

  //  @Bean  It's not good enough , Cannot configure rollback exception .  In fact, and the way above   The principle is the same .
  //  public TransactionInterceptor txAdvice() {
  //
  //    DefaultTransactionAttribute txAttr_REQUIRED = new DefaultTransactionAttribute();
  //    txAttr_REQUIRED.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  //    txAttr_REQUIRED.setTimeout(TX_METHOD_TIMEOUT);
  //
  //    DefaultTransactionAttribute txAttr_REQUIRED_READONLY = new DefaultTransactionAttribute();
  //    txAttr_REQUIRED_READONLY.setPropagationBehavior(
  //        TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
  //    txAttr_REQUIRED_READONLY.setReadOnly(true);
  //
  //    NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
  //    source.addTransactionalMethod("add*", txAttr_REQUIRED);
  //    source.addTransactionalMethod("save*", txAttr_REQUIRED);
  //    source.addTransactionalMethod("delete*", txAttr_REQUIRED);
  //    source.addTransactionalMethod("update*", txAttr_REQUIRED);
  //    source.addTransactionalMethod("exec*", txAttr_REQUIRED);
  //    source.addTransactionalMethod("set*", txAttr_REQUIRED);
  //
  //    //    source.addTransactionalMethod("get*", txAttr_REQUIRED_READONLY);
  //    //    source.addTransactionalMethod("query*", txAttr_REQUIRED_READONLY);
  //    //    source.addTransactionalMethod("find*", txAttr_REQUIRED_READONLY);
  //    //    source.addTransactionalMethod("list*", txAttr_REQUIRED_READONLY);
  //    //    source.addTransactionalMethod("count*", txAttr_REQUIRED_READONLY);
  //    source.addTransactionalMethod("*", txAttr_REQUIRED_READONLY);
  //
  //
  //
  //    return new TransactionInterceptor(transactionManager, source);
  //  }

  @Bean
  public Advisor txAdviceAdvisor() {
    AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
    pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
    return new DefaultPointcutAdvisor(pointcut, txAdvice());
  }
}


TransactionDefinition.PROPAGATION_NOT_SUPPORTED Don't configure

This is how my colleagues used to configure , I haven't noticed before , Test today Read only transactions , It didn't work .
It can still be done in Method Write database operation , And there's no transaction control !!

source.setNameMap(txMap); And addTransactionalMethod It's the same principle

source.setNameMap(txMap); Source code Namely Cycle call addTransactionalMethod Method

A lot of searches are DefaultTransactionAttribute This code , It doesn't define Execption Exception type rollback

xml Global transaction configuration

Not used spring boot Old projects before development , Basic it is Use xml To configure global transaction interception

 <!-- Transaction configuration example -->
    <aop:config proxy-target-class="true">
		<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.skg.crm.*.domain..*(..)) "  />
	</aop:config>  
	
	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
		    <!-- about oracle Come on  read-only="true"  It didn't work ,
		    	 The rollback exception is configured to prevent   Careless use of operation data, exception, no rollback .
		    	 If there is no operation data in the method and an exception occurs , Configuration rollback has no effect    -->
		  	<tx:method name="get*" read-only="true" rollback-for="java.lang.Exception" />
			<tx:method name="is*" read-only="true" rollback-for="java.lang.Exception" />
			<tx:method name="find*" read-only="true" rollback-for="java.lang.Exception" />
			<tx:method name="query*" read-only="true" rollback-for="java.lang.Exception" />
			<tx:method name="*" propagation="REQUIRED" read-only="false" isolation="DEFAULT" rollback-for="java.lang.Exception"/>
		</tx:attributes>
	</tx:advice>
	
	 <!--  Enable annotation support for transaction control ,proxy-target-class="true" Class agent is widely used   -->
	 <!-- order  There is no general configuration , If aop xml  The transaction is configured , The code again uses transaction annotations , Well, it's mainly code annotations .
	  close order  It is to prevent the code from being customized in the future AOP  And that affects transaction annotations aop Abnormal transaction rollback of , Default transaction annotated aop Has the lowest priority .
	  Plus, it's also to tell you clearly spirng  Declarative transaction annotations have the highest priority .
	   -->  
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" order="200"/>

Reference resources

Transaction configuration
Intercept point configuration

版权声明
本文为[The abyss]所创,转载请带上原文链接,感谢

Scroll to Top