Spring JPA 삽질일지

최민수·2023년 4월 12일
0

[개발] Java Spring

목록 보기
16/18


영상에서는 Spring JPA를 쓰면서 직접 영속성 컨텍스트, JPQL, 지연 로딩에 관해 테스트 해보고 이해해보는 과정을 소개한다.

자바 스프링을 배우면서 나 또한 이런 궁금증과 문제를 마주했던 경험들이 있었기에 공감이 가고, 또 확실하게 정리하는 기회로 삼고자 글을 쓴다.


비영속, 준영속, 영속, 삭제 엔티티?

영속비영속 엔티티, 그리고 준영속 엔티티의 개념은 알고 있었다.

영속성 컨텍스트 안에서 직접 관리되고 있는 엔티티를 영속, 그렇지 않은 것은 비영속이며 한 때 영속 엔티티였지만 현재는 연결이 detach 되어 관리되고 있지 않은 엔티티를 준영속 엔티티라 한다.

그럼 삭제 엔티티는 무엇일까?

공식 문서의 설명은 다음과 같이 되어있다.

Removed Entity instances have a persistent identity, are associated with a persistence context, and are scheduled for removal from the data store.

즉, ID 값이 존재하고 영속성 컨텍스트와 연결이 되어있지만 DB에서 제거되도록 예약되어 있는 상태의 엔티티라고 한다. 바로 아래 그림과 같이 테스트에서 특정 데이터를 삭제하고 조회를 시도한다면 아이디는 존재하기 때문에 조회는 되지만 값을 가져올 수 없는 그런 상황인 것이다.


데이터 삭제 후 바로 DB에 반영이 될까?

영속성 컨텍스트와 그 안에 있는 1차 캐시, 그리고 쓰기 지연 SQL 저장소의 존재와 동작 원리를 알면 delete 메서드 호출 후 바로 DB에 반영이 되지 않는다는 사실을 알고 있을 것이다.

조금만 더 구체적으로 과정을 살펴보자면,
DB에 반영되기 전에 쓰기 지연 SQL 저장소에 쿼리를 쌓아두고 flush 발생 후 DB에 반영이 된다.

flush가 발생하는 경우는 크게 3가지 경우가 존재한다.
강제로 flush() 호출할 때, JPQL 쿼리가 실행될 때 관련있는 엔티티에 관한 쿼리는 flush가 이루어짐, 그리고 트랜잭션이 커밋될 때이다.

따라서 영속성 컨텍스트의 동일성을 보장하기 위해 헤매지 않으려면 위 과정을 이해하는 것이 필요하다.


프록시 객체에서 값을 읽어오지 못한다는 에러 메세지

위와 같은 에러 메세지를 마주하는 경우가 생각보다 많다.

양방향 연관관계에서 아래와 같이 fetch type 을 LAZY로 설정하면, 스프링에서는 해당 객체를 만들 때 연관관계가 있는 객체를 모두 만들어놓지 않고 프록시 객체를 쓴다. 그리고 실제로 값이 참조되거나 이용이 될 때 객체를 만든다.

@ManyToOne(fetch = FetchType.LAZY)
private Team team
...

따라서 이런 상황을 이해하지 못하고 바로 엔티티에서 값을 가져온다던가, 이러한 상황에서 Null Pointer exception이 터지는 경우가 생각보다 많다. 이럴 때는 해당 객체를 한번 참조해 주고 값을 가지고 오면 대부분 해결이 되었다.


영상 출처: [10분 테코톡] 잉, 페퍼의Spring Data JPA 삽질일지

profile
CS, 개발 공부기록 🌱

0개의 댓글