JpaRepository
Spring Data JPA를 사용할 때 JpaRepository를 상속하는 interface를 만들어서 사용합니다.
public interface MemberRepository extends JpaRepository<Member, Long> {
}
우리는 interface를 상속했을 뿐인데, findAll() 같은 다양한 CRUD 메서드를 사용할 수 있습니다.
memberRepository.findAll();
Spring Data JPA는 내부적으로 JpaRepository를 상속하기만 해도 아래와 같은 구현체를 생성해주기 때문입니다.
@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
@Override
public List<T> findAll() {
return getQuery(null, Sort.unsorted()).getResultList();
}
// 다양한 CRUD 메서드 (생략) ...
}
JpaRepository구현체에 @Transactional(readOnly = true)가 있습니다.
단순히 읽는 용도면 트랜잭션이 왜 필요한걸까요??
@Trasnactional
궁금해서 검색을 조금 해보니, 성능 향상을 위해서 @Transactional(readOnly = true)를 사용한다는 글이 많습니다.
절반은 사실이지만, 정확한 표현이 절대 아닙니다!
트랜잭션 없이도 쿼리를 실행할 수는 있습니다. 하지만, 이 때는 영속성 컨텍스트는 작동하지 않습니다.
JPA의 엔터티는 반드시 영속성 컨텍스트(Persistance Context)안에서 동작합니다. 영속성 컨텍스트(Persistance Context)는 트랜잭션에서 동작합니다.
JPA의 Entity Manager는 기본적으로 PersistenceContextType.TRANSACTION
로 사용됩니다.
결과적으로, JPA의 Entity Manager는 트랜잭션이 있어야 동작합니다.
1차 캐시를 사용할 생각이 없다면, Read 메소드에서는 Transaction이 없어도 무방합니다. Spring Data JPA는 영속성 컨텍스트를 사용하기 위해서 모든 메소드에 기본적으로 트랜잭션을 생성합니다.
(readOnly = true)
@Transactional(readOnly =true)에서 readOnly 속성을 true로 명시하는 이유는 성능 향상이 맞습니다.
기본적인 @Transactional은 스냅샷을 저장하고, 변경을 감지하게 됩니다.
읽기(Read)를 위한 Repository method가 변경감지를 하는 것 자체가 성능 낭비이기 때문에, readOnly 속성을 주는 것입니다.
@Repository
@Transactional(readOnly = true)
public class SimpleJpaRepository<T, ID> implements JpaRepositoryImplementation<T, ID> {
@Override
public Optional<T> findById() {
// ...생략
}
@Transactional
@Override
public void deleteById(ID id) {
// ...생략
}
// ...
}
deleteById()처럼 변경(Write)에 대한 메소드들은 @Transactional을 명시합니다. 더 좁은 범위의 애노테이션이 적용되고 클래스에 적용된 @Transactional(readOnly = true)는 무시합니다.
반면, 읽기(Read)에 대한 메소드들은 method 단위의 @Transactional을 명시하지 않아서 Class 단위의 @Transactional(readOnly = true) 속성이 적용됩니다.
모든 읽기 메소드에 @Transactional(readOnly = true) 속성을 정의해도 문제가 없지만, 읽기(Read) 메소드가 훨씬 많습니다.
그래서 클래스 단위로 @Transactional(readOnly)를 먼저 명시하고, 수정(Write) 메소드에 한해서 새로 @Transactional을 명시해준다고 보시면 되겠습니다!
감사합니다.
'Server > Spring JPA' 카테고리의 다른 글
Spring - 샤딩 모듈 개발 이야기 (feat. AbstractRoutingDataSource) (10) | 2022.05.05 |
---|---|
JPA - 비관적 락, 낙관적 락 (+ 트랜잭션 격리 수준) 정리! (0) | 2022.04.17 |
Spring Data JPA - Bulk Update(일괄 수정)할 때 주의할 점! [영속성 컨텍스트] (0) | 2022.04.08 |
Spring Data JPA - Named query 정리 (+ @Query) !! (0) | 2022.04.08 |
JPA - 영속성(persistence란) [+1차 캐시] (5) | 2022.03.15 |