분류 전체보기 954

55. 트랜잭션 전파 활용 2

트랜잭션 동작에 대해 볼거임. 현재는 이런 상황. 그냥 트랜잭션 한 구역 다 끝내고, 다음 트랜잭션 시작해서 다 끝내는 거라 완전히 남인 트랜잭션임. 주황색이 트랜잭션 범위. 그래서 @Test void outerTxOff_fail(){ String username = "로그예외_outerTxOff_fail"; memberService.joinV1(username); assertTrue(memberRepository.findByUsername(username).isPresent()); assertTrue(logRepository.findByMessage(username).isPresent()); } 우리가 message에 "로그예외"라는 글자가 있으면 runtimeException을 날리도록 해 놨는데, ..

54. 트랜잭션 전파 활용 1

비즈니스 요구사항 회원 등록, 조회 회원 데이터가 변경될 때 변경 이력을 DB LOG로 남겨야 함. 일단 등록 시에만 LOG 남기도록 함. 도메인부터 새로 만듦. @Entity @Getter @Setter public class Member { @Id @GeneratedValue private Long id; private String username; public Member() { } public Member(String username) { this.username = username; } } Long id 가 @Id이고, @GeneratedValue 줘서 이거는 DB나 어디선가 할당해 주는 값을 받는 거임. 이거 안 넣어주면 우리가 Id 직접 넣어줘야 함. JPA에서 기본 생성자(비어 있는 거) ..

53. 트랜잭션 전파 6

다양한 전파 옵션에 대해 알아보겠다. 보통 REQUIRED를 기본으로 쓰고, 아주 가끔 REQUIRES_NEW를 쓴다. REQUIRED 기존 트랜잭션에 참여 없으면 새로 생성 REQUIRES_NEW 항상 새 트랜잭션을 생성. SUPPORT 기존 트랜잭션 있으면 참여 없으면 아예 트랜잭션 없이 진행 말 그대로 지원 정도 NOT_SUPPORT 기존 트랜잭션 있을 시에도 트랜잭션 없이 진행하되, 기존 트랜잭션은 보류시킴. suspend 그거 인 듯 없을 시 그냥 트랜잭션 없이 진행 MANDATORY 기존 트랜잭션에 참여한다. 없으면 예외 발생. IllegalTransactionStateException 의무적인, 이란 뜻으로 반드시 트랜잭션이 있어야 한다. NEVER 기존 트랜잭션 있으면 예외 발생 없을 시 ..

52. 트랜잭션 전파 5

지금까지는 트랜잭션이 한몸이었는데 이번에는, 예를 들자면 외부 트랜잭션은 rollback이지만 내부 트랜잭은 commit인? 그 반대의 상황도. 알아보겠다. 그러니까, 코드상 동일한 시간선상에서 돌아간다고 하더라도, 각자 다른 트랜잭션 이다. 서로 각각의 물리 트랜잭션을 사용하도록. 이럴 땐 그냥 REQUIRES말고(이게 기본값임) REQUIRES_NEW 옵션을 사용하면 된다. @Test void inner_rollback_requires_new(){ log.info("외부 트랜잭션 시작"); TransactionStatus status1 = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("외부 트랜잭션 .isNewTransa..

51. 트랜잭션 전파 4

이번엔 외부 트랜잭션이 롤백되는 경우를 보자. @Test void outerRollback(){ log.info("외부 트랜잭션 시작"); TransactionStatus status1 = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("외부 트랜잭션 .isNewTransaction()={}", status1.isNewTransaction()); log.info("내부 트랜잭션 시작"); TransactionStatus status2 = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("내부 트랜잭션 .isNewTransaction()={}", sta..

50. 트랜잭션 전파 3

본격적으로 트랜잭션 전파에 대해 알아볼 것이다. 트랜잭션이 중첩적인, 그러니까 트랜잭션 도중 트랜잭션이 끝나지 않았는데(commit or rollback) 또 트랜잭션을 마주 한다면? 기존의 트랜잭션을 이어 받을 지, 새 트랜잭션을 만들어 진행 해야 할 지, 이런 것을 정하는 것이 트랜잭션 전파. propagation 우선, 트랜잭션 진행 중에 또 다른 트랜잭션을 시작하는 경우. 보통 트랜잭션을 이어 받는다..? 어.. 그렇기 보단 보통은 일단 스프링은 하나의 트랜잭션을 논리 트랜잭션이라고 정의한다. 그러니까, @Transactional 붙인거나 getTransaction 해서 시작하거나 해서 트랜잭션 도중의 범위들을 하나의 논리 트랜잭션 이라고 한다. 그리고, 이미 트랜잭션 진행 도중에 또 다른 트랜잭..

49. 스프링 트랜잭션 전파 2

이번엔 여러가지 상황을 살펴볼 건데, 트랜잭션 후, 다시 트랜잭션 @Test void doubleCommit(){ log.info("트랜잭션1 시작"); TransactionStatus status1 = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("트랜잭션1 커밋 시작"); txManager.commit(status1); log.info("트랜잭션1 커밋 끝"); log.info("트랜잭션1 끝."); log.info("트랜잭션2 시작"); TransactionStatus status2 = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("트랜잭션..

48. 스프링 트랜잭션 전파

트랜잭션이 둘 이상 있을 때 라던지, 아니면 저번에 트랜잭션 프록시에서 트랜잭션 아닌 거에서 트랜잭션을 호출했을 때 어떻게 동작하는 지 알아 봄. @Slf4j @SpringBootTest public class BasicTxTest { @Autowired PlatformTransactionManager txManager; @Test void commit(){ log.info("트랜잭션 시작"); TransactionStatus status = txManager.getTransaction(new DefaultTransactionAttribute()); log.info("트랜잭션 커밋 시작"); txManager.commit(status); log.info("트랜잭션 커밋 완료"); } @Test void ..

47. 트랜잭션과 예외 -활용

체크예외를 커밋하는 이유는 스프링 설계 자체가 비즈니스 예외는 체크예외, 언체크예외는 복구 불가능 한 예외라고 가정하고 설계 됨. 물론 꼭 따를 필요는 없음. 그냥 rollbackFor 이런 거 써도 되고. 비즈니스 예외라는 것은, 예를 들어 잔고부족 같은 거. 보통 이런 건 우리가 따로 비즈니스 적으로 예를 들어 잔고가 부족합니다! 이런 메시지를 클라이언트에게 전해주게 하던지 처리 해야 하니까. 주문데이터를 일단 저장하고, 결제 상태를 대기로 만들고, 고객에게 잔고 부족을 알리는 등. 이렇게 시스템 자체는 문제가 없지만 비즈니스 상황에 대해 있는 문제를 비즈니스 예외. 이런 비즈니스 예외는 굉장히 중요하고 반드시 처리해야 하는 경우가 많아서 체크 예외를 고려. 그래서 보통 예외 구분은 시스템 장애 예외..

46. 트랜잭션과 예외

Default는 런타임예외 발생 시 롤백, 체크예외 발생 시 커밋임. @SpringBootTest public class RollbackTest { @Autowired RollbackService service; @Test void runtimeException(){ assertThatThrownBy(()->service.runtimeException()) .isInstanceOf(RuntimeException.class); } @Test void checkedException(){ assertThatThrownBy(()->service.checkedException()) .isInstanceOf(MyException.class); } @Test void rollbackFor(){ assertThatTh..