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;
말 그대로 이 속성 은 업무 가 상호작용 을 할 때 유효 합 니 다.그렇다면 어떻게 발 효 됐 을 까?핵심 소스 코드 는
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
		}
	}
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);
	}
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 사무 전파 특성 에 관 한 내용 은 예전 의 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.