When a spring transaction is mentioned, it is reminiscent of four basic characteristics, five isolation levels and seven communication characteristics. I'm sure most people know this, but knowing it's one thing, and using it well is another. When using Spring transactions, I've encountered several serious issues, so I'll make a self-summary here.
Question 1, propagation.NESTED and propagation. REQUIRED_ What is the difference between NEW?
The effect is the same when the caller does not have a transaction. So the premise for discussing this issue here is that the caller has a transaction. PROPAGATION_REQUIRES_NEW starts a new "internal" transaction that is independent of the environment. This transaction will be completely commited or rolled back, independent of external transactions, with its own isolation, its own locks, and so on. When the internal transaction begins to execute, the external transaction is suspended, and when the internal transaction ends, the external transaction continues to execute.
On the other hand, PROPAGATION_NESTED begins a "nested" transaction, which is a true sub-transaction of an existing transaction. When the latent transaction starts executing, it will get a savepoint. If this nested transaction fails, we will roll back to this savepoint. A latent transaction is part of an external transaction and will not be committed until the external transaction has ended.
Thus, PROPAGATION_REQUIRES_NEW and PROPAGATION_ The biggest difference with NESTED is that PROPAGATION_REQUIRES_NEW is a completely new transaction, and PROPAGATION_NESTED is a subtransaction of an external transaction. If the external transaction commit, the nested transaction will also be commit. This rule also applies to roll back.
Q2. Why does @Transactional ly fail?
1. The caller and the callee belong to the same component, and the callee's @Transacational comment is invalid
package com.transacational; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; @Component public class Service { public void test1(){ test2(); } @Transactional//Invalid comment here public void test2(){ } }
2. The callee is not a public method and the callee's @Transacational comment is invalid
@Component public class Service { @Resource private Service1 service1; public void test1(){ test2(); service1.test3(); } @Transactional//1. The comment here is invalid public void test2(){ } }
package com.transacational; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; /** * Created by chenqimiao on 17/10/31. */ @Component public class Service1 { @Transactional//2. The comment here is invalid protected void test3(){ } }
3. Transaction switches are not turned on, such as @EnableTransactionManagement is not used by the startup class in SpringBoot
Q3. How do you understand the @Transactional timeout?
Timeout is a property that allows developers to set timeout times. Default value -1, the time-out is determined by the specific sql system.
/** * Created by chenqimiao on 17/10/31. */ @Component public class Service3 { @Resource private AdminInfoDoMapper adminInfoDoMapper; @Transactional(timeout = 4)//Do not time out public void test4(){ adminInfoDoMapper.selectNameById(1); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } }
Specific definition of timeout: from the beginning of a transaction (before the first code execution of this method) to the end of the last Statement execution
So as you write below, the transaction will time out
@Component public class Service3 { @Resource private AdminInfoDoMapper adminInfoDoMapper; @Transactional(timeout = 4) public void test4(){ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } adminInfoDoMapper.selectNameById(1); } }
Q4. @Transactional Default rollback policy?
By default, transactions roll back only when exceptions to RuntimeException or its subclasses are caught by a transaction. If you want a transaction to roll back all exceptions, you must specify @Transactional(rollbackFor=Exception.class) manually so that inheriting Exception's subclasses or Exception itself can roll back the transaction.