배경
평화롭던 금요일 오후, 간단한 기능들을 구현하고 검토하던 와중에 요상한 로직을 발견한다.
해당 로직
- 이 프로젝트에는 예약 기능이 존재한다.
- 따라서 어떤 회원이, 어떤 병원에 예약했는지를 담기 위해
Appointment
엔티티는 Member
와 Hospital
을 참조한다.
- 우선 정적 생성 메서드를 만들었고.. 서비스에서는 예약 정보를 받아 Repository로 넘긴다.
- (이후 Repository에서는 Entitymanager를 이용해 persist 함!)
- 그러다 불현듯 스친 생각 : ‘?? 이러면 서비스에 넘길때 필요한 Appointment는 어디서 만들지??’
문제점
- JPA를 이용하면 엔티티 간에 참조가 된다지만, 현재는 객체를 직접 인자로 받고 있다.
- → 따라서 넘어온 객체는 비영속 객체이다.
- → 변경을 인지하도록 하기 위해선 id를 매개변수로 넘겨받고,
findOne()
메서드로 조회하여 쓴다면 영속 상태를 유지할 수 있다.
이제 뜯어 고쳐보자!
1. Service 뜯어고치기
- 예약 정보에 필요한
Member
와 Hospital
는 변경 감지를 이용하기 위해 영속 상태를 유지해야 한다.
- 따라서, id를 이용한 조회를 통해 가져와야 한다. →
MemberService
, HospitalService
를 필드로 추가!
- 이후엔 각각의 service를 이용해
findOne()
메서드로 기본 키인 id를 이용해 조회하여 가져왔다.
- 그리고 마지막에서야 미리 엔티티에 작성해놓은 정적 생성 메소드의 매개변수로 조회한 객체들을 넘겨준다.
2. ServiceTest 뜯어고치기
기존 로직
- 위에서 Service의
save()
의 매개변수를 대거 수정했으니, 테스트 코드도 마저 수정이 필요하다.
수정한 로직
- 매개변수가 많아 화면에선 짤렸지만, 제대로 변경사항에 맞게 작성하였다.
이제 테스트 코드를 실행해보면 잘 되겠지??
결과 : ???????
- 오류 메시지를 보니 매개변수에 들어가있는 id가 필요로 하다고 한다.
해결 방법
- 현재 매개변수로 넘겨준 member와 hospital의 id가 없는 상황이다.
- 이는 당연하다. 왜냐?? 단지 객체를 생성했을 뿐, DB에 저장하지도 않았다!
- 따라서
EntityManager
를 의존성 주입하고, 각각의 회원과 병원을 먼저 저장해주어 id를 얻도록 하였다.
교훈 : 영속성을 항상 염두에 두자..