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
}
}
현재 업무 가 존재 하지 않 을 때,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에 따라 라이센스가 부여됩니다.