Spring 소스 코드 분석 트 랜 잭 션 전파 특성

사용 방법
Transactional 을 사용 하여 propagation 을 설정 하면 됩 니 다.
열기org.springframework.transaction.annotation.Transactional를 통 해 알 수 있 듯 이 기본 전파 특성 은REQUIRED입 니 다.

/**
	 * The transaction propagation type.
	 * <p>Defaults to {@link Propagation#REQUIRED}.
	 * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
	 */
	Propagation propagation() default Propagation.REQUIRED;
2.getTransaction
말 그대로 이 속성 은 업무 가 상호작용 을 할 때 유효 합 니 다.그렇다면 어떻게 발 효 됐 을 까?핵심 소스 코드 는org.springframework.transaction.support.AbstractPlatformTransactionManager에 있다.핵심 입 구 는 getTransaction 방법 입 니 다.

@Override
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
		Object transaction = doGetTransaction();

		// Cache debug flag to avoid repeated checks.
		boolean debugEnabled = logger.isDebugEnabled();

		//
		if (definition == null) {
			// Use defaults if no transaction definition given.
			definition = new DefaultTransactionDefinition();
		}

		//                   
		if (isExistingTransaction(transaction)) {
			// Existing transaction found -> check propagation behavior to find out how to behave.
			return handleExistingTransaction(definition, transaction, debugEnabled);
		}
		// Check definition settings for new transaction.
		if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
			throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
		}

		// No existing transaction found -> check propagation behavior to find out how to proceed.
		//        MANDATORY       
		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		//REQUIRED  REQUIRES_NEW NESTED        
		else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
				logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
			}
			try {
				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
				DefaultTransactionStatus status = newTransactionStatus(
						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
				doBegin(transaction, definition);
				prepareSynchronization(status, definition);
				return status;
			}
			catch (RuntimeException | Error ex) {
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
			xxx
		}
	}
현재 업무 가 존재 하지 않 을 때,
  • MANDATORY 직접 이상 던 지기
  • REQUIRED REQUIRES_NEW NESTED 에서 자동 으로 새 트 랜 잭 션 을 만 듭 니 다.
  • 그렇다면 업무 가 존재 할 때 어떻게 처리 합 니까?
    3.handleExistingTransaction
    
    /**
    	 *            
    	 * Create a TransactionStatus for an existing transaction.
    	 */
    	private TransactionStatus handleExistingTransaction(
    			TransactionDefinition definition, Object transaction, boolean debugEnabled)
    			throws TransactionException {
    
    		//NEVER              
    		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
    			throw new IllegalTransactionStateException(
    					"Existing transaction found for transaction marked with propagation 'never'");
    		}
    
    		//NOT_SUPPORTED   prepareTransactionStatus                null,            。         。
    		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
    			if (debugEnabled) {
    				logger.debug("Suspending current transaction");
    			}
    			Object suspendedResources = suspend(transaction);
    			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
    			return prepareTransactionStatus(
    					definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    		}
    
    
    		//REQUIRES_NEW             
    		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
    			if (debugEnabled) {
    				logger.debug("Suspending current transaction, creating new transaction with name [" +
    						definition.getName() + "]");
    			}
    			SuspendedResourcesHolder suspendedResources = suspend(transaction);
    			try {
    				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    				DefaultTransactionStatus status = newTransactionStatus(
    						definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
    				doBegin(transaction, definition);
    				prepareSynchronization(status, definition);
    				return status;
    			}
    			catch (RuntimeException | Error beginEx) {
    				resumeAfterBeginException(transaction, suspendedResources, beginEx);
    				throw beginEx;
    			}
    		}
    
    		//NESTED       
    		if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
    			//           
    			if (!isNestedTransactionAllowed()) {
    				throw new NestedTransactionNotSupportedException(
    						"Transaction manager does not allow nested transactions by default - " +
    						"specify 'nestedTransactionAllowed' property with value 'true'");
    			}
    			if (debugEnabled) {
    				logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
    			}
    			//        Savepoint                  
    			if (useSavepointForNestedTransaction()) {
    				// Create savepoint within existing Spring-managed transaction,
    				// through the SavepointManager API implemented by TransactionStatus.
    				// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
    				DefaultTransactionStatus status =
    						prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
    				//       savePoint
    				status.createAndHoldSavepoint();
    				return status;
    			}
    			else {
    				// Nested transaction through nested begin and commit/rollback calls.
    				// Usually only for JTA: Spring synchronization might get activated here
    				// in case of a pre-existing JTA transaction.
    				boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    				//     newTransaction     true,                 
    				DefaultTransactionStatus status = newTransactionStatus(
    						definition, transaction, true, newSynchronization, debugEnabled, null);
    				doBegin(transaction, definition);
    				prepareSynchronization(status, definition);
    				return status;
    			}
    		}
    		// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
    		if (debugEnabled) {
    			logger.debug("Participating in existing transaction");
    		}
    		if (isValidateExistingTransaction()) {
    			if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
    				Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
    				if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
    					Constants isoConstants = DefaultTransactionDefinition.constants;
    					throw new IllegalTransactionStateException("Participating transaction with definition [" +
    							definition + "] specifies isolation level which is incompatible with existing transaction: " +
    							(currentIsolationLevel != null ?
    									isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
    									"(unknown)"));
    				}
    			}
    			if (!definition.isReadOnly()) {
    				if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
    					throw new IllegalTransactionStateException("Participating transaction with definition [" +
    							definition + "] is not marked as read-only but existing transaction is");
    				}
    			}
    		}
    		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    		//                       
    		return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
    	}
    
    이미 사무 가 존재 할 때,
  • NEVER 가 직접 오 류 를 보고 하고 사 무 를 지원 하지 않 습 니 다
  • NOT_지원 은 묵묵히 비사 무 방식 으로 실행
  • REQUIRES_NEW 새 트 랜 잭 션 입 니 다.
  • NESTED 는 내장 사 무 를 처리 할 때 상황 에 따라 savePoint 또는 새 사 무 를 사용 합 니 다.
  • 기타 가입 현재 사무
  • 4.NESTED 내장 사무
    SavePoint
    SavePoint 메커니즘 부터 간단히 말씀 드 리 겠 습 니 다.이것 도 쉬 워 요.
    예 를 들 어 한 가지 일이 비교적 복잡 해서 실 수 를 하기 쉽다.그러면 현재 DB 가 SavePoint 를 지원 한다 면 SavePoint 를 만 드 는 것 은 스냅 샷 을 만 드 는 것 과 같 습 니 다.매번 모든 업 무 를 스크롤 하지 않 고 지정 한 SavePoint 로 스크롤 하면 됩 니 다.
    개인 이해
    NESTED 는 이 처리 가 확실히 복잡 하 다.개인 적 으로 도 많은 자 료 를 찾 아 봤 습 니 다.현재 개인 은 현재 다음 과 같이 이해 합 니 다.
    NESTED 의 업무 처 리 는 주로 등급 이 다르다 는 데 있다.
    REQUIRES_NEW 가 만 든 두 사 무 는 동급 입 니 다.한 업무 의 성공 여 부 는 다른 업무 의 성공 여부 에 영향 을 주지 않 습 니 다.
    한편,NESTED 가 만 든 사 무 는 명실상부 하고 아버지 급 업무 의 영향 을 받는다.
    한 마디 로 하면 서브 업무 의 성공 여 부 는 아버지 급 업무 의 성공 에 영향 을 주지 않 지만 아버지 급 업무 의 성공 과 그렇지 않 으 면 서브 업무 의 성공 에 영향 을 줄 수 있다 는 것 이다.
    아버지 일 은 다시 굴 러 가 고,아들 일 은 반드시 굴 러 갈 것 이다.
    자식 이 다시 굴 러 가면 아버지의 일이 반드시 굴 러 가 는 것 은 아니다.
    총화
    마지막 으로 다음 과 같이 요약 한다.
    명칭.
    설명 하 다.
    PROPAGATION_REQUIRED
    방법 이 호출 될 때 자동 으로 트 랜 잭 션 을 시작 하고 트 랜 잭 션 범위 내 에서 사용 하면 같은 트 랜 잭 션 을 사용 합 니 다.그렇지 않 으 면 새로운 트 랜 잭 션 을 시작 합 니 다.기본 설정.
    PROPAGATION_SUPPORTS
    현재 트 랜 잭 션 을 지원 합 니 다.현재 트 랜 잭 션 이 없 으 면 비 트 랜 잭 션 으로 실 행 됩 니 다.
    PROPAGATION_MANDATORY
    현재 트 랜 잭 션 을 지원 합 니 다.현재 트 랜 잭 션 이 없 으 면 이상 을 던 집 니 다.
    PROPAGATION_REQUIRES_NEW
    새 트 랜 잭 션,현재 트 랜 잭 션 이 존재 하면 현재 트 랜 잭 션 을 걸 어 놓 습 니 다.
    PROPAGATION_NOT_SUPPORTED
    비 사무 방식 으로 작업 을 수행 합 니 다.현재 사무 가 존재 하면 현재 사 무 를 걸 어 놓 습 니 다.
    PROPAGATION_NEVER
    비 사무 방식 으로 실행 되 며,현재 사무 가 존재 한다 면 이상 을 던 집 니 다.
    PROPAGATION_NESTED
    활성 화 된 트 랜 잭 션 이 존재 하면 포 함 된 트 랜 잭 션 에서 실 행 됩 니 다.활성 화 된 트 랜 잭 션 이 없 으 면 TransactionDefinition.PROPAGATION 을 누 르 십시오.REQUIRED 속성 이 실 행 됩 니 다.JDBC 3.0 이상 의 지원 이 필요 합 니 다.
    여기 서 Spring 소스 코드 해석 의 사무 전파 특성 에 관 한 글 은 여기까지 소개 되 었 습 니 다.더 많은 Spring 사무 전파 특성 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부탁드립니다!

    좋은 웹페이지 즐겨찾기