Programming/Spring

[Spring JPA] Transactional Manager

주죵 2022. 5. 12. 00:10
728x90
반응형

Transaction의 특성 ACID

1. Atomicity (원자성) : 부분적 성공 허용 X. all or nothing. 내가돈보내는건 됐는데 상대방계좌에 돈이안찍히는건 안되는 이런경우는 X!

-> 하나의 트랜잭션으로 묶인곳에서 RuntimeException발생하면 전체 다 커밋되지 않음.

-> 하나의 트랜잭션안에서 저장이 여러번 일어나게되면 컨텍스트 내에서만 저장을 수행하고 최종 커밋은 트랜잭션이 종료될때 수행됨

2. Consistency(일관성) : 데이터간의 정합성을 일관성있게 맞춰야함

 

3. Isolation (독립성) : transaction의 조작은 다른 transaction에 대해 독립적

 

4. Durability (지속성) : 데이터는 영구적으로 지속되야함.

 

Transaction 사용의 잘못된 대표예시

1. Checked Exception의 사용

그냥 Exception을 사용해서 예외처리를 하는경우 커밋이 수행됨.

-> RuntimeException은 예외 발생시 롤백하지만 Checked Exception은 개발자가 예외처리에대한 책임을 전부 가지게됨. catch에서 전부 롤백을 수행해야하므로 잊지말고 넘어가야하는부분!

왜 Checked Exception은 롤백이 되지 않는가?

-> Spring AOP 기반의 구성을 하나하나 따라가보자. TransactionAspectSupport.java > invokeWithininTransaction 상에 구현된 소스를 보면, 예외 발생시 처리되는 completeTransactionAfterThrowing > transactionAttribute.rollbackOn  구현을 보면, 예외발생시 RuntimeException이나 Error타입인경우 롤백이 진행됨. Checked Exception의 경우는 롤백없이 commit 수행.

-> Checked Exception 발생에서 롤백하는방법은?? : rollbackFor = Exception.class 과 같은 설정으로 롤백을 수행할 checked Exception  레벨을 지정가능하다

 

2. Private 메서드에서의 @Transactional 사용

구체적으론 같은 클래스내에서 참조하여 호출하는 메서드가 transactional 사용중일 경우를 의미함

> 이와같은 경우에도 롤백이 일어나지 않음. 스프링 컨테이너는 Bean 클래스로 진입할때 어노테이션을 처리함. Bean 내부에서 내부 다른 메서드를 호출하게 되면 그 메서드에 있던 transactional은 무효화가 된다. (Bean 외부에서 호출되는 시점에 AOP에서 처리해버리기 떄문)

 

Transaction propagation(전파)

jpa에서 transaction은 해당 메소드의 시작과 끝까지를 하나의 트랜잭션으로 잡음. 그런데 내부적으로 다른 클래스의 메소드를 호출한다면?? 현재의 트랜잭션과 다른 클래스 메서드의 트랜잭션은 어떤 순서로 진행될까? 이런경우 교통정리를 해주는게 Transaction propagation이라는 속성이다.

- Required : 기존 사용하던 트랜잭션이 있다면 사용, 없으면 새로운 트랜잭션 생성. 즉 호출당한 메서드의 transaction이 required로 처리되게 되어있으면 호출한쪽의 트랜잭션을 그대로 사용한단말!

- Requires_new : 있던 없던 상관없이 항상 새로운 트랜잭션을 생성. 호출한쪽의 트랜잭션과 상관없이 별도의 독립적인 트랜잭션을 새로생성

- Nested : 호출하는쪽에서의 트랜잭션에 종석적인 새로운 트랜잭션을 생성함. 그러나 상위의 트랜잭션에게 영향을 주진 않는다고 보면 된다. 예를들면 A(...->B(nested)...) 인경우 B의 오류시 B는 롤백되나 A전체의 영향은 안줌. 그러나 A자체가 오류가나버리면 B까지 함께 롤백됨

- Supports : requried와 비슷하나, required는 없으면 생성 이건 없으면 트랜잭션 생성없이 처리 

- not_supported : 해당 영역은 트랜잭션 생성없이 처리. 호출한 트랜잭션쪽은 해당 로직이 완료되면 트랜잭션 이어감

- mandatory : 필수적으로 트랜잭션이 필수적으로 있어야함. 호출한쪽에서 트랜잭션이 없다면 오류를 발생

- never : mandatory와 반대. 호출한쪽에서 트랜잭션이 있다면 오류 발생

 

일반적으로 transaction 흐름을 제어할정도의 어려운로직을 잘 쓰진않음. 유지보수나 디버그의 어려움이 있으므로 required만을 사용하는걸 장려한다.

 

 

Transactional Scope의 차이

Class scope : 클래스에 속한 모든 메서드에 대한 처리

method scope : 해당 메소드에 대한 처리. 당연히 이것이 선적용임

 

728x90

'Programming > Spring' 카테고리의 다른 글

[Spring JPA] Casacade(영속성 전이), 고아제거속성  (0) 2022.06.22
[Spring JPA] Entity lifecycle  (0) 2022.04.25
[Spring JPA] 영속성 컨텍스트  (0) 2022.04.24
SpringData JPA 기초  (0) 2022.02.23
[Spring boot] Spring Boot란  (0) 2021.06.20