어제에 이어 JPA 강의를 들으면서 내가 생각했던 의문점이 풀림!
JPA를 이해하려면 영속성에 대한 이해가 필요함. 영속성이란 자바 App과 DB를 연결시켜주는 통로 같은 것.
자바의 객체를 DB에 넣을 때 영속성 상태가 된 상태에서 넣어주는것! 자바의 Entity는 영속성 컨텍스트 안에 들어가지 않으면 아직 DB과 관계없는 그냥 순수한 객체임. 영속성 컨텍스트에 들어가게되면 이제 이 객체는 DB와 연관을 맺게 되는 것.
그럼 영속성은 어떻게 관리되는지?
바로 EntityManager의 persist()메서드를 이용해 객체를 영속성 컨텍스트에넣어준다. 또한 find를 해서 DB로부터 조회한 데이터도 영속성 컨텍스트 안에 들어가 영속 상태로 들어감! 이렇게 영속성이 되면 주는 이점은 다음과 같음
1. 1차 캐시
2. 동일성 보장
3. 트랜잭션을 지원하는 쓰기 지연
4. 변경 감지
5. 지연 로딩
[1차 캐시]
같은 트랜잭션 내에서 Entity를 조회할 때 쿼리를 날리지 않고, 1차 캐시에 들어있는 Entity를 바로 반환하는 것.
내가 여기서 의문이였다. 같은 트랜잭션이라면... 거의 1차 캐시 사용하지 않을거 같은데.. 트랜잭션 범위가 엄청 넓지 않고, 보통 메서드 하나하나 트렌잭션을 걸고 끄기 때문에 이건 그렇게 이점이 크지 않을거 같은데??? 라고 생각했다.
역시 영한님도 그렇게 말씀 해주셨다. 이 1차 캐시틑 실무에서 그렇게 이점이 큰 부분은 아니다.라고
하지만 그래도 나중에 쓸일이 있겠지? 알아두자!
같은 트랜잭션 내에서 Entity라 영속성 컨텍스트 안에 있다면 1차 캐시에서 쿼리 없이 조회가 가능하다는 점!
[동일성 보장]
같은 트랜잭션 내에서 같은 조건으로 find한 두 Entity는 같은 객체가 됨!
이건 이전 포스트에서 말한 내용과 연결됨. DB에서 같은 조건으로 조회를 해오면? 영속화가 되지 않았다면 이는 두 객체가 다른 객체로 인식됨. 그냥 DB에서 값들을 가져와서 새로운 객체에 집어넣었을 뿐임
하지만 같은 트랜잭션 내에서 가져온 두개의 객체는 같은 객체로 인식함! 왜냐하면? 같은 트랜잭션은 1차 캐시에서 가져오기 때문임~~
이건 좀 중요한 속성일듯. 두 객체의 정합성을 비교할 때 같은 트랜잭션 내에서만 비교를 해야하기 때문.
[트랜잭션을 지원하는 쓰기 지연]
내 최종 프로젝트에서 적용한 BatchSize 얘기 같음. 쿼리를 그때그때 날리지 않고 모아서 한번에 쿼리를 날리는 것.
따라서 불필요하게 중복되는 쿼리를 줄일 수 있어 App과 DB의 연결 횟수를 줄일 수 있음.
[변경 감지]
우리가 아주 자주 쓰던 것. 영속성 컨텍스트 안에서 관리되는 Entity는 데이터가 변경될 경우 flush를 하지 않아도 자동으로 DB에 업데이트 쿼리가 날아가서 DB에 반영이 됨.
[지연 로딩]
아직 말씀을 안해주심 ㅎㅎ;;
지연로딩은 내가 알기로 객체를 불러오는 쿼리를 내가 원하는 때에 맞춰 날리는 것으로 알고 있음. 예를 들어 Member Table을 조회할 때 Member와 Team이 N:1 관계를 맺을 때, Team Table의 정보가 필요할 때만 쿼리를 날리기 위해서 Member에 쿼리를 날릴 때 쿼리 타이밍을 조절해서 Team 쿼리가 필요할때까지 기다렸다가 날리는 것으로 알고 있음.
이를 통해 쿼리 수를 줄일 수 있음.
그렇다면 영속성 컨텍스트에 Entity를 넣어놨다. 이걸 언제 DB에 반영하는지?
그건 바로 EntityManager의 flush()메서드를 이용해서임.
???근데 우리 실습코드엔 flush()메서드가 없는데요? commit()안에 flush가 존재함.