Blog

[Spring][JPA]49_2 Entity 연관관계 햇갈려서 예시를 통해 한번 더 정리

Category
Author
Tags
PinOnMain
1 more property

다대일 (N:1) 관계 단방향과 양방향

1. 다대일 관계 단방향

다대일 (N:1) 관계 (단방향)
예시: 하나의 주문(Order)은 하나의 고객(Customer)에 속합니다.
설명:
여러 주문은 같은 고객에게 속할 수 있지만, 하나의 주문은 오직 하나의 고객에 속합니다. 이것은 다대일 관계입니다.
따라서 Order 엔티티에는 customer라는 속성(또는 외래 키)이 있을 것이며, 이 속성은 Customer 엔티티를 참조합니다.
Spring JPA 어노테이션
@Entity: 엔티티 클래스임을 표시합니다.
@ManyToOne: 다대일 관계를 나타내며, 이 어노테이션은 Order 엔티티의 customer 속성과 관련됩니다.
@JoinColumn: 외래 키를 지정합니다. @ManyToOne과 함께 사용하여 어떤 컬럼이 외래 키인지 지정합니다. 키의 주인
@Entity public class Order { // 다른 필드들... @ManyToOne @JoinColumn(name = "customer_id") private Customer customer; // Getter와 Setter... } @Entity public class Customer { // 다른 필드들... // Getter와 Setter... }
Java
복사

2. 다대일 관계 양방향

다대일 (N:1) 관계 (양방향)
예시: 하나의 주문(Order)은 하나의 고객(Customer)에 속합니다. 동시에 하나의 고객도 여러 주문을 가질 수 있습니다.
Spring JPA 어노테이션:
@Entity: 엔티티 클래스임을 표시합니다.
@ManyToOne: 다대일 관계를 나타내며, Order 엔티티의 customer 속성과 관련됩니다.
@JoinColumn: 외래 키를 지정합니다. @ManyToOne과 함께 사용하여 어떤 컬럼이 외래 키인지 지정합니다.
@OneToMany: 일대다 관계를 나타내며, Customer 엔티티의 customer 로 참조됩니다. Customer 엔티티에서 orders 리스트와 관련됩니다.
@Entity public class Order { // 다른 필드들... @ManyToOne @JoinColumn(name = "customer_id") private Customer customer; // Getter와 Setter... } @Entity public class Customer { // 다른 필드들... @OneToMany(mappedBy = "customer") private List<Order> orders; // <<<<-----양방향으로 추가됨 // Getter와 Setter... }
Java
복사

일대다 (1:N) 관계 단방향과 양방향

1. 일대다 관계 단방향

일대다 (1:N) 관계 (단방향)
다쪽에서 일에 대한 참조가 필요없을 때 위와 같이 일이되는 쪽에 @OneToMany를 사용한다.
이떄 @JoinColumn으로 외래키를 지정해줘야한다. 그래야 해당 컬럼을 외래키로 쓸 것임을 JPA가 알 수 있다.
생성을해서 쿼리를 살펴보자
1:N 관계에선 N 쪽에 FK가 있기 때문에 팀 엔티티의 Team.members로 회원 테이블의 TEAM_ID FK 관리
따라서 1쪽에서 관리하는 FK가 N 쪽의 테이블에 있다는 것이 단점
이 경우 엔티티 저장과 연관관계 처리를 위해 insert 이외에 추가로 update sql을 실행해야 함
결론 => 일대다 단방향보다는 다대일 양방향 매핑을 사용하자!!!
@Entity public class Member { @Id @GeneratedValue private Long id; // Getter와 Setter... } @Entity public class Team { // 다른 필드들... @OneToMany @JoinColumn(name = "team_id") private List<MemberOtM> members = new ArrayList<>(); // Getter와 Setter... }
Java
복사
객체관계에서는 Team이 member 쪽으로 참조를 하지만 테이블에서 외래키를 갖고 있는쪽은 member이기때문에 insert 2번, update1번이 실행된다.
member를 persist할 때 insert 한번 team을 persist할때 insert 한번 member의 team_id(FK)를 updata하는 쿼리 한번 이렇게 3번이 나가는 것
일단 외래키를 갖은 member쪽에서 team 방향으로 단방향으로 설계를 하고 , team에서 member의 참조가 필요하다면 맵핑을 추가해주는 것이 좋다.

2. 일대다 관계 양방향

일대다 (1:N) 관계 (양방향)
정확히는 일대다 양방향 매핑에서 @OneToMany는 데이터베이스의 특성상 연관관계의 주인이 될 수 없다. 일대다 관계에서는 항상 다 쪽에 외래 키가 존재하기 때문이다. 그래서 @ManyToOne에는 mappedBy 속성이 없다.
스펙상 공식적으로 나와 있는 것은 아니고 억지로 할 수 있다 잘 사용하지 않는다.
반대쪽 방향에서도 @joinColumn을 걸어 주면된다. 대신 이렇게 되면 양쪽 다 연관관계의 주인이 되기 떄문에 주인이 아닌곳에
옵션으로 insertable = false updatable = false 를 넣어줘야한다 아래 코드와 같다 주인이 아닌곳에서 조회만 가능하게 하는 것
사실 일대다 양방향과 다대일 양방향이 똑같은 말이기 때문에 가능한 다대일 양방향을 사용하는 것이 좋다.
1:N, N:1 관계에서 항상 N 쪽에 FK가 있기 때문에 양방향 매핑에서 @OneToMany는 연관관계의 주인이 될 수 없다. 따라서 일이 연관관계의 주인인 일대다 양방향 매핑은 존재하지 않는다. 다만 일대다 단방향 매핑 반대편에 다대일 단방향 매핑을 읽기 전용으로 추가해서 일대다 양방향처럼 보이도록 할 수 있다. 하지만 이 방법도 위에서 설명한 일대다 단방향 매핑의 단점을 그대로 가진다.
@Entity public class Team { @Id @GeneratedValue @Column(name = "TEAM_ID") private Long id; private String name; @OneToMany(mappedBy = "team") @JoinColumn(name = "TEAM_ID") // MEMBER 테이블의 TEAM_ID (FK) private List<Member> members = new ArrayList<Member>(); } @Entity public class Member { @Id @GeneratedValue @Column(name = "MEMBER_ID") private Long id; private String username; @ManyToOne @JoinColumn(name = "TEAM_ID", insertable = false, updatable = false) // 읽기 전용 private Team team; }
Java
복사

다대다 (N:M) 관계 단방향과 양방향

1. 다대다 관계 단방향

다대다 (N:M) 관계 (단방향)
예시: 여러 학생(Student)이 여러 과목(Course)을 수강할 수 있으며, 한 과목에는 여러 학생이 수강할 수 있습니다.
설명:
여러 엔티티가 여러 개의 다른 엔티티와 관련이 있을 수 있는 관계입니다. 다대다 관계는 일반적으로 연결 테이블(중개 엔티티)을 사용하여 해결됩니다.
예를 들어, Student 엔티티와 Course 엔티티 사이에는 중개 테이블(예: StudentCourse)이 있으며, 이 테이블은 어떤 학생이 어떤 과목을 수강하는지를 나타냅니다.
Spring JPA 어노테이션
@Entity: 엔티티 클래스임을 표시합니다.
@ManyToMany: 다대다 관계를 나타내며, Student 엔티티와 Course 엔티티 사이에 중개 테이블을 생성합니다.
@Entity public class Student { // 다른 필드들... @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private List<Course> courses; // Getter와 Setter... } @Entity public class Course { // 다른 필드들... @ManyToMany(mappedBy = "courses") private List<Student> students; // Getter와 Setter... }
Java
복사

2. 다대다 관계 양방향

다대다 (N:M) 관계 (양방향)
예시: 여러 학생(Student)이 여러 과목(Course)을 수강할 수 있으며, 한 과목에는 여러 학생이 수강할 수 있습니다.
Spring JPA 어노테이션:
@Entity: 엔티티 클래스임을 표시합니다.
@ManyToMany: 다대다 관계를 나타내며, Student 엔티티와 Course 엔티티 사이에 중개 테이블을 생성합니다.
@JoinTable: 중개 테이블의 이름과 외래 키 컬럼을 지정합니다.
@JoinColumn: 외래 키 컬럼 이름을 지정합니다.
@Entity public class Student { // 다른 필드들... @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private List<Course> courses; // Getter와 Setter... } @Entity public class Course { // 다른 필드들... @ManyToMany(mappedBy = "courses") private List<Student> students; // Getter와 Setter... }
Java
복사