스프링AOP를 통해서 @Transactional 어노테이션만으로 Service 계층에서 트랜잭션을 걸 수있다.
일반적으로 조회용 메서드에는 @Transactional(readOnly = true)를 설정함으로써 성능상 이점? 을 얻을 수 있다고 한다.
그렇다면 왜 그런것일까?
특징 | @Transactional 없음 |
@Transactional(readOnly = true) |
---|---|---|
트랜잭션 생성 여부 | ❌ 없음 | ✅ 읽기 전용 트랜잭션 생성 |
영속성 컨텍스트 유지 여부 | ❌ 없음 (즉시 종료) | ✅ 유지됨 (트랜잭션 범위 내에서) |
Dirty Checking 작동 여부 | ❌ 작동 안 함 (컨텍스트가 없음) | ❌ 작동 안 함 (readOnly=true로 인해 비활성화) |
flush() 실행 여부 | ❌ 실행되지 않음 | ❌ 실행되지 않음 |
성능 최적화 적용 여부 | ❌ 없음 | ✅ 일부 최적화 (Repeatable Read, JDBC 최적화 가능) |
@Transactional 이 없는 경우
public void findPlaceTwice(Long id) {
Place place1 = placeRepository.findById(id).orElseThrow();
Place place2 = placeRepository.findById(id).orElseThrow();
}
@Transactional
이 없는 경우 영속성 컨텍스트가 생성되긴 하지만 바로 닫혀버린다.
즉, findById(id) 라는 조회용 메서드를 실행 후 영속성 컨텍스트는 바로 닫힌다.findById(id)
를 호출하게 되면 Spring Data JPA가 내부적으로 임시 트랜잭션을 만들어서 조회 후 즉시 종료한다.@Transactoinal(readOnly=true) 인 경우
@Transactional(readOnly = true)
public void findPlace(Long id) {
Place place = placeRepository.findById(id).orElseThrow();
}
readOnly=true
를 사용하면, 트랜잭션을 유지하므로 영속성 컨텍스트도 유지된다.