-
[JPA] 연관관계기초/JPA 2022. 10. 8. 18:20
방향
DB테이블의 관계는 항상 양방향이다.
객체는 한 쪽만 참조할 수 있고, 양쪽 모두 참조할 수 있다.
양방향 관계
양쪽 객체가 단방향으로 서로를 참조할수 있는 관계다.
연관관계 주인 ( Owner )
객체가 양방향 관계가 되면 주인을 정해야 한다.
객체 그래프 탐색
관계가 형성된 객체는 참조를 통해 연관관계를 탐색할 수 있다.
School school = student1.getSchool();
객체 관계 매핑
ex) Studen (M) : School (1)의 관계
@Entity public class Student{ @Id private String id; @ManyToOne @JoinColumn(name="SCHOOL_ID") private School school; public void setSchool(School school) { this.school = school; } }
@Entity public class School{ @Id @Column(name = "SCHOOL_ID") private String id; }
Student > School (단방향)
이 때 School 엔티티가 Student를 바라보게 되면 양방향이 관계가 된다.
@Entity public class School{ @Id @Column(name = "SCHOOL_ID") private String id; //추가됨 @OneToMany(mappedBy = "student") private List<Student> students = new ArrayList<>(); }
- mappedBy 옵션 : 엔티티간의 관계에서 주인이 아닐 경우 사용
객체에서 양방향 연관관계는 없고, 오직 서로를 바라보는 단방향 관계만 존재한다.
테이블은 외래키 1개를 통해 두 사이의 관계를 맺지만, 객체는 양방향이 없으므로 주인을 설정으로 mappedBy 옵션을 사용한다.
ManyToOne어노테이션은 MappedBy 옵션이 없다. 따라서 항상 주인이 되고 OneToMany 옵션에서 mappedBy 옵션을 사용하면 된다.
이때 또 하나의 문제점이 있다.
엔티티의 관계는 정리가 끝났지만 객체간의 데이터의 무결성은 성립되지 않았다.
*테스트 서비스
public class Service{ public void saveSchoolAndStudent (String school, String student1, String student2) { School school1 = new School("school1"); Student student1 = new Student("student1"); Student student2 = new Student("student2"); student1.setSchool(school1); student2.setSchool(school1); List<Student> Students = school1.getStudents); // list empty } }
Student 객체에서 setSchool을 통해 Student 객체는 School 객체안에 값이 저장되지 않았다.
@Entity public class Student{ @Id private String id; @ManyToOne @JoinColumn(name="SCHOOL_ID") private School school; public void setSchool(School school) { //추가 기존 매핑된 관계가 있다면 제거해 주어야 한다. if(this.school != null) { this.school.getStudents().remove(this); } this.school = school; school.getStudents().add(this); //추가 getStudents().add 까지 리펙토링도 할수있다. } }
이렇게 코드를 작성하게 되면 객체 데이터간의 무결성도 성립된다.
*주의사항
연관관계의 주인을 정하는 기준은 외래키의 위치다.
비지니스 중요도로 접근하면 안된다.
양방향 관계시 그래프 참조가 무한루프에 빠지지않도록 주의한다.
JSON 라이브러리, Lombok 라이브러리를 사용할 때 자주 발생한다.
* JPA를 사용하여 모델링하게되면 데이터 중심의 설계보다는 객체 중심의 설게를 하게된다.
다대다 연관관계
다대다 관계에서 추가적인 컬럼이 필요한 경우가 대부분이다.
따라서 관계 자체의 테이블을 하나 만들어주어 두 관계에 부가적인 컬럼을 추가해주는 일대다대일 관계를 만들어준다.
Student(학생) M : Club(동아리)M 간의 관계가 정의될 때 부가적인 컬럼은 동아리 가입 시기, 동아리 가입 사유 등이 있을 수 있다.
Student (1) StudentClub (M) Club (1) - Student ID - Student ID
- Club ID
- createDate
- content- Club ID * 연결 테이블의 식별자
식별관계 : 받아온 식별자를 기본 키 + 외래 키 로 사용
@IdClass, @EmbeddedId 를 사용하여 구성하므로 복합키를 사용하게 된다.
비식별 관계 : 받아온 식별자는 외래키, 새로운 식별자를 추가 (추천)
'기초 > JPA' 카테고리의 다른 글
[JPA] 식별관계, 비식별 관계, 복합키 (0) 2022.10.11 [JPA] 객체간의 매핑 (0) 2022.10.11 [JPA] JPA 어노테이션 (0) 2022.10.08 [JPA] 영속성 컨텍스트 (2) 2022.10.08