트랜잭션 전파(Propagation)는 메서드가 기존 트랜잭션을 유지할지, 새로운 트랜잭션을 생성할지, 아니면 트랜잭션 없이 실행할지를 결정하는 정책
@Transactional(propagation = Propagation.REQUIRED)
REQUIRED (기본값): 기존 트랜잭션이 있으면 참여, 없으면 새 트랜잭션 생성REQUIRES_NEW: 기존 트랜잭션을 무시하고 항상 새로운 트랜잭션 생성SUPPORTS: 트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행NOT_SUPPORTED: 트랜잭션을 사용하지 않고 실행MANDATORY: 기존 트랜잭션이 있어야 실행 (없으면 예외 발생)NEVER: 트랜잭션 없이 실행 (기존 트랜잭션이 있으면 예외 발생)NESTED: 기존 트랜잭션이 있으면 중첩 트랜잭션 사용 (저장점 SAVEPOINT 생성)@Service
public class ParentService {
@Autowired
private ChildService childService;
@Transactional(propagation = Propagation.REQUIRED)
public void parentMethod() {
saveParentData();
childService.childMethod(); // 같은 트랜잭션에 포함됨
}
}
@Service
public class ChildService {
@Transactional(propagation = Propagation.REQUIRED) // 기본값
public void childMethod() {
saveChildData(); // parentMethod와 같은 트랜잭션
}
}
@Service
public class ParentService {
@Autowired
private ChildService childService;
@Transactional
public void parentMethod() {
saveParentData();
try {
childService.childMethod(); // 별도 트랜잭션
} catch (Exception e) {
// 예외 처리
}
}
}
@Service
public class ChildService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void childMethod() {
saveChildData();
throw new RuntimeException("예외 발생!"); // 여기서 예외가 발생해도 부모 트랜잭션 영향 X
}
}
@Service
public class ParentService {
@Autowired
private ChildService childService;
@Transactional
public void parentMethod() {
saveParentData();
try {
childService.childMethod();
} catch (Exception e) {
// 자식 트랜잭션만 롤백됨
}
}
}
@Service
public class ChildService {
@Transactional(propagation = Propagation.NESTED)
public void childMethod() {
saveChildData();
throw new RuntimeException("예외 발생!"); // SAVEPOINT까지 롤백
}
}
IllegalTransactionStateException 발생@Service
public class SomeService {
// 해당 메서드는 반드시 부모 트랜잭션이 존재한 상태로 호출돼야 함
@Transactional(propagation = Propagation.MANDATORY)
public void someMethod() {
saveData();
}
}
@Service
public class SomeService {
// 해당 메서드는 반드시 부모 트랜잭션이 없는 상태로 호출돼야 함
@Transactional(propagation = Propagation.NEVER)
public void someMethod() {
saveData();
}
}