JPA에서의 연관관계: 단방향과 양방향
JPA에서 엔티티 간의 연관관계는 크게 단방향과 양방향으로 나뉘어. 이는 객체 간의 참조를 어떻게 설정하는지에 따라 구분돼. 또한, 연관관계는 일대일(1:1), 일대다(1:N), 다대일(N:1), **다대다(N:M)**로 나눌 수 있어. 각각의 경우를 단방향과 양방향으로 나누어 설명해줄게.
1. 단방향 연관관계
단방향 연관관계에서는 한쪽 엔티티만 다른 엔티티를 참조해. 즉, 객체 간의 관계가 한쪽으로만 연결돼 있는 경우야.
예시: 다대일(N:1) 단방향
• 상황: 여러 명의 학생이 한 명의 선생님에게 속해 있는 경우 (학생:선생님 = N:1).
• 설명: 학생(Student) 엔티티는 선생님(Teacher) 엔티티를 참조하지만, 선생님은 학생을 참조하지 않아.
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "teacher_id")
private Teacher teacher;
}
위 코드에서 Student는 Teacher를 참조하지만, Teacher는 Student를 참조하지 않기 때문에 단방향 관계야.
2. 양방향 연관관계
양방향 연관관계에서는 양쪽 엔티티가 서로를 참조해. 즉, 객체 간의 관계가 서로 연결되어 있어, 한쪽에서 다른 쪽을 조회할 수 있고, 반대쪽에서도 이를 조회할 수 있어.
예시: 다대일(N:1) 양방향
• 상황: 여러 명의 학생이 한 명의 선생님에게 속해 있고, 선생님은 자신의 학생들을 조회할 수 있음.
• 설명: 학생은 선생님을 참조하고, 선생님도 학생들을 참조하는 양방향 관계.
@Entity
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "teacher")
private List<Student> students = new ArrayList<>();
}
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "teacher_id")
private Teacher teacher;
}
Teacher 엔티티는 students 리스트를 통해 학생들을 참조하고, Student 엔티티는 teacher를 참조해서 양방향 연관관계가 설정돼.
양방향 관계에서 중요한 점:
• 양방향 관계를 유지하려면, 편의 메서드를 통해 두 엔티티 간의 관계를 동기화해줘야 해.
• 예를 들어, Student를 Teacher에 추가할 때, Teacher에서도 Student를 참조하도록 설정해야 데이터 일관성이 유지돼.
연관관계의 종류와 단방향/양방향 적용
1. 일대일(1:1)
• 단방향: 한쪽 엔티티에서만 다른 엔티티를 참조.
• 예시: 한 명의 사람이 하나의 여권을 가짐.
@Entity
public class Person {
@OneToOne
@JoinColumn(name = "passport_id")
private Passport passport;
}
• 양방향: 양쪽 엔티티가 서로를 참조.
@Entity
public class Passport {
@OneToOne(mappedBy = "passport")
private Person person;
}
2. 일대다(1:N)
• 단방향: 한쪽 엔티티에서 여러 엔티티를 참조.
• 예시: 한 명의 선생님이 여러 명의 학생을 가르침.
@Entity
public class Teacher {
@OneToMany
@JoinColumn(name = "teacher_id")
private List<Student> students;
}
• 양방향: 양쪽에서 서로 참조. (위 다대일 양방향 예시와 같음)
3. 다대일(N:1)
• 단방향: 다수의 엔티티가 하나의 엔티티를 참조. (위 단방향 다대일 예시와 같음)
• 양방향: 양쪽에서 서로 참조. (위 양방향 다대일 예시와 같음)
4. 다대다(N:M)
• 단방향: 양쪽 엔티티가 각각 서로를 참조.
• 예시: 학생이 여러 과목을 듣고, 과목도 여러 학생을 가짐.
@Entity
public class Student {
@ManyToMany
@JoinTable(name = "student_subject",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "subject_id"))
private List<Subject> subjects = new ArrayList<>();
}
@Entity
public class Subject {
@ManyToMany(mappedBy = "subjects")
private List<Student> students = new ArrayList<>();
}
결론
• 단방향: 한쪽 엔티티만 참조.
• 양방향: 양쪽 엔티티가 서로 참조.
• 양방향 관계에서 편의 메서드를 사용해 관계를 동기화해야 데이터 일관성을 유지할 수 있어.
JPA에서의 Cascade는 엔티티 간의 연관관계에서 부모 엔티티의 상태 변화(저장, 삭제 등)가 자식 엔티티에 자동으로 전파되도록 하는 설정이야. 즉, 부모 엔티티를 저장하거나 삭제할 때, 연관된 자식 엔티티도 자동으로 처리되도록 할 수 있어. 이는 데이터 일관성을 유지하고, 수동으로 각각의 엔티티를 처리해야 하는 번거로움을 줄여줘.
Cascade의 종류
1. CascadeType.PERSIST: 부모 엔티티를 저장할 때, 연관된 자식 엔티티도 자동으로 저장돼.
• 예: 부모 엔티티 Team을 저장하면, 연관된 Member 엔티티들도 함께 저장됨.
2. CascadeType.REMOVE: 부모 엔티티를 삭제할 때, 연관된 자식 엔티티도 자동으로 삭제돼.
• 예: Team을 삭제하면, 해당 Team에 속한 모든 Member도 삭제됨.
3. CascadeType.MERGE: 부모 엔티티가 병합(업데이트)될 때, 연관된 자식 엔티티도 자동으로 병합돼.
• 예: Team 엔티티를 병합할 때, 자식 Member 엔티티들도 자동으로 병합됨.
4. CascadeType.REFRESH: 부모 엔티티가 새로 고침될 때, 연관된 자식 엔티티도 함께 새로 고침돼.
• 예: Team 엔티티가 새로고침될 때, 연관된 Member들도 새로 고침됨.
5. CascadeType.DETACH: 부모 엔티티가 영속성 컨텍스트에서 분리될 때, 자식 엔티티도 함께 분리돼.
• 예: Team이 영속성 컨텍스트에서 분리되면, 연관된 Member들도 영속성 컨텍스트에서 분리됨.
6. CascadeType.ALL: 위의 모든 Cascade 옵션을 한 번에 적용하는 설정. 즉, PERSIST, REMOVE, MERGE, REFRESH, DETACH 모두가 적용돼.
예시 코드
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "team", cascade = CascadeType.ALL)
private List<Member> members = new ArrayList<>();
// 연관관계 편의 메서드
public void addMember(Member member) {
members.add(member);
member.setTeam(this);
}
}
위 코드에서, Team과 Member는 1:N 관계로, Team을 저장, 삭제, 병합할 때 모든 연관된 Member도 자동으로 처리돼.
Cascade의 장점
1. 코드 간소화: 연관된 엔티티들을 일일이 관리하지 않고, 한 번의 조작으로 자동으로 처리할 수 있어.
2. 일관성 유지: 부모 엔티티와 자식 엔티티 간의 상태를 항상 일관성 있게 유지할 수 있어.
주의할 점
Cascade 설정을 무분별하게 사용하면, 데이터 손실 등의 위험이 생길 수 있어. 특히 CascadeType.REMOVE처럼 부모 엔티티가 삭제될 때 자식 엔티티도 함께 삭제되기 때문에, 잘못된 설정으로 인한 데이터 손실에 주의해야 해.
정리하자면, Cascade는 연관된 엔티티들 간의 일관성을 유지하고, 코드를 간소화하기 위해 사용되지만, 상황에 맞게 올바르게 설정하는 것이 중요해.
'Database > JPA' 카테고리의 다른 글
JPA 고급 상속 매핑 전략: 단일 테이블, 조인 테이블, 테이블당 클래스 비교와 활용 (1) | 2024.09.13 |
---|---|
JPA 연관관계와 복합 키 (2) | 2024.09.13 |
객체 간 관계를 완벽히 이해하는 JPA 연관관계 매핑 (0) | 2024.09.11 |
JPA 기본 키 생성 전략: IDENTITY, SEQUENCE, TABLE과 allocationSize의 이해 (1) | 2024.09.10 |
QueryDSL로 JPA 쿼리 쉽게 작성하기 (3) | 2024.09.10 |