JPA/JPA 기본

19. N : 1 다대일, 다양한 연관관계

sdafdq 2023. 10. 24. 12:20

연관관계는 

N : 1

1 : N

1 : 1

N : M

이렇게 있는데,

 

이번에는 N : 1을 알아볼 것이다. 즉, N이 연관관계 주인일 경우

 

 

연관관계 매핑 시 고려사항은

다중성

단방향, 양방향

양방향 일 시 연관관계 주인

 

다중성

@ManyToOne

@OneToMany

@OneToOne

@ManyToMany

이런 다중성 다 JPA가 제공

 

JPA의 애노테이션은 거의 전부 DB와 매핑하기 위해 있다고 생각하면 됨.

 

DB관점에서 다중성을 보면 됨.

 

다중성이란 일대다 같이 그런 관계를 말하는 거임. 뭐를 다로 해야 하고 뭐를 일로 해야 할 지.

 

근데,

@ManyToMany 다대다는 안 씀. 쓰면 안됨.

 

@ManyToOne 많이 씀

@OneToMany 필요하다고 느끼면 씀(양방향일때 쓰는 듯)

@OneToOne 가끔 씀

 

 

 

사실 테이블은 단방향, 양방향 이런 게 없음.

그냥 외래키 하나로 양쪽 조인 가능함.

 

근데 객체는 필드가 있는 쪽만 참조가 가능함.

그래서 두개 객체에 서로 참조를 추가해서 이 두개의 단방향을 합쳐서 이걸 양방향이라고 부르는 것.

 

 

그럼 본격적으로, N:1 단방향.

가장 기초고, 기본임. 이건 중요함.

DB 테이블 상에서 보통 다 쪽에 외래키가 있고,

그에 따라 객체도 따라서 다 쪽에 참조를 넣으면 됨.

 

다쪽에 외래키를 넣음.

 

단방향 연관관계이고, 객체상에서 외래키로 접근하고 싶은게 아니라 참조를 통해서 접근하고 싶다면,

@ManyToOne 해서 연관관계라는거 명시해 주면 됨.

@JoinColumn(name="") 해서 무슨 열이 연관관계에서 join하기 위해 필요한 열 인지 해 주고.

 

여튼, 우선 단방향.

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

    @Column(name="USERNAME", nullable = false)
    private String name;

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

테이블의 team_id열이 외래키임을 명시해 주고

그걸 이용해 Team을 가져오겠다.

Team 엔티티의 테이블을 참조할 듯.

저거하면 뭐 지연처리 때문에 호출할 때 DB에서 쿼리날려 불러오겠지만,

여튼 호출하면

Member에 의해 Team을 생성하는데, Team의 테이블이 TEAM이니 MEMBER의 외래키 TEAM_ID와 TEAM 테이블의 ID를 맞춰서 DB에서 값을 가져온 다음에, 그걸 Team 객체로 만들어서 Member에 넣어줌.

 

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

일단 단방향이니, 팀은 뭐 할것 없다.

 

 

 

그 다음 양방향.

객체상의 양방향 이란 것은 두개의 객체가 각각 서로를 참조하게 되는 이 두가지의 단방향을 편의 상 양방향 이라고 부르는 것 이므로, 이미 Member가 Team의 연관관계는 단방향으로 보기에,

Team만 연관관계를 추가시켜주면 된다.

 

@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(mappedBy = "team")
private List<Member> members = new ArrayList<>();

이걸 추가시켜 줬다.

@OneToMany 해서 일대다 라는 것을 일러주고,

mappedBy 해서 저 다쪽, 다(다니까 List) 쪽의 하나의, 즉 Member 객체의 "team"이라는 이름을 가진 필드가 우리가 참조할 것 이다.

mappedBy이므로 내가 주인이 아니기 때문에, Team의 members는 그냥 읽기전용이다.

Team의 members를 바꿔봤자 DB에 반영되지 않는다.

mappedBy라는 뜻 그대로 Member객체의 필드 "team"에 의해 매핑된 것이다.