다대일 (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
복사