스프링 347

58. 트랜잭션 전파 활용 5

전은 commit의 경우만 알아봤는데, 이제 rollback의 경우를 직접 실습해 보자. REQUIRED이므로 묶여져 있다고 생각하고, 하나만 rollback이 되도 모두 rollback이다. 롤백 시 내부 트랜잭션들은 rollback해도 물리 트랜잭션을 rollback하는 것이 아니라 rollbackOnly로 마크를 새겨둠. 저 커넥션? 트랜잭션 동기화 매니저? 에다가. 외부 트랜잭션이 commit이나 rollback 해야 진짜 commit이나 rollback임.

57. 트랜잭션 전파 활용 4

이제야 본격적으로 트랜잭션 전파를 활용하기 시작했다. 리마인드 시켜보자면, 트랜잭션을 논리 트랜잭션과 물리 트랜잭션이라는 관점으로 나누면 상당히 관리하기가 편하다. 논리 트랜잭션은 말 그대로 어떤 논리적인 트랜잭션, 어.. 논리적이지, 실제로는 적용을 아직 안 했을 수도 있다는 그런 뜻이다. 논리적으로는 적용을 한 것이다. 물리 트랜잭션은 실제 물리적으로 트랜잭션을 적용 하는 것 이다. 그리고, 이 물리 트랜잭션은 가장 외부의 트랜잭션이나, REQUIRE_NEW 해서 새롭게 트랜잭션을 생성한 트랜잭션이나, 여튼 첫번째 트랜잭션만이 이 물리 트랜잭션을 다룰 수 있다. 이 물리 트랜잭션이 commit 혹은 rollback을 해야 비로소 진정 트랜잭션이 끝나는 것이다. 다른 것은 그냥 논리적으로 commit을..

56. 트랜잭션 전파 활용 3

MemberRepository와 LogRepository를 묶는 가장 간단한 방법은 Service에서 트랜잭션 하는 것이다. 몇가지 경우가 있는데, 먼저 아예 MemberRepository와 LogRepository에 있던 @Transactional을 주석처리 하고, Service에만 @Transactional을 추가해 @Transactional public void joinV1(String username){ Member member = new Member(username); Log logMessage = new Log(username); log.info("== memberRepository 호출 시작 =="); memberRepository.save(member); log.info("== member..

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("트랜잭션..