스프링 프레임워크에 관련된 내용이다. 기본적으로 모든 repository는 기본적으로 트랜잭션이 적용되어 있다.(repository 구현체인 SimpleJpaRepository에 @Transactional이 적용되어 있기 때문이다.)
repository나 service계층(repository를 사용하는 계층)에서 사용된다. 기본적으로 RuntimeException이나 error가 발생하면 해당 트랜잭션을 롤백시킨다. Checked Exception에는 롤백이 일어나지 않는다.
여러가지 옵션을 줄 수 있다.
readOnly
: 데이터를 변경하는 operation이 없는 경우 true로 설정해주는 것이 좋다.
Isolation
: 여러개의 트랜잭션이 동시에 데이터베이스에 접근했을때, 해당 트랜잭션들을 어떻게 처리할 것인지에 대한 설정(동시에 처리할 것인지, 하나 하나 처리할 것인지 등) 기본값은 default로 DB의 기본값을 따라간다.(대부분 READ_COMMITTED 방식이 default값이다.)
Propagation
: 트랜잭션을 어떻게 전파시킬 것인지에 관한 것이다. 예를 들어 @Transactional을 가지고 있는 메서드가 있고, 그 메서드 안에서 다른 메서드를 호출했는데 그 메서드도 @Transactional을 가지고있는 경우, 첫 번째 메서드가 가지고 있던 트랜잭션을 두 번째 메서드가 이어갈 것이냐, 두 번째 메서드 자체에서 트랜잭션을 만들어서 따로 사용할 것이냐를 결정하는 것이다.(nested transaction에 관한 내용)
JPA 구현체로 Hibernate를 사용할 때, 트랜잭션을 readOnly로 사용하면 좋은점이 있다.
flush모드
를 NEVER로 설정해줘서, 해당 트랜잭션안에서는 Dirty checking
을 하지 않게 해준다.
flush모드
: 데이터베이스와 sync를 맞춰주는 모드. 즉 언제 데이터베이스에 sync를 할 것인지에 관한 것이다. 기본값은 보통 커밋하거나 데이터를 가져오기 전에 flush하게 되어있다.
Dirty checking
: 트랜잭션 내에서 변경이 일어날 시, PersistanceContext가 변경을 감지하여 데이터베이스에 반영하는 것
데이터를 읽어올 것이 많은 경우, DirtyChecking을 꺼놓으면 성능이 많이 올라간다.
Ex. findById 같은 경우 데이터를 읽어오기만 하기 때문에, readOnly 해주는 것이 좋다.(데이터 변경이 일어나지 않을 것이므로)
@Transactional(readOnly=true)
<T> List <T> findByPost_Id(Long id, Class<T> type);