테이블과 객체 사이에는 많은 패러다임 불일치가 있다고 앞선 챕터에서 설명했습니다. 그 중 가장 간극이 크다고 여겨지는 불일치중 하나는 연관관계의 참조에 대한 불일치 문제입니다.
JPA가 이런 연관관계 참조 불일치 문제를 어떤 방식으로 해결하는지 살펴보겠습니다.
이번 챕터에서는 객체 연관관계 매핑의 기초적이고 개념적인 부분을 체크합니다. 실제 프로덕트에 개발을 고려하고있다면, [다음 글 링크] 를 확인하세요!
JPA의 연관관계 매핑을 공부하기 전, 알아야할 내용!
RDBMS의 외래 키
RDBMS에서는 외래 키는 다른 테이블의 Primary Key를 참조하는 컬럼을 말합니다. 여기에 RDBMS에서 제공하는 외래 키 제약조건(Foreign Key Constraint) DDL을 선언해주면 , 참조 무결성을 보장합니다.
참조 무결성은 보통 삭제동작에서 검증하며, 부모 레코드가 삭제되어 고아 레코드가 되는것을 방지하고,
먼저 팀과 멤버가 갖는 객체, 테이블 각각에서의 연관관계를 확인하며 연관관계가 갖는 특성을 살펴보겠습니다.
객체에서의 연관관계
테이블에서의 연관관계
객체와 테이블 연관관계의 가장 큰 차이점: 객체는 [member → team], [team → member] 로 참조를 두 개 만들어도, 양방향 관계가 아니다!
Member와 Team엔티티가 연관관계를 맺는 예시입니다. 아래에서는 해당 엔티티를 통해 연관관계 매핑을 설명합니다.
Member 엔티티
@Entity
public class Member{
@Id
@Column(name="MEMBER_ID")
private String id;
@ManyToOne
@JoinColumn(name="TEAM_ID")
private Team team;
private String username;
}
Team엔티티
@Entity
public class Team{
@Id
@Column(name="TEAM_ID")
private String id;
private String name;
}
엔티티를 저장할 때는, 연관관계 엔티티를 저장하려 하는 경우, 연관 엔티티 역시 영속상태여야 한다.
이것을 보고 궁금해서 직접 실험해봤는데, 영속하지 않은 상태에서 setTeam한 후, 영속시켜도 정상적으로 동작하는것을 확인했다. 내부적으로 어떤 차이가 있는지는 확인이 필요하다.
연관 엔티티 수정은 특별한 방법 없이 엔티티를 수정하면 플러시 시점에 변경감지가 작동한다.
연관 엔티티를 제거할 때는, 연관관계의 주인이 먼저 삭제될 수 없다(외래 키 제약조건) 이 경우, 데이터베이스에서 참조 무결성 오류가 발생한다.
따라서, 외래키를 가지고있는 부모 엔티티의 연관관계를 삭제하거나, 자식 엔티티를 삭제해 연관관계를 지운 후 부모 엔티티를 삭제할 수 있다.