Spring-Tx
传播行为
propagation 提交 异常 捕获 后异常 required (rollbackOnly) do nothing / commit setRollbackOnly / rollback setRollbackOnly / rollback required_new (isNewTransaction) commit / commit rollback / rollback rollback / commit commit / rollback nested (savePoint) releaseSavepoint / commit rollbackToSavepoint & releaseSavepoint / rollback rollbackToSavepoint & releaseSavePoint / commit
REQUIRED
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。
本质上是同一个事务
提交:什么也不做
异常传递:rollbackOnly = true
异常捕获:rollbackOnly = true
REQUIRED_NEW
新建事务,如果当前存在事务,把当前事务挂起。
提交:isNewTx = true 提交
异常传递:rollback / rollback
异常捕获:rollback / commit
异常后捕:commit / rollback
A、B不可操作同一条记录,因为处于不同事务中,会产生死锁。
NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
提交:releaseSavepoint / commit
异常传递:rollbackToSavepoint & releaseSavepoint / rollback
异常捕获:rollbackToSavepoint & releaseSavepoint / commit
A、B可操作同一条记录,因为处于同一个事务中。
SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
提交:
异常捕获:
异常传递:
MANDATORY
使用当前的事务,如果当前没有事务,就抛出异常。
提交:
异常捕获:
异常传递:
NOT_SUPPORTS
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
提交:
异常捕获:
异常传递:
NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
提交:
异常捕获:
异常传递:
核心代码-AOP
TransactionInfo txInfo = createTransactionIfNecessary ( tm, txAttr, joinpointIdentification) ;
Object retVal = null ;
try {
retVal= invocation. proceedWithInvocation ( ) ;
} catch ( Throwable ex) {
completeTransactionAfterThrowing ( txInfo, ex) ;
throw ex;
} finally {
cleanupTransactionInfo ( txInfo) ;
}
commitTransactionAfterReturning ( txInfo) ;
return retVal;
回滚事务
if ( status. hasSavepoint ( ) ) {
if ( status. isDebug ( ) ) {
logger. debug ( "Rolling back transaction to savepoint" ) ;
}
status. rollbackToHeldSavepoint ( ) ;
}
else if ( status. isNewTransaction ( ) ) {
if ( status. isDebug ( ) ) {
logger. debug ( "Initiating transaction rollback" ) ;
}
doRollback ( status) ;
}
else if ( status. hasTransaction ( ) ) {
if ( status. isLocalRollbackOnly ( ) || isGlobalRollbackOnParticipationFailure ( ) ) {
if ( status. isDebug ( ) ) {
logger. debug ( "Participating transaction failed - marking existing transaction as rollback-only" ) ;
}
doSetRollbackOnly ( status) ;
}
else {
if ( status. isDebug ( ) ) {
logger. debug ( "Participating transaction failed - letting transaction originator decide on rollback" ) ;
}
}
}
提交事务-01
DefaultTransactionStatus defStatus = ( DefaultTransactionStatus ) status;
if ( defStatus. isLocalRollbackOnly ( ) ) {
if ( defStatus. isDebug ( ) ) {
logger. debug ( "Transactional code has requested rollback" ) ;
}
processRollback ( defStatus) ;
return ;
}
if ( ! shouldCommitOnGlobalRollbackOnly ( ) && defStatus. isGlobalRollbackOnly ( ) ) {
if ( defStatus. isDebug ( ) ) {
logger. debug ( "Global transaction is marked as rollback-only but transactional code requested commit" ) ;
}
processRollback ( defStatus) ;
if ( status. isNewTransaction ( ) || isFailEarlyOnGlobalRollbackOnly ( ) ) {
throw new UnexpectedRollbackException ( "Transaction rolled back because it has been marked as rollback-only" ) ;
}
return ;
}
processCommit ( defStatus) ;
提交事务-02
if ( status. isNewTransaction ( ) || isFailEarlyOnGlobalRollbackOnly ( ) ) {
globalRollbackOnly = status. isGlobalRollbackOnly ( ) ;
}
if ( status. hasSavepoint ( ) ) {
if ( status. isDebug ( ) ) {
logger. debug ( "Releasing transaction savepoint" ) ;
}
status. releaseHeldSavepoint ( ) ;
}
else if ( status. isNewTransaction ( ) ) {
if ( status. isDebug ( ) ) {
logger. debug ( "Initiating transaction commit" ) ;
}
doCommit ( status) ;
}
测试代码
package center. leon. springtx ;
import center. leon. springtx. service. TxAService ;
import lombok. extern. slf4j. Slf4j ;
import org. springframework. aop. framework. autoproxy. InfrastructureAdvisorAutoProxyCreator ;
import org. springframework. boot. SpringApplication ;
import org. springframework. boot. autoconfigure. SpringBootApplication ;
import org. springframework. context. ConfigurableApplicationContext ;
import org. springframework. transaction. annotation. AnnotationTransactionAttributeSource ;
import org. springframework. transaction. annotation. EnableTransactionManagement ;
import org. springframework. transaction. event. TransactionalEventListenerFactory ;
import org. springframework. transaction. interceptor. BeanFactoryTransactionAttributeSourceAdvisor ;
import org. springframework. transaction. interceptor. TransactionInterceptor ;
@Slf4j
@EnableTransactionManagement
@SpringBootApplication
public class SpringTxApplication {
public static void main ( String [ ] args) {
ConfigurableApplicationContext run = SpringApplication . run ( SpringTxApplication . class , args) ;
final InfrastructureAdvisorAutoProxyCreator infrastructureAdvisorAutoProxyCreator = run. getBean ( InfrastructureAdvisorAutoProxyCreator . class ) ;
assert null != infrastructureAdvisorAutoProxyCreator;
final TransactionalEventListenerFactory transactionalEventListenerFactory = run. getBean ( TransactionalEventListenerFactory . class ) ;
assert null != transactionalEventListenerFactory;
final AnnotationTransactionAttributeSource annotationTransactionAttributeSource = run. getBean ( AnnotationTransactionAttributeSource . class ) ;
assert null != annotationTransactionAttributeSource;
final TransactionInterceptor transactionInterceptor = run. getBean ( TransactionInterceptor . class ) ;
assert null != transactionInterceptor;
final BeanFactoryTransactionAttributeSourceAdvisor beanFactoryTransactionAttributeSourceAdvisor = run. getBean ( BeanFactoryTransactionAttributeSourceAdvisor . class ) ;
assert null != beanFactoryTransactionAttributeSourceAdvisor;
final TxAService txAService = run. getBean ( TxAService . class ) ;
txAService. truncateTable ( ) ;
txAService. required_commit_NoTx_commit ( ) ;
try {
txAService. required_commit_NoTx_Ex ( ) ;
} catch ( Exception e) {
}
txAService. required_commit_Required_commit ( ) ;
try {
txAService. required_commit_Required_Ex ( ) ;
} catch ( Exception e) {
}
try {
txAService. required_commit_Required_Ex_Caught ( ) ;
} catch ( Exception e) {
}
txAService. required_commit_Required_New_Commit ( ) ;
try {
txAService. required_commit_Required_New_Ex ( ) ;
} catch ( Exception e) {
}
txAService. required_commit_Required_New_Ex_Caught ( ) ;
try {
txAService. required_Ex_Required_New_commit ( ) ;
} catch ( Exception e) {
}
txAService. required_commit_Required_Nested_Commit ( ) ;
try {
txAService. required_commit_Required_Nested_Ex ( ) ;
} catch ( Exception e) {
}
txAService. required_commit_Required_Nested_Ex_Caught ( ) ;
txAService. required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid ( ) ;
txAService. required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid ( ) ;
System . out. println ( "天地英雄气,千秋尚凛然" ) ;
}
}
ServiceA Interface
package center. leon. springtx. service ;
public interface TxAService {
void truncateTable ( ) ;
void required_commit_NoTx_commit ( ) ;
void required_commit_NoTx_Ex ( ) ;
void required_commit_Required_commit ( ) ;
void required_commit_Required_Ex ( ) ;
void required_commit_Required_Ex_Caught ( ) ;
void required_commit_Required_New_Commit ( ) ;
void required_commit_Required_New_Ex ( ) ;
void required_commit_Required_New_Ex_Caught ( ) ;
void required_Ex_Required_New_commit ( ) ;
void required_commit_Required_Nested_Commit ( ) ;
void required_commit_Required_Nested_Ex ( ) ;
void required_commit_Required_Nested_Ex_Caught ( ) ;
void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid ( ) ;
void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this ( String name) ;
void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid ( ) ;
void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring ( String name) ;
}
ServiceAImpl Class
package center. leon. springtx. service. impl ;
import center. leon. springtx. dao. MonkeyDao ;
import center. leon. springtx. mapper. MonkeyMapper ;
import center. leon. springtx. service. TxAService ;
import center. leon. springtx. service. TxBService ;
import lombok. extern. slf4j. Slf4j ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Service ;
import org. springframework. transaction. annotation. Propagation ;
import org. springframework. transaction. annotation. Transactional ;
@Service
@Slf4j
public class TxAServiceImpl implements TxAService {
@Autowired
private TxBService txBService;
@Autowired
private MonkeyDao monkeyDao;
@Autowired
private MonkeyMapper monkeyMapper;
@Autowired
private TxAService txAService;
@Override
public void truncateTable ( ) {
monkeyMapper. truncateTable ( ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_NoTx_commit ( ) {
monkeyDao. insert ( "required_commit_NoTx_commit_A" ) ;
txBService. required_commit_NoTx_commit ( "required_commit_NoTx_commit_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_NoTx_Ex ( ) {
monkeyDao. insert ( "required_commit_NoTx_Ex_A" ) ;
txBService. required_commit_NoTx_Ex ( "required_commit_NoTx_Ex_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_commit ( ) {
monkeyDao. insert ( "required_commit_Required_commit_A" ) ;
txBService. required_commit_Required_commit ( "required_commit_Required_commit_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Ex ( ) {
monkeyDao. insert ( "required_commit_Required_Ex_A" ) ;
txBService. required_commit_Required_Ex ( "required_commit_Required_Ex_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Ex_Caught ( ) {
monkeyDao. insert ( "required_commit_Required_Ex_Caught_A" ) ;
try {
txBService. required_commit_Required_Ex_Caught ( "required_commit_Required_Ex_Caught_B" ) ;
} catch ( Exception e) {
log. info ( "required_commit_Required_Ex_Caught_B. error : {}" , e. getMessage ( ) , e) ;
}
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_New_Commit ( ) {
monkeyDao. insert ( "required_commit_Required_New_Commit_A" ) ;
txBService. required_commit_Required_New_Commit ( "required_commit_Required_New_Commit_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_New_Ex ( ) {
monkeyDao. insert ( "required_commit_Required_New_Ex_A" ) ;
txBService. required_commit_Required_New_Ex ( "required_commit_Required_New_Ex_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_New_Ex_Caught ( ) {
monkeyDao. insert ( "required_commit_Required_New_Ex_Caught_A" ) ;
try {
txBService. required_commit_Required_New_Ex_Caught ( "required_commit_Required_New_Ex_Caught_B" ) ;
} catch ( Exception e) {
log. info ( "required_commit_Required_New_Ex_Caught_B : {}" , e. getMessage ( ) , e) ;
}
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_Ex_Required_New_commit ( ) {
monkeyDao. insert ( "required_Ex_Required_New_commit_A" ) ;
txBService. required_Ex_Required_New_commit ( "required_Ex_Required_New_commit_B" ) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Nested_Commit ( ) {
monkeyDao. insert ( "required_commit_Required_Nested_Commit_A" ) ;
txBService. required_commit_Required_Nested_Commit ( "required_commit_Required_Nested_Commit_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Nested_Ex ( ) {
monkeyDao. insert ( "required_commit_Required_Nested_Ex_A" ) ;
txBService. required_commit_Required_Nested_Ex ( "required_commit_Required_Nested_Ex_B" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Nested_Ex_Caught ( ) {
monkeyDao. insert ( "required_commit_Required_Nested_Ex_Caught_A" ) ;
try {
txBService. required_commit_Required_Nested_Ex_Caught ( "required_commit_Required_Nested_Ex_Caught_B" ) ;
} catch ( Exception e) {
log. info ( "required_commit_Required_Nested_Ex_Caught_B. error : {}" , e. getMessage ( ) , e) ;
}
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid ( ) {
monkeyDao. insert ( "required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_A" ) ;
this . required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this ( "required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . NEVER)
public void required_commit_or_ex_catch_This_Any_propagation_commit_or_ex_or_caught_is_invalid_this ( String name) {
monkeyDao. insert ( name) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid ( ) {
monkeyDao. insert ( "required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_A" ) ;
txAService. required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring ( "required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring" ) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . NEVER)
public void required_commit_or_ex_catch_Spring_Any_propagation_commit_or_ex_or_caught_invalid_Spring ( String name) {
monkeyDao. insert ( name) ;
}
}
ServiceB Interface
package center. leon. springtx. service ;
public interface TxBService {
void required_commit_NoTx_commit ( String name) ;
void required_commit_NoTx_Ex ( String name) ;
void required_commit_Required_commit ( String name) ;
void required_commit_Required_Ex ( String name) ;
void required_commit_Required_Ex_Caught ( String name) ;
void required_commit_Required_New_Commit ( String name) ;
void required_commit_Required_New_Ex ( String name) ;
void required_commit_Required_New_Ex_Caught ( String name) ;
void required_Ex_Required_New_commit ( String name) ;
void required_commit_Required_Nested_Commit ( String name) ;
void required_commit_Required_Nested_Ex ( String name) ;
void required_commit_Required_Nested_Ex_Caught ( String name) ;
}
ServiceBImpl Class
package center. leon. springtx. service. impl ;
import center. leon. springtx. dao. MonkeyDao ;
import center. leon. springtx. service. TxBService ;
import org. springframework. beans. factory. annotation. Autowired ;
import org. springframework. stereotype. Service ;
import org. springframework. transaction. annotation. Propagation ;
import org. springframework. transaction. annotation. Transactional ;
@Service
public class TxBServiceImpl implements TxBService {
@Autowired
private MonkeyDao monkeyDao;
@Override
public void required_commit_NoTx_commit ( String name) {
monkeyDao. insert ( name) ;
}
@Override
public void required_commit_NoTx_Ex ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_commit ( String name) {
monkeyDao. insert ( name) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Ex ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRED)
public void required_commit_Required_Ex_Caught ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRES_NEW)
public void required_commit_Required_New_Commit ( String name) {
monkeyDao. insert ( name) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRES_NEW)
public void required_commit_Required_New_Ex ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRES_NEW)
public void required_commit_Required_New_Ex_Caught ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . REQUIRES_NEW)
public void required_Ex_Required_New_commit ( String name) {
monkeyDao. insert ( name) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . NESTED)
public void required_commit_Required_Nested_Commit ( String name) {
monkeyDao. insert ( name) ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . NESTED)
public void required_commit_Required_Nested_Ex ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
@Override
@Transactional ( rollbackFor = Exception . class , propagation = Propagation . NESTED)
public void required_commit_Required_Nested_Ex_Caught ( String name) {
monkeyDao. insert ( name) ;
int i = 0 / 0 ;
}
}