• 방향 : 단방향, 양방향이 존재한다.
    • JPA에는 단방향만 존재하며 양방향의 경우 단방향이 양쪽에서 이루어진다
    • DB에서는 양방향만 존재한다
  • 다중성 : 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:N)

다대일(N:1), 일대다(1:N)

(1) 단뱡향 연관관계

  • 한 멤버는 한 팀에 속하고 한 팀에는 여러 멤버가 속한다 (Member N : Team 1)
@Entity
public class Team {
    @Id
    private String id;
    private String name;
}

@Entity
public class Member {
    @Id
    private String id;
    private String username;

    @ManyToOne
    @JoinColumn(name="team_id")
    private Team team;
}
  • MemberTeam 은 접근이 가능하다 (member.getTeam())
  • TeamMember 는 접근 불가능하다

(2) 양방향 연관관계

  • 기존 단방향의 연관관계를 TeamMember 접근도 가능하게 해보자
@Entity
public class Member {
    @Id
    private String id;
    private String username;

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

@Entity
public class Team {
    @Id
    private String id;
    private String name;

    @OneToMany(mappedBy = "team", cascade = CascadeType.ALL)
    private List<Member> members = new ArrayList<Member>();
}
  • Team : Member = 1 : N 관계 이기 때문에 List를 사용한다
  • mappedBy 속성
    • 객체 연관관계에는 양방향이 존재하지 않기 때문에 단방향 2개로 양방향처럼 만들어야 한다.
    • 실제 DB는 외래키 하나로 양방향 관계를 맺는다. 두개의 연관관계 중 하나를 정해서 테이블의 외래키를 관리하는 주인을 설정해야 한다
    • 주인은 외래키를 관리(등록, 수정, 삭제) 할 수 있고 주인이 아닌 쪽은 읽기만 가능
    • mappedBy를 설정하지 않은 쪽이 주인이다
    • 정확히 정리하자면 @ManyToOne은 외래키를 갖고(주인)이고 @OneToMany는 외래키를 갖지 않는다
  • cascade 속성
    • 영속성 전이 속성으로 부모 엔티티에게 수행된 작업이 자식 엔티티에도 전파된다
    • 여기서는 Team에서 cascade가 걸려있기 때문에 Team이 지워지면 속한 Member들이 같이 지워지게 된다.

일대일(1:1)

  • 일대다, 다대일은 항상 다(N)쪽이 외래키를 갖지만 일대일은 양쪽 중 어느 곳이나 외래키를 갖을 수 잇다
  • 양쪽 중 어느 쪽에나 외래키를 갖을 수 있지만, 주인이 정해져야 한다.
    • 많이 사용되는 쪽을 주인으로 설정한다

(1) 단방향 연관관계

@Entity
public class Member {
    @Id
    private String id;
    private String username;

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

@Entity
public class Locker {
    @Id
    private String id;
    private String name;
}

(2) 양방향 연관관계

@Entity
public class Member {
    @Id
    private String id;
    private String username;

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

@Entity
public class Locker {
    @Id
    private String id;
    private String name;

    @OneToOne(mappedBy="locker")
    private Member member;
}

다대다(N:N)

  • DB에서 다대다 관계는 연결 테이블이 필요하다
  • 실무에서 사용하면 안된다
    • 이유 : @ManyToMany로 생성된 연결 테이블은 변경이 불가능해서 유연하지 못하다
    • 다대다(N:N)를 다대일(N:1)과 일대다(1:N)로 나누어 표현한다
    • 연결 테이블을 Entity로 직접 만든다

(1) 단방향 연관관계

@Entity
public class Member {
    @Id
    private String id;
    private String username;

    @ManyToMany
    @JoinTable(name="member_product",
            joinColumns=@JoinColumn(name="member_id"),
            inverseJoinColumns=@JoinColumn(name="product_id"))
    private List<Product> products = new ArrayList<Product>();
}

@Entity
public class Product {
    @Id
    private String id;
    private String name;
}

(2) 양방향 연관관계

@Entity
public class Member {
    @Id
    private String id;
    private String username;

    @ManyToMany
    @JoinTable(name="member_product",
            joinColumns=@JoinColumn(name="member_id"),
            inverseJoinColumns=@JoinColumn(name="product_id"))
    private List<Product> products = new ArrayList<Product>();
}

@Entity
public class Product {
    @Id
    private String id;
    private String name;

    @ManyToMany(mappedBy="products")
    private List<Member> members;
}