다양한 연관관계 매핑(1) - slahsk/study GitHub Wiki

다대일

객체 양방향 관계에서 연관관계의 주인은 항상 다쪽이다.

다대일 단방향[N:1]

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

    private String username;

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

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

    private String name;

  }

Member.team으로 팀 엔티티를 참조할 수 있지만

반대로 팀에서는 회원을 참조하는 필드가 없다. 따라서 회원과 팀은 다대일 단방향 연관관계이다.

다대일 양방향[N:1, 1:N]

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

    private String username;

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

    public void setTeam(Team team){
      this.team = team;

      //팀의 멤버중에 자기 자신이 없으면 추가
      if(!team.getMembers().contain(this)){ //양쪽에 작성되어 있기에 무한루프 방지
        team.getMembers().add(this);
      }

    }
    ...
  }

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

    private String name;

    @OneToMay(mappedMy="team")
    private List<Member> members = new ArrayList<>();

    //
    private void addMember(Member member){
      this.members.add(member);

      //멤버의 팀이 자기자신이 아니면 멤버에 팀 추가
      if(member.getTeam() != this){//양쪽에 작성되어 있기에  무한루프 방지
        member.setTeam(this);
      }
    }
  }

양방향은 외래 키가 있는 쪽이 연관관계의 주인이다.

양방향 연관관계는 항상 서로를 참조해야한다. 항상 서로 참조하게 하려면 연관관계 편의 메소드를 작성하는것디 좋은데 setTeam(), addMember() 메소드가 편의 메소드들이다.

편의 메소드는 한 곳에서만 작성하거나 양쪽에 다 작성할 수 있는데, 양쪽에 다 작성하면 무한루프에 빠지므로 주의해야한다.

일대다

일대다 관계는 엔티티를 하나이상 참조할 수 있다.(Collection, List, Map, Set)

일대다 단방향[1:N]

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

    private String username;

    ...
  }

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

    private String name;


    //member 마다 각각의 외래키를 가지고 있다. 본인이 아닌 다른테이블에 관리
    @OneToMay
    @JoinColumn(name = "TEAM_ID")
    private List<Member> members = new ArrayList<>();
  }

본인 테이블에 외래 키가 있으면 엔티티의 저장과 연관관계 처리를 INSERT SQL 한 번으로 끝낼 수 있지만, 다른 테이블에 외래 키가 있으면 연관관계 처리를 위한 UPDATE SQL을 추가로 실행해야 한다.

  Mmeber member1 = new Member("member1");
  Mmeber member2 = new Member("member2");

  Team team1 = new Team("team1");
  team1.getMembers().add(member1);
  team1.getMembers().add(member2);

//팀 정보가 디비에 없다
//멤버 입력후 팀이 입력후 member 에 팀정보가 업데이트 가 실행 된다.
  em.perist(member1);
  em.perist(member2);
  em.perist(team1);

  transaction.commit();

일대다 단방향 매핑보다는 다대일 양방향 매핍을 사용하자 일대다 단뱡향 은 다른 테이블에서 외래키를 관리해야 한다.

성능 문제도 있지만 괸리도 ?? 부담스럽다.

일대다 양방향[1:N, N:1]

다대일 방향 매핍을 사용

⚠️ **GitHub.com Fallback** ⚠️