spring boot Transaction(@Transactional) 여기에 잘못된 정보가 있다. 그래서 다시 포스팅을 한다.
여기 보면 3번
@Transactional(readOnly = true)가 적용된 메서드에서 @Transactional 혹은 @Transactional(readOnly = false)가 적용된 메서드를 호출 할 경우 무조건 read-only Transaction이 적용된다. 만약 이때 R을 제외한 CUD를 할 경우 에러를 발생한다. 이런 내용이 있었다.
영 찜찜해서 다시 해봤는데 역시나 잘못되었다. 분명히 저번에 테스트 할때는 에러가 났는데 방금 해보니까 위와 같이 되지 않았다. 테스트를 잘 못했나?
아무튼 각성하고 다시 설명을 하겠다.
일단 중요한건 에러가 나지 않는다. 근데 왜 저번엔 에러가 났지?ㅠㅠ read 어쩌고 저쩌고 하면서 에러가 분명 났는데..
그리고 에러도 나지 않지만 TransactionSynchronizationManager.isCurrentTransactionReadOnly() 메스드 결과가 true지만 롤백도 된다. 또한 @Transactional(readOnly = true) 설정 이라도 insert시 에러를 뱉지 않고 정상적으로 커밋도 된다.
찾아 보니까 JDBC 벤더들마다 다르다고 한다. 근데 오래전 글이라 지금도 적용될지는 모른다. 글쎄다.. 뭐가 어떻게 돌아가는지.. 나원참..
정리하자면 @Transactional(readOnly = true) 에서 @Transactional 메서드를 호출하더라도 정상적으로 작동한다. CRUD 모두 작동한다. 또한 @Transactional(readOnly = true) 에서 CUD를 하더라도 에러가 나지않고 커밋된다. 하지만 벤더들마다 다르다고 하니 잘 판단해서 해야 한다.
좀더 테스트한 결과 3번이 아예 잘못된 결과는 아니 였다. mysql 경우에 readOnly가 true 일경우 에러는 내뱉는다.
java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
위와 같은 로그가 찍혔다. 필자가 그때 테스트 한것이 mysql로 했나부다..
계속 왔다 갔다. 정리가 안된다..ㅠㅠ
마지막으로 다시 정리 하자면
@Transactional(readOnly = true)가 적용된 메서드에서 @Transactional 혹은 @Transactional(readOnly = false)가 적용된 메서드를 호출 할 경우 무조건 read-only Transaction이 적용된다.는 참이다. 트랙잭션이 전파되는 것은 맞지만 JDBC 벤더들 마다 readOnly속성의 구현이 된 벤더들도 있고 그렇지 않은 벤더들도 있다.
그래서 만약 이때 R을 제외한 CUD를 할 경우 에러를 발생한다. 이것은 참일수도 있고 거짓일 수도 있다. h2와 mysql을 테스트를 한 결과 h2는 거짓이지만 mysql은 참이다.
필자의 mysql 버전은 5.6.25이다. mysql의 readOnly는 버전 5.6.5부터 지원한다고 한다.