728x90
JPA 는 과연 1차 캐시를 통해서 Repeatable Read 를 애플리케이션 레벨에서 지원할까 ?
이번 주제는 JPA 는 과연 1차 캐시를 통해서 Repeatable Read 를 애플리케이션 레벨에서 지원하는지에 대해 테스트한 결과를 정리한 내용이다.
Repeatable Read
Repeatable Read 는 트랜잭션 고립 레벨2(Transaction Isolation Level)에 속한다.
- MySQL InnoDB 에서 기본으로 채택하고 있는 격리 수준
- 선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때가지 후행 트랜잭션이 갱신하거나 삭제하는 것은 불허함으로써 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴
- Insert 는 가능
- Phantom Read 현상은 여전히 발생
위와 같은 특징을 가지고 있다.
테스트하는 데이터베이스는 H2
이며 H2 는 Read Committed 를 기본으로 설정되어있기 때문에, 테스트를 위해서 레벨을 따로 바꿔줄 필요는 없다.
Test
@Getter @Setter
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String userName;
}
@DisplayName("Repeatable Read Test")
@SpringBootTest
class RepeatableReadTest {
@Value("${persistence.unitname}")
private String persistenceUnitName;
@DisplayName("1차 캐시를 통한 Repeatable Read 를 지원하는지 테스트")
@Test
void repeatableReadByCache() throws Exception {
// given
EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName);
insertDummyData(emf);
// when
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin(); // 선행 트랜잭션 시작
Member findMember1 = em.find(Member.class, 1L);
/**
* findMember1 : Member 를 데이터베이스에서 조회
* Member 를 다시 조회하기 전에 H2 데이터 베이스에서 UPDATE 문 실행
* findMember2 : Member 를 데이터베이스가 아닌 1차 캐시에서 조회
*/
Member findMember2 = em.find(Member.class, 1L);
tx.commit(); // 선행 트랜잭션 종료
em.close();
emf.close();
// then
assertThat(findMember1.getUserName()).isEqualTo(findMember2.getUserName());
}
@DisplayName("더미 데이터 삽입")
private void insertDummyData(EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
member.setUserName("JungHo");
em.persist(member);
tx.commit();
em.close();
}
}
순서는 다음과 같이 진행했다.
- 더미 데이터 삽입
- 선행 트랜잭션 시작
- Member 를 데이터베이스에서 조회
- H2 데이터베이스에서 직접 Update 쿼리를 날린다.
- UPDATE MEMBER SET USERNAME = 'TEST' WHERE ID = 1;
- Member 를 다시 조회
- 이때, 데이터베이스가 아닌 1차 캐시를 통해서 데이터가 조회된다.
- 따라서, USERNAME 이 TEST 가 아닌 JungHo 가 조회된다.
- 선행 트랜잭션 종료
테스트 결과, JPA 는 1차 캐시를 통해서 데이터베이스가 아닌 애플리케이션 레벨에서 Repeatable Read
를 제공하는 것을 알 수있다.
728x90
'JPA' 카테고리의 다른 글
다양한 연관관계 매핑과 설정에 따른 트레이드 오프 (0) | 2021.12.31 |
---|---|
테이블과 컬럼에 대한 명세를 엔티티에 자세하게 적는것이 좋은지? (0) | 2021.12.29 |
AllocationSize 를 통한 성능 최적화 (0) | 2021.12.28 |
기본키 매핑 전략에 따른 INSERT QUERY 실행 시점 (0) | 2021.12.28 |
EntityManager 를 쓰레드간 공유하면 안되는 이유 (0) | 2021.12.28 |