[JPA] Entity와 Serializable

maxxyoung·2022년 11월 9일
0

문제 상황

Member 객체, FriendRelation 객체는 1:N의 관계를 맺고 있음
하지만 FriendRelation 객체에 Member 객체를 매핑할 때 PK를 FK로 쓴것이 아닌 회원의 아이디를 FK로 썼음
FriendRepository에서 친구 객체에 멤버객체를 조인한 리스트를 가져오려고 했는데

public List<FriendRelation> findRequestedFriend(String myId, String status) {
        return em.createQuery("select fr from FriendRelation fr join fetch fr.friend where fr.friend.id = :myId and fr.status = :status", FriendRelation.class)
                .setParameter("myId", myId)
                .setParameter("status", status)
                .getResultList();
    }

다음과 같은 오류가 발생

ClassCastException : MemberCompany cannot be cast to java.io.Serializle

발생 이유

영속성 컨텍스트는 엔티티의 PK를 사용해서 엔티티를 관리함
JPA를 구현한 하이버네이트 입장에서 Member 객체를 가져오는데 PK가 아닌 다른필드, 즉 아이디 필드로 데이터를 조회하고, 그 결과에 있는 PK를 다시 찾아서 영속성 컨텍스트에서 객체를 관리하게 됨
이 속에서 엔티티를 생성하고 관리하는 복잡한 라이프사이클이 존재
이 복잡한 과정을 풀어내기 위해 하이버네이트 구현체는 객체를 임시로 직렬화(Serializable)해서 메모리에 올려두는 작업을 함
이 과정 때문에 객체(자바)에에 직렬화를 구현해야함

영한쌤의 설계 조언

  • 설계 관점에서 모든 연관관계는 PK를 보도록 설계하는 것이 좋은 설계
  • 만약 PK가 아닌 다른 컬럼을 보야한다면, 올바른 연관관계가 아니라고 판단하고 연관관계를 끊어버림(연관관계가 없어도 조인은 가능함)
  • 해당 컬럼이 성능상 필요하면 역정규화

그럼 어떻게 수정할까

방법은 2가지

  • 연관관계를 끊어버림
  • 엔티티의 연관관계를 PK를 보도록 수정

첫번째는 친구 관계에 있어서 사용자 정보가 꼭 필요하므로 옳은 방법이 아님

왜 아이디로 매핑했냐면 화면에서 아이디만 넘어온다고 가정을 했기 때문에 다시 PK를 알려면 디비에 한 번 갔다와야해서 아이디로만 연관관계를 맺음
근데 애초에 화면에서 PK가 넘어 왔다면 PK로만 연관관계를 맺어도 됐을 것 같음

2번째로 하도록 수정하는게 옳음

느낀점: 잘못된 설계는 다 갈아 엎어야하는구나..

참고

profile
오직 나만을 위한 글. 틀린 부분 말씀해 주시면 감사드립니다.

1개의 댓글

comment-user-thumbnail
2023년 4월 6일

감사합니다. 제가 궁금한 것들을 깔끔하게 정리해주셨네요!

답글 달기