CH15 고급 주제와 성능 최적화
Last updated
Last updated
스프링 프레임워크에서 JPA 에서 정의한 예외들을 직접 사용하게 되면 JPA 에 의존하는 형태가 된다. 그래서 JPA 예외들이 발생하면 각 예외마다 이에 맞는 스프링의 예외로 변환해서 throw 할 수 있다.
PersistenceExceptionTranslationPostProcessor 를 bean으로 등록해두면 알아서 이를 변환해준다. 스프링부트에는 이미 이것이 bean으로 등록되어 있다.
이 있어 링크를 남긴다. 그냥 스프링부트를 사용하면서 마주치는 JPA 에서의 에러는 이미 변환기에 의해서 변환된 스프링 예외이며 그 과정은 자동으로 bean으로 등록된 PersistenceExceptionTranslationPostProcessor 가 해준다라는 사실만 기억하면 될 듯 하다.
동일성 : identical, == 비교
동등성 : equivalent, equals() 비교
데이터베이스 관점에서의 동등성 : pk가 같다
1차 캐시에서 이미 조회된 것이기에 같은 주소값을 할당해준다. 따라서 동일성, 동등성 모두 같다.
동일성은 같지 않다. 주소값이 다르기 때문이다. 하지만 동등성은 같다. 같은 row를 대상으로 한 데이터이기 때문이다.
예제에선 하이버네이트를 사용했기 때문에 이러한 비교를 해본 것인데 실제로는 Spring Data JPA를 사용할 것이라서 이 단계까지 학습할 필요성이 있을지는 모르겠다.
entityManager.find(), entityManager.getReference() 두 가지 메소드를 두고서 무엇을 먼저 실행해서 결과를 가져왔는지에 따라서 처음에 find()로 entity를 가져왔다면 getReference()로 조회해도 entity가 할당된다. 반면에, 처음에 getReference()로 프록시를 가져왔다면 find()로 조회해도 프록시가 할당된다.
영속성 컨텍스트는 자신이 관리하는 영속 엔티티의 동일성을 보장한다. 다시말해 영속성 컨텍스트는 한 번 프록시로 노출한 엔티티는 계속 프록시로 노출한다. 그래야 사용하는 입장에서 프록시인지 아닌지 구분하지 않고 사용할 수 있기 때문이다.
말 그대로 쿼리가 동작할때 ‘읽기 전용’으로만 동작하도록 하는 것이 읽기 전용 쿼리이다.
그렇다면 읽기만 전용으로 동작한다면 그 외에 무엇이 동작을 안한다는 것인가? 1차 캐시 및 스냅샷 저장을 하지 않는다는 것이다.
@QueryHint 를 사용할 경우 스냅샷을 저장하지 않기 때문에 메모리를 절약할 수 있다.
위와 같이 데이터를 변경해도 update 가 발생하지 않는다. findByName 의 @QueryHint 를 삭제하면 Update 문이 수행된다.
findByName 의 @QueryHint 를 삭제한 상태로 위 로직 수행시 Update 문이 수행되지 않는다.
@Transactional(readOnly = true) 을 사용할 경우 기본적으로 트랜잭션 종료 시점에 flush()를 사용하지 않아서, dirty checking과 쓰기 지연 SQL의 flush 가 발생하지 않는다. 을 보면 @Transactional(readOnly = true) 을 해주면 스냅샷도 만들지 않는다고 한다.