caffeine-library / pro-spring-5

🌱 전문가를 위한 스프링5를 읽는 스터디
5 stars 0 forks source link

[question] readOnly=true 트랜잭션에 적용되는 최적화 #72

Closed binchoo closed 3 years ago

binchoo commented 3 years ago

질문

read-only 트랜잭션 최적화 원리

상세 내용

finder 메서드들은 readOnly=true 속성을 사용하여, 영속성 제공자가 구현한 최적화 기능을 활용하라고 가이드 되어 있습니다. readOnly에 트랜잭션에 대한 최적화가 어떤 원리로 구현되어 있는지 알고 싶습니다.

연관 챕터

66 , 책 p.694

참고

binchoo commented 3 years ago

Hibernate의 readOnly 엔터티에 대한 처리

하이버네이트가 ResultSet에서 엔터티를 읽어들여 적재할 때, 기본적으로 loaded state 라는 값을 Session에 저장한다. 이 과정을 hydration이라 부른다. (아마 해당 시점의 엔터티 스냅샷인것 같다)

loaded state의 용도

영속성 컨텍스트는 엔터티를 managed entity로서 관리하면서

이에 활용되는 loaded state값은 Session이 닫힐 때까지 유지한다. 따라서 엔터티 적재 시간과 메모리 비용을 더 소모한다.

하지만, read-only 엔터티는 loaded state를 적재하지 않으므로 비용을 아낄 수 있다.

테스트 코드

readOnly=true 트랜잭션 하에서 읽어들인 엔터티는 getLoadedState()loadedState를 획득할 수 없음을 보여주고 있다.

@Override
@Transactional(readOnly = true) // readOnly 설정
public List<Post> findAllByTitle(String title) {
    List<Post> posts = postDAO.findByTitle(title);

    org.hibernate.engine.spi.PersistenceContext persistenceContext = getHibernatePersistenceContext();

    for(Post post : posts) {
        assertTrue(entityManager.contains(post));

        EntityEntry entityEntry = persistenceContext.getEntry(post);
        assertNull(entityEntry.getLoadedState()); // pass: readOnly 엔터티의 loadedState는 null이다.
    }

    return posts;
}

@Override
@Transactional // readOnly 설정 안 함
public Post findById(Long id) {
    Post post = postDAO.findById(id);

    org.hibernate.engine.spi.PersistenceContext persistenceContext = getHibernatePersistenceContext();

    EntityEntry entityEntry = persistenceContext.getEntry(post);
    assertNotNull(entityEntry.getLoadedState()); // pass: 영속성 컨텍스트에 loadedState가 적재되어 있음.

    return post;
}
binchoo commented 3 years ago

DB 벤더 별 readOnly 트랜잭션 최적화

https://lob-dev.tistory.com/entry/DBMS-%EB%B3%84-Transaction-Read-Only%EC%97%90-%EB%8C%80%ED%95%9C-%EB%8F%99%EC%9E%91-%EB%B0%A9%EC%8B%9D-1