다양한 연관관계 매핑

강한친구·2022년 7월 11일
0

JPA

목록 보기
8/27

연관관계 매핑 시, 고려할 상황

  • 다중성
  • 단방향, 양방향
  • 연관관계의 주인

다대일 @ManyToOne

다대일은 이전글에서 만들었던 Member, Team 구조가 ManyToOne 구조이다.

@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
}

Member쪽이 주인이 된다.
Team도 만약 거꾸로 Member로 가보고싶다면 양방향 설계를 하면 된다.

@Entity
public class Team {

    @Id @GeneratedValue
    @Column(name = "TEAM_ID")
    private long id;
    private String name;

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();
}

일대다 @OneToMany

아까 만든 Member Team에서 Team을 중심으로 무언가를 한다고 하면 OneToMany가 된다.
하지만 DB쪽에서는 다를 가진 테이블에 FK를 설정해야한다.

try {
            Team team = new Team();
            team.setName("TeamA");
            em.persist(team);

            Member member = new Member();
            member.setUsername("UserA");
            em.persist(member);

            team.getMembers().add(member);

            tx.commit();
        }

일대다 관계를 만들고 이런 쿼리를 작성해서 실행해보면,

이렇게 db에는 정상적으로 나가는것을 볼 수 있지만, FK가 member테이블에 있어서 member 테이블 업데이트 없이는 Team에다가 member를 어떻게 할 수가 없다. 따라서 query가 update에 한번 더 나가게 되고 이는 추후 성능저하가 될 수 있다.

일대일 @OneToOne

일대일관계는 아무대나 외래키를 넣어도 된다.
주 테이블에 넣거나, 대상 테이블에 넣거나 한가지를 선택해야한다. 또한 외래키에 데이터베이스 유니크 제약조건이 추가해야한다.

@Entity
public class Locker {

    @Id @GeneratedValue
    private long id;

    private String name;
    
    @OneToOne(mappedBy = "locker")
    private Member member;
}
@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

    @OneToOne
    @JoinColumn(name = "LOCKER_ID")
    private Locker locker;
}

Locker와 Member는 1대1 관계이다.
이 방식이 가장 간단한 연관관계이고 양방향의 경우 똑같이 반대편에 mappedBy를 넣어주면 된다.

어디 테이블에 외래키를 넣는가

  • 주 테이블
    • 주 테이블에 외래키를 두고 대상테이블을 찾는다.
    • 객체지향 개발자들이 선호한다
    • JPA 매핑이 편리하다
    • 장점 : 주 테이블만 조회해도 대상테이블 데이터 여부를 확인할 수 있다.
    • 단점 : 값이 없다면 외래키에 null이 허용된다.
  • 대상 테이블에 외래키
    • 대상테이블에 외래키를 놔둔다
    • 전통적 DB 개발자들이 이를 선호한다
    • 장점 : 주 테이블과 대상테이블 관계를 변경할 떄 구조가 유지가 된다
    • 단점 : JPA에서 양방향으로 만들어야만 한다. 프록시 기능의 한계로 지연로딩으로 설정해도 항상 즉시로딩 해버린다.

다대다 @ManyToMany

다대다의 경우 객체는 컬랙션을 이용해서 객체 2개로 다대다를 구현한다.

테이블의 경우 가운데 테이블을 만들어서 매핑을 해준다.

이는 매우 편리해보이지만, 실무에서는 사용할수가 없다.
연결테이블이 단순하게 연결하고 끝나지 않고 안에 추가데이터가 들어가야해서 문제가 발생한다.

따라서 엔티티 연결용 테이블을 직접 만들어서 사용하는것이 권장된다.

0개의 댓글