[JPA] 영속성을 간과했던 나

이동엽·2023년 3월 10일
1

jpa

목록 보기
7/8
post-thumbnail

배경

평화롭던 금요일 오후, 간단한 기능들을 구현하고 검토하던 와중에 요상한 로직을 발견한다.


해당 로직

  • 이 프로젝트에는 예약 기능이 존재한다.
    • 따라서 어떤 회원이, 어떤 병원에 예약했는지를 담기 위해 Appointment 엔티티는 MemberHospital을 참조한다.

  • 우선 정적 생성 메서드를 만들었고.. 서비스에서는 예약 정보를 받아 Repository로 넘긴다.
    • (이후 Repository에서는 Entitymanager를 이용해 persist 함!)
    • 그러다 불현듯 스친 생각 : ‘?? 이러면 서비스에 넘길때 필요한 Appointment는 어디서 만들지??
      • → 그렇다. 여기서 잘못되었다.

문제점

  • JPA를 이용하면 엔티티 간에 참조가 된다지만, 현재는 객체를 직접 인자로 받고 있다.
    • → 따라서 넘어온 객체는 비영속 객체이다.
    • 변경을 인지하도록 하기 위해선 id를 매개변수로 넘겨받고, findOne() 메서드로 조회하여 쓴다면 영속 상태를 유지할 수 있다.

이제 뜯어 고쳐보자!

1. Service 뜯어고치기

  • 예약 정보에 필요한 MemberHospital변경 감지를 이용하기 위해 영속 상태를 유지해야 한다.
    • 따라서, id를 이용한 조회를 통해 가져와야 한다. → MemberService , HospitalService 를 필드로 추가!
  • 이후엔 각각의 service를 이용해 findOne() 메서드로 기본 키인 id를 이용해 조회하여 가져왔다.
  • 그리고 마지막에서야 미리 엔티티에 작성해놓은 정적 생성 메소드의 매개변수로 조회한 객체들을 넘겨준다.

2. ServiceTest 뜯어고치기

기존 로직

  • 위에서 Service의 save() 의 매개변수를 대거 수정했으니, 테스트 코드도 마저 수정이 필요하다.


수정한 로직

  • 매개변수가 많아 화면에선 짤렸지만, 제대로 변경사항에 맞게 작성하였다.


이제 테스트 코드를 실행해보면 잘 되겠지??

결과 : ???????

  • 오류 메시지를 보니 매개변수에 들어가있는 id가 필요로 하다고 한다.
    • 즉, id가 없다!!

해결 방법

  • 현재 매개변수로 넘겨준 member와 hospital의 id가 없는 상황이다.
    • 이는 당연하다. 왜냐?? 단지 객체를 생성했을 뿐, DB에 저장하지도 않았다!

  • 따라서 EntityManager를 의존성 주입하고, 각각의 회원과 병원을 먼저 저장해주어 id를 얻도록 하였다.
    • 결과 → 테스트 성공!

교훈 : 영속성을 항상 염두에 두자..

profile
백엔드 개발자로 등 따숩고 배 부르게 되는 그 날까지

0개의 댓글