ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JPA] 연관관계의 주인
    프로그래밍/JPA 2021. 10. 21. 18:08
    반응형

    이 글은 혼자 학습한 내용을 바탕으로 작성되었습니다.

    틀리거나 잘못된 정보가 있을 수 있습니다.

    댓글로 알려주시면 수정하도록 하겠습니다.


    1. 연관관계의 주인

    이전 글에서 (회원 -> 팀) 단방향 매핑에서 (회원 -> 팀, 팀 -> 회원) 양방향 매핑을 위해 팀 엔티티의 MemberList에 OneToMany 어노테이션과 mappedBy 속성이 추가하였습니다.

    양방향 연관관계는 DB의 경우 외래 키 하나를 가지고 양방향 연관관계를 맺습니다.

     

    그러나 엔티티의 경우 두 엔티티에서 단방향 연관관계를 맺음으로 양뱡향 연관관계 처럼 연관관계를 맺습니다.

     

    이때 엔티티의 양방향 연관관계 관점에서는 참조가 2개가 되고 DB의 관점에서 양방향 연관관계는 외래 키 1개가 됩니다.

     

    이러한 엔티티와 DB의 차이 때문에 엔티티의 양방향 연관관계의 경우 연관관계의 주인을 지정하여 주인만 DB의 연관관계와 매핑되고 외래 키를 관리할 수 있습니다.

     

    반대로 주인이 아닌 위 사진의 members는 읽기(조회)만 가능합니다.

     

    2. 주인관계 설정

    양방향 연관관계의 주인이 된 엔티티 속성은 mappedBy 속성을 사용하지 않고 반대로 주인이 아닌 경우는 mappedBy 속성을 사용해서 양방향 연관관계의 주인이 누구인지를 지정해야 합니다.

     

    연관관계의 주인을 지정하는 것을 DB의 외래 키를 관리할 엔티티를 정하는 것입니다.

     

    하여 주인은 DB의 외래 키를 가지고 있는 엔티티가 주인이 되어야 합니다.

     

    회원과 팀 관계에서 외래 키는 회원 엔티티와 매핑되는 MEMBER테이블에 존재합니다.

     

    그러므로 회원과 팀과의 양방향 연관관계에서는 회원 엔티티가 연관관계의 주인이 되어야 합니다.

     

    ※ 다대일, 일대다 관계에서는 항상 다 쪽에 외래 키가 생성된다. 그러므로 ManyToOne 어노테이션에는 mappedBy 속성이 존재하지 않는다.

     

    3. 양방향 연관관계 주의사항

    양방향 연관관계의 경우는 주인이 존재한다고 위에서 설명하였습니다.

     

    주인 엔티티는 DB의 외래 키를 관리 할 수 있지만 주인이 아닌 엔티티는 DB의 외래 키를 관리 할 수 없고 읽기만 가능 합니다.

     

    그러므로 주인이 아닌 엔티티에 연관관계를 맺고 저장을 하여도 DB에는 엔티티에 맺은 연관관계가 정상적으로 저장되지 않습니다.

     

    public void relactionOwner(EntityManager em){
    	Member member1 = new Member("member1", "회원1");
    	em.persist(member1);
        
    	Team team1 = new Team("team1", "팀1");
    	team1.getMembers().add(member1);
    	em.persist(team1);
    }

    위 코드를 보면 우리가 희망하는 결과는 MEMBER 테이블에

    member1 회원1 team1

    위 표처럼 Row 하나가 추가되길 바라고 코드를 작성 하였습니다.

     

    member1 회원1 Null

    하지만 DB에 저장된 결과는 위 표처럼 Row 하나가 추가 되었습니다.

     

    이유는 양방향 연관관계에서의 주인인 Member 엔티티에 연관관계를 맺어주지 않아서 입니다.

     

    위 코드는 주인이 아닌 Team 엔티티에 Member 엔티티와 연관관계를 맺고 Team 엔티티를 저장 하였기 때문에 MEMBER 테이블에는 TEAM_ID 컬럼이 Null이 입력되는 것 입니다.

     

    public void relactionOwner(EntityManager em){    
    	Team team1 = new Team("team1", "팀1");
    	em.persist(team1);
        
    	Member member1 = new Member("member1", "회원1");
    	member1.setTeam(team1);
    	em.persist(member1);
    }

    위 코드 처럼 양방향 연관관계의 주인인 Member엔티티에 Team엔티티와 연관관계를 맺고 Member 엔티티를 저장하면 우리가 원하는 Row가 저장 될 것입니다.

     

    4. 객체 관점의 양방향 연관관계

    엔티티의 양방향 연관관계는 주인인 엔티티에만 연관관계를 설정하면 DB에는 정상적으로 데이터가 입력되는 것을 알 수 있습니다.

     

    그럼 양방향 연관관계는 주인 엔티티에만 연관관계를 설정하면 되는 것일까?

     

    객체의 관점에서 보면 회원이 포함된 팀이 무엇인지 member.getTeam()을 통해 확인이 가능 해야 합니다.

     

    반대로 팀에서도 해당 팀에 속한 회원들이 누구인지 team.getMembers()를 통해 확인이 가능 해야합니다.

     

    DB와 매핑이 되는 것은 주인 엔티티에 연관관계를 맺어주면 되지만 엔티티를 비즈니스 로직을 처리하면서 사용하다 보면 두 엔티티 모두에 연관관계를 맺어주는 것이 가장 안전하며 추후 생길 문제를 방지할 수 있다.

    반응형

    '프로그래밍 > JPA' 카테고리의 다른 글

    [JPA] Dirty Checking(변경 감지)  (0) 2021.12.24
    [JPA] 예외 처리  (0) 2021.11.05
    [JPA] 연관관계  (0) 2021.10.20
    [JPA] Entity 매핑  (0) 2021.10.17
    [JPA] 영속성 컨텍스트  (0) 2021.10.14

    댓글

Designed by Tistory.