현재 있는 트랜잭션과 다른 클래스의 트랜잭션이 전파되는 현상을 정리한다.
enum Propagation에서는 다음 7가지를 지원한다.
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED)
SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS)
MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY)
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW)
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)
NEVER(TransactionDefinition.PROPAGATION_NEVER)
NESTED(TransactionDefinition.PROPAGATION_NESTED)
REQUIRED
(TransactionDefinition.PROPAGATION_REQUIRED)
기존에 사용하던 트랜잭션이 있다면 사용하고, 트랜잭션이 없다면 새로운 트랜잭션을 사용한다. default이다.
save() 함수가 REQUIRED로 적용되어 있다. 따라서 메서드에 @Transactional이 설정되어 있다면 메서드의 트랜잭션 범위를 따르고, 없다면 save()자체에 REQUIRED를 적용한다.
@Test
void transactionTest() {
try{
bookService.putBookAndAuthor();
} catch(RuntimeException e) {
System.out.println(e.getMessage());
}
}
//BookService.class
@Transactional(propagation = Propagation.REQUIRED)
public void putBookAndAuthor() {
Book book = new Book();
book.setName("JPA 시작하기");
bookRepository.save(book);
try {
authorService.putAuthor();
} catch(RuntimeException e) {
System.out.println(e.getMessage());
}
//throw new RuntimeException("오류가 발생하였습니다");
}
//AuthorService.class
@Transactional(propagation = Propagation.REQUIRED)
public void putAuthor() {
Author author = new Author();
author.setName("bert");
authRepository.save(author);
//throw new RuntimeException("오류가 발생하였습니다");
}
author, book에서 발생하면,
둘 다 rollback이 된다. REQUIRED이기 때문에 같은 트랜잭션으로 묶여 있어서 모두 성공 혹은 실패로 나뉜다.
REQUIRES_NEW
(TransactionDefinition.PROPAGATION_REQUIRES_NEW)
트랜잭션이 있던 없던 상관없이, 새로운 트랜잭션을 만들어 독립적으로 커밋과 롤백을 진행한다.
//BookService.class
@Transactional(propagation = Propagation.REQUIRED)
//@Transactional(propagation = Propagation.REQUIRES_NEW)
public void putBookAndAuthor() {
Book book = new Book();
book.setName("JPA 시작하기");
bookRepository.save(book);
try {
authorService.putAuthor();
} catch(RuntimeException e) {
System.out.println(e.getMessage());
}
//throw new RuntimeException("오류가 발생하였습니다");
}
//AuthorService.class
@Transactional(propagation = Propagation.REQUIRED)
//@Transactional(propagation = Propagation.REQUIRES_NEW)
public void putAuthor() {
Author author = new Author();
author.setName("bert");
authRepository.save(author);
//throw new RuntimeException("오류가 발생하였습니다");
}
REQUIRES_NEW를 author 사용하고 author에서 예외를 발생시키면,
book은 commit이 되고, author만 rollback이 된다.
REQUIRES_NEW를 book에 사용하고 book에서 예외를 발생시키면,
author는 commit이 되고 book은 rollback이 된다.
NESTED
(TransactionDefinition.PROPAGATION_NESTED)
호출하는 쪽의 트랜잭션을 그대로 사용하면서도 독립적으로 작동한다.
//BookService.class
@Transactional(propagation = Propagation.REQUIRED)
public void putBookAndAuthor() {
Book book = new Book();
book.setName("JPA 시작하기");
bookRepository.save(book);
try {
authorService.putAuthor();
} catch(RuntimeException e) {
System.out.println(e.getMessage());
}
//throw new RuntimeException("오류가 발생하였습니다");
}
//AuthorService.class
@Transactional(propagation = Propagation.NESTED)
public void putAuthor() {
Author author = new Author();
author.setName("bert");
authRepository.save(author);
//throw new RuntimeException("오류가 발생하였습니다");
}
author에서 예외가 발생하면,
author는 rollback이 되지만, book은 commit이 된다. 왜냐하면 author가 NESTED로 스스로 처리되기 때문에 영향을 주지 않는다.
book에서 예외가 발생하면,
동일한 트랜잭션을 사용하고 있기 때문에 author와 함께 rollback이 된다.
SUPPORTS
(TransactionDefinition.PROPAGATION_SUPPORTS)
호출하는 쪽에서 트랜잭션이 있다면 재활용한다. REQUIRED와 달리 호출하는 쪽에 트랜잭션이 없다면 새로 생성하지 않고 처리한다.
NOT_SUPPORTED
(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)
호출하는 쪽에서 트랜잭션이 있다고 해도 재활용하지 않는다. REQUIRED_NEW 처럼 별개의 트랜잭션을 생성하지 않고 해당 영역은 트랜잭션 없이 동작한다. 즉, 서로 별개로 처리된다.
MANDATORY
(TransactionDefinition.PROPAGATION_MANDATORY)
필수적으로 트랜잭션이 존재해야 한다. REQUIRED는 트랜잭션이 없다면 새로 만들었다. 하지만, MANDATORY는 만약 트랜잭션이 없다면 오류가 발생한다.
NEVER
(TransactionDefinition.PROPAGATION_NEVER)
아무런 트랜잭션이 없어야 한다. 하지만 만약 트랜잭션이 존재한다면 오류가 발생한다.
실무에서는, REQUIRED, REQUIRES_NEW를 제외하고는 잘 사용하지 않는다.
@Transactional은 TYPE과 METHOD 모두에서 사용이 가능하다. 클래스에 설정하면, 모든 메서드 적용하겠다는 의미이다. 또한 클래스에 적용한 것보다 메서드에 적용한 것이 우선순위로 작동한다.
'학습 > DB' 카테고리의 다른 글
@Embedded, @Embedabble (0) | 2021.09.30 |
---|---|
Native Query (0) | 2021.09.30 |
고아제거 속성 알아보기 (0) | 2021.09.26 |
Cascade 활용하기 (0) | 2021.09.26 |
@Query 활용하기 2 (0) | 2021.09.26 |