본문 바로가기
JPA

JPA - 다양한 연관관계 매핑(2) : 일대다 [1 : N]

by 왈레 2022. 4. 9.

1. 일대다 단방향

public class Team{
    @OneToMany // (mappedBy = "team") 가 빠짐
    @JoinColumn(name = "TEAM_ID") //@JoinColumn이 추가됨
    private List<Member> members = new ArrayList<>(); // 단순 조회가 아닌 변경이 가능해짐
}
public class Member{
	...
    // 아무것도 해줄 필요 없음
}

 

Member member = new Member("member1");
em.persister(member);

Team team = new Team("teamA");

team.getMembers().add(member); // 이런 코드가 가능해진다.
em.persist(team);

TEAM과 MEMBER의 데이터베이스 테이블 연관관계는 이전의 다대일과 100% 동일하다. (당연한거)

하지만 일대다 관계에서 일(Team)이 외래 키를 관리하는 연관관계의 주인이다.

 

 

일대다 단방향 정리

  • 일대다 단방향은 일대다(1:N)에서 일(1)이 연관관계의 주인
  • 테이블 일대다 관계는 항상 다(N) 쪽에 외래 키가 있음 (당연한거)
  • 객체와 테이블의 차이 때문에 반대편 테이블의 외래 키를 관리하 는 특이한 구조
  • @JoinColumn을 꼭 사용해야 함. 그렇지 않으면 조인 테이블 방식을 사용함 (중간에 테이블을 하나 추가함)

 

일대다 단방향의 문제점

Member member = new Member("member1");
em.persist(member);

Team team = new Team("teamA");
team.getMembers().add(member);

em.persist(team);

위의 코드에서는 update member 쿼리가 나가게된다.

왜냐하면 외래 키가 Team 테이블에 있는게 아니라, Member 테이블에 있기때문이다.

일대다에서는 무저건 쿼리가 한번 나가게된다. (크지는 않지만 성능상 약간의 패널티가 있다.)

 

성능상 단점이 있는데 크게 문제는 아니다.

더 큰 문제는 지금처럼 team을 persist했는데 member update가 나가게되면 개발자 입장에서 해석하기가 힘들어질수 있다.

실무에서는 엄청 많은 테이블들끼리 연관관계를 맺고해서 운영이 더욱 힘들어진다.

엔티티가 관리하는 외래 키가 다른 테이블에 있다는 것은 어마어마한 단점이다.

 

★일대다 단방향 매핑보다는 "다대일 양방향 매핑"을 사용하는 것이 좋다.★

일대다 구조를 택하는 방식보다는 다대일 선택하고 양방향 연관관계 매핑을 짓는게 낫다.

객체지향적으로 조금 손해를 보더라도 (예를들어 member에서 team 참조할일이 없다고 해도)

Member연관관계 주인을 설정하고 양방향 맵핑을 하는게 유지보수에 유리하다.

 

 

 

2. 일대다 양방향

public class Team{
    @OneToMany
    @JoinColumn(name = "TEAM_ID")
    private List<Member> members = new ArrayList<>();
}
public class Member{
    @ManyToOne
    @JoinColumn(name = "TEAM_ID", insertable = false, updateble = false)
    private Team team;
}
  • 이런 매핑은 공식적으로 존재하지 않는다.
  • @JoinColumn(insertable=false, updatable=false)
  • 읽기 전용 필드를 사용해서 양방향 처럼 사용하는 방법
  • 다대일 양방향을 사용하자

 

★다대일과 일대다 차이 정리★

  • 다대일과 일대다의 DB 테이블은 100% 동일하다.
  • @JoinColumn을 누가 가지고 있냐, 즉 외래 키 관리를 하는 객체의 관점에서 따라 다대일, 일대다로 나뉜다.
  • 다대일 단방향은 N이 외래키를 관리, 1은 아무것도 추가하지않음
  • 다대일 양방향은 N이 외래키를 관리, 1은 N객체를 참조하고 mappyedBy설정
  • 일대다 단방향은 1이 외래키를 관리, N에는 아무것도 추가하지않음 (다대일 양방향으로 대체)
  • 일대다 양방향은 1이 외래키를 관리, N은 1을 추가하고 읽기전용필드를 사용해서 양방향처럼 사용
    (다대일 양방향으로 대체)
  • 간단하게 일대다는 단방향이건 양방향이건 사용 자체를 하지말고 "다대일 양방향"으로 대체

댓글