preface
Transaction is one or more database operations that need to ensure atomicity, isolation, consistency and persistence at the same time
This article will explain the implementation methods of two transactions in springBoot, programming transaction configuration and declarative transaction configuration, as well as aspect transactions. Of course, before that, we will talk about some basic things: the four characteristics of transactions, the isolation level of transactions, and the propagation behavior of transactions
Four characteristics of transactions (ACID)
- Atomicity: all operations in a transaction are inseparable in the database, either all or none
- Consistency: for several transactions executed in parallel, the execution result must be consistent with the result of serial execution in a certain order
- Isolation: the execution of a transaction is not disturbed by other transactions. The intermediate results of transaction execution must be transparent to other transactions
- Persistence: for any committed transaction, the system must ensure that the changes made to the database by the transaction are not lost
Open transaction
@EnableTransactionManagement
SpringBoot declarative transaction
Declarative transaction @ Transactional can be used on classes or public methods. If it is used on classes, transactions will be enabled for all public methods. If there are transactions on classes and methods, transactions on methods will take effect
Can be used on classes
@Transactional(rollbackFor=Exception.class) public class TransactionServiceImpl implements TransactionService { }
It is more used in methods
@Override @Transactional(rollbackFor=Exception.class) public void t1(Student one) { }
@Parameters for Transactional
Some of its parameters are used when using @ Transactional
parameter | effect |
value | When multiple transaction managers are configured, you can use this attribute to specify which transaction manager to select |
transactionManager | When multiple transaction managers are configured, you can use this attribute to specify which transaction manager to select |
propagation | Propagation behavior of transactions. The default value is Propagation.REQUIRED |
isolation | The isolation level of the transaction. The default value is Isolation.DEFAULT |
timeout | The timeout of the transaction. The default value is - 1. If the time limit is exceeded but the transaction has not completed, the transaction will be rolled back automatically |
readOnly | Specifies whether the transaction is read-only. The default value is false; To ignore methods that do not require transactions, such as reading data, you can set read only to true |
rollbackFor | Used to specify exception types that can trigger transaction rollback. Multiple exception types can be specified |
rollbackForClassName | Used to specify exception types that can trigger transaction rollback. Multiple exception types can be specified |
noRollbackFor | Throw the specified exception type, do not roll back the transaction, or specify multiple exception types |
noRollbackForClassName | Throw the specified exception type, do not roll back the transaction, or specify multiple exception types |
value is the same as transactionManager. rollbackFor and rollbackForClassName are the same. noRollbackFor and noRollbackForClassName are the same
Isolation level of transaction
Isolation level is used in isolation
parameter | Transaction isolation level | Dirty reading | Non repeatable reading | Unreal reading |
READ_UNCOMMITTED | Read uncommitted | yes | yes | yes |
READ_COMMITTED | Read committed | no | yes | yes |
REPEATABLE_READ | Repeatable read | no | no | yes |
SERIALIZABLE | serializable | no | no | no |
Propagation of transactions
Propagation will use this propagation script
Communication behavior | explain |
REQUIRED | If there is a transaction, join it. If there is no transaction, create a new transaction |
SUPPORTS | If a transaction currently exists, join the transaction; If no transaction currently exists, it continues to run in a non - transactional manner |
MANDATORY | If a transaction currently exists, join the transaction; Throw an exception if no transaction currently exists |
REQUIRES_NEW | Recreate a new transaction. If there is a current transaction, pause the current transaction |
NOT_SUPPORTED | Run in a non - transactional manner. If a transaction currently exists, suspend the current transaction |
NEVER | Run in a non - transactional manner and throw an exception if a transaction currently exists |
NESTED | It has the same effect as REQUIRED |
SpringBoo programmatic transaction
Inject TransactionTemplate where needed
@Autowired private TransactionTemplate transactionTemplate;
Then use it in your code
@Override public final void save2() { transactionTemplate.execute((status)->{ mapper.saveStudent(newOne()); mapper.saveStudent(newOne()); return Boolean.TRUE; }); }
These two mappers. Savestudent (newone()); Executed in one transaction
SpringBoo faceted programmatic transactions
This method is based on AOP function, so it needs to be added
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
Write configuration class
@Aspect @Configuration public class MyTransactionConfig { /** * Configure method expiration time, default - 1, never timeout */ private final static int TX_METHOD_TIME_OUT = 10; /** * The global transaction location configures where transactions are required * Configure pointcut expressions */ private static final String POITCUT_EXPRESSION = "execution(* zdc.enterprise.service.impl.*.*(..))"; @Autowired private PlatformTransactionManager platformTransactionManager; @Bean public TransactionInterceptor txadvice() { /*Read only things, do not update and delete, etc*/ /*Transaction management rules*/ RuleBasedTransactionAttribute readOnlyRule = new RuleBasedTransactionAttribute(); /*Set whether the current transaction is read-only. true is read-only*/ readOnlyRule.setReadOnly(true); /* transactiondefinition Define the isolation level of transactions; *If a transaction currently exists, join the transaction; If there are currently no transactions, continue to run in a non transactional manner.*/ readOnlyRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS); /*Add, delete and modify transaction rules*/ RuleBasedTransactionAttribute requireRule = new RuleBasedTransactionAttribute(); /*Execute pointcut rollback after throwing an exception. It is recommended to customize the exception*/ requireRule.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class))); /*PROPAGATION_REQUIRED:The transaction isolation is 1. If there is a current transaction, join the transaction; If there is no current transaction, a new transaction is created. This is the default. */ requireRule.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); /*Set the transaction expiration time, which exceeds 10 seconds*/ requireRule.setTimeout(TX_METHOD_TIME_OUT); /** Configure transaction management rules nameMap Declare a method name that needs to manage a transaction Here we use addTransactionalMethod and setNameMap */ Map<String, TransactionAttribute> nameMap = new HashMap<>(); nameMap.put("add*", requireRule); nameMap.put("save*", requireRule); nameMap.put("insert*", requireRule); nameMap.put("update*", requireRule); nameMap.put("delete*", requireRule); nameMap.put("remove*", requireRule); /*During batch operation*/ nameMap.put("batch*", requireRule); nameMap.put("get*", readOnlyRule); nameMap.put("query*", readOnlyRule); nameMap.put("find*", readOnlyRule); nameMap.put("select*", readOnlyRule); nameMap.put("count*", readOnlyRule); NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource(); source.setNameMap(nameMap); TransactionInterceptor transactionInterceptor = new TransactionInterceptor(platformTransactionManager, source); return transactionInterceptor; } /** * Set tangent = tangent pointcut + notification TxAdvice * @return */ @Bean public Advisor txAdviceAdvisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression(POITCUT_EXPRESSION); return new DefaultPointcutAdvisor(pointcut, txadvice()); } }
With this aspect configuration class, don't use @ Transactional on the class or each method. Of course, the prefix of the method name should match the setting
The parameters of RuleBasedTransactionAttribute are roughly the same as those of @ Transactional. There are detailed comments in it, but there is no more explanation
END
The granularity of faceted transactions is the coarsest. If the method names do not match, it is easy to leak methods. The granularity of declarative transactions is medium, but problems will occur in case of large transactions. The granularity of programming transactions is the smallest. You can consider using it at special times