개발하는 쿠키
article thumbnail

이번 장을 읽으면서 em.find() vs JPQL select 차이와 JPA flush에 대해 정리한다.

 

em.find() vs JPQL select

 

em.find(Member.class, 1L);
em.find(Member.class, 1L);
이 코드를 실행하면 데이터베이스에 쿼리가 몇 번 실행될까?

 

답은 한 번이다.

 

JPA 의 em.find() 를 실행하면 영속성 컨텍스트에 해당 엔티티가 있는지 검사한다.

영속성 컨텍스트에 엔티티가 있으면 그 엔티티를 반환하고,

없으면 데이터베이스에 조회 쿼리를 실행 > 영속성 컨텍스트에 저장 > 반환한다.

 

em.find(Member.class, 1L);
em.createQuery("select m from Member m where m.id = 1")
	.getSingleResult();

 

이 코드를 실행하면 데이터베이스에 쿼리가 몇 번 실행될까?

 

답은 두 번이다.

 

JPA의 em.find() 를 통해 영속성 컨텍스트에 엔티티가 저장되어 있다고 해도,

JPQL은 쿼리를 데이터베이스에 실행해서 결과를 얻어낸다.

 

JPQL은 아래와 같이 실행된다.

쿼리를 데이터베이스에서 실행 > 영속성 컨텍스트 확인 > 영속성 컨텍스트에 해당 엔티티가 있으면 데이터베이스에서 조회한 엔티티 정보 버림 > 영속성 컨텍스트 엔티티 반환

 

영속성 컨텍스트에 해당 엔티티가 없으면 > 데이터베이스에서 조회한 엔티티 정보를 영속성 컨텍스트에 저장 > 영속성 컨텍스트의 엔티티 반환

 

 

JPA flush()

flush(): 영속성 컨텍스트에 있는 쿼리들을 실제 데이터베이스에서 실행한다.

 

flush() 메서드는 어떻게 동작할까?

- Dirty Checking 방식으로 변경을 감지한다.

- 변경을 적용할 SQL을 쓰기 지연 저장소에 등록한다.

- 쓰기 지연 저장소의 쿼리를 DB에 전송한다.

- commit() 메서드를 호출해서 변경사항을 반영한다.

 

commit()은 Transaction 끝에서 실행된다.

 

 

flush() 가 호출되는 시점

- Transaction commit() 할 때 호출

- JPQL 쿼리 실행할 때 호출

 

flush() 는 옵션을 통해 호출되는 시점을 정할 수 있다.

FlushModeType.AUTO 는 위처럼 Transaction commit() 할 때와 JPQL 쿼리를 실행할 때 호출된다.

FlushModeType.COMMIT 은 commit() 이 실행될 때만 flush()를 호출한다.

 

em.setFlushMode(FlushModeType.COMMIT);

Member member = em.find(Member.class, 1L);
member.setAge(15);

Member foundMember = 
	em.createQuery("select m from Member m where m.age = 15")
		.getSingleResult();

 

이 코드를 실행하기 전 Member 테이블에는 age=15인 데이터가 없다고 가정하자.

이 코드를 실행한 후 foundMember변수에는 데이터가 있을까?

 

답은 '데이터가 없다.' 이다.

 

위 코드에서 데이터를 조회하려면 어떻게 바꿔야 할까?

- em.flush() 를 실행해서 commit() 이 작동하게 하거나

- JPQL을 실행하면서 flushMode를 Auto로 잠깐 설정해주는 방법이 있다.

em.setFlushMode(FlushModeType.COMMIT);

Member member = em.find(Member.class, 1L);
member.setAge(20);

//em.flush() 를 호출해 DB와 영속성 컨텍스트를 동기화한다.

Member foundMember = 
	em.createQuery("select m from Member m where m.age = 20")
    	.setFlushMode(FlushModeType.Auto) // Query 에 직접 설정한다.
		.getSingleResult();

 

반응형
profile

개발하는 쿠키

@COOKIE_

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!