일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- 백준#BOJ#8012#한동이는영업사원
- 백준#boj#16932#모양만들기
- 백준#BOJ#1939#중량제한
- 백준#BOJ#14501#퇴사#브루트포스
- 백준#BOJ#12865#평범한배낭
- 백준#BOJ#2615#오목
- 백준#boj#12755
- Today
- Total
순간을 성실히, 화려함보단 꾸준함을
@Transactional 은 mySql 의 auto_increment 값을 롤백시켜주지 않는다고요?! 본문
안녕하세요. 폭발토끼입니다.
오늘은 글또 3번째 글을 작성하는 날입니다!!
오늘 다뤄볼 주제는 spring 을 사용하고 있으시면 test code 를 작성할때 한번쯤은 마주해봤을 내용을 가져왔습니다.
바로 auto_increment 에 관한 내용입니다.
테스트 코드를 작성하는 법에 대해서 공부하던 중에 테스트 하나만 진행했을때는 문제없이 성공했지만 두개 이상의 테스트를 진행했을 경우에 이상하게 자꾸 에러가 발생하는 문제가 생겼었습니다.
Member Entity 입니다. 기본키 전략을 IDENTITY 로 설정해주었습니다.
간단한 회원가입 Controller 를 테스트 하는 코드입니다. Member 테이블에 save 하면 기본키가 1씩 증가하게 되겠죠?
회원정보 수정 Controller 를 테스트 하는 코드입니다. 마찬가지로 Member 객체를 생성하고 save 하게 되면 member 테이블에 기본키가 1이 증가한 값이 들어가게 될 것 입니다.
각각 테스트를 따로 돌려보겠습니다.
두 테스트 모두 문제없이 성공하는 것을 볼 수 있습니다.
그럼 이번에는 한꺼번에 돌려보겠습니다.
하나의 테스트만 성공하고 나머지 하나는 실패한걸 볼 수 있죠??
이유가 대체 뭘까요??분명히 메소드마다 @Transactional
어노테이션을 붙여줬으면 테스트가 끝나고 롤백이 되어야 하는게 맞는데 말이죠....
바로 이 부분에 대해서 크게 착각을 하고 있었던 것 입니다.
사실 mySql 에서 auto_increment 속성은 @Transcational
어노테이션과 관계없이 원래 롤백이 되지 않기 때문입니다.
왜 롤백 대상이 아닐까요? 바로 데이터의 정합성 때문입니다.
예시를 하나 들겠습니다.
1번 세션에서 테이블 A 에 데이터를 insert 했습니다.
2번 세션에서 테이블 A 에 데이터를 insert 했습니다.
2번 세션에서 테이블 A 의 pk 값을 테이블 B에 fk 로 잡아 insert 하였습니다.
2번 세션에서 commit 을 진행합니다.
1번 세션에서 rollback 을 실행합니다.
이런상황에서 2번세션에서 commit 했을때의 기본키의 값을 1번 세션에서 rollback을 진행했다는 이유로 나머지 데이터들의 pk 값들을 rollback 시켜야 될까요? 그럼 fk 를 가지고 있는 테이블B 에 들어가 있는 값은 어떻게 수정해줄까요???
이런 문제점들 때문에 auto_increment 는 rollback 의 대상에서 제외되는 것 입니다.
자 그럼 우린 지금까지 내용으로 mysql 의 auto_increment 전략은 롤백이 되지 않는구나! 라는걸 알았습니다.
그러면 테스트 코드를 대체 어떻게 짜야할까요???
첫번째 방법은 테스트를 시작하기 전에 매번 auto_increment 의 값을 1로 초기화위와 같이 테스트를 시작하기 전에 매번 auto_increment 값을 1로 초기화 해주면 됩니다. 그러나 이 방법에는 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 를 사용하면 정상적으로 적용이 되지 않습니다.
그 이유는 https://kth990303.tistory.com/371 이 블로그를 참고해보세요!
@BeforeEach
void clean(){
this.entityManager .createNativeQuery("ALTER TABLE MEMBER AUTO\_INCREMENT = 1") .executeUpdate();
}
위와 같이 말이죠.
두번째 방법은 auto_increment 에 의존하지 않고 직접 save한 객체를 조회해서 테스트에 적용하는 것 입니다.
위와 같이 소스를 수정하고 한꺼번에 테스트를 돌려보도록 하겠습니다.
짠~ auto_increment 를 초기화 하지 않았음에도 무사히 테스트 코드가 통과한 것을 확인할 수 있습니다.
이렇게 또 테스트 코드를 작성할때 한가지 Tip 을 배울 수 있었던 경험이었습니다.
출처 :
(https://stackoverflow.com/questions/449346/mysql-auto-increment-does-not-rollback)
'나의 개발 메모장' 카테고리의 다른 글
HttpClient 를 사용해서 Rest API 웹서비스 구현해보기!!! (0) | 2023.04.18 |
---|---|
@Value 어노테이션이 자꾸 null 이 나와요!!!! (0) | 2023.03.26 |
[Javascript, Spring]fetch API 로 데이터 서버로 전송하기 (0) | 2023.02.21 |
JPA metamodel must not be empty!!!!!! (0) | 2023.01.18 |
[JUnit] controller 테스트시 java.lang.IllegalStateException: Failed to load ApplicationContext 에러 (0) | 2023.01.13 |