반응형
JPA에서 엔티티 간의 관계를 설정할 때 가장 중요한 개념 중 하나는
양방향 연관관계와 연관관계의 주인(Owner) 입니다.
이는 데이터베이스 외래키(FK)를 누가 관리할지 결정하는 핵심 요소이므로 반드시 명확히 이해해야 합니다.
🤔 연관관계의 주인이란?
양방향 관계에서는 두 엔티티가 서로를 참조하지만,
데이터베이스의 외래키는 단 한 곳에만 존재합니다.
따라서 JPA는 어떤 엔티티가 FK를 관리(등록·수정·삭제)할지 알아야 합니다.
이 역할을 맡는 엔티티가 바로 연관관계의 주인(Owner) 입니다.
- 1:N 관계에서
- ➡️ N(다) 쪽이 보통 외래키를 가지므로 주인이 됩니다.
- ➡️ 1(일)은 mappedBy를 사용하여 자신이 주인이 아님을 명시해야 합니다.
👉 즉, 1:N 관계에서는 항상 N 쪽이 주인이 됩니다.
🤔 양방향 연관관계 예시
예를 들어 Team과 Member 엔티티가 있다고 해봅시다.
- Member → Team: 한 명의 멤버는 하나의 팀에 소속됩니다. (@ManyToOne)
- Team → Member: 한 팀에는 여러 명의 멤버가 소속됩니다. (@OneToMany)
즉, 두 엔티티는 서로를 참조할 수 있으므로 양방향 연관관계입니다.
Member.java (연관관계의 주인)
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id") // 외래키
private Team team;
// Getter, Setter
}
Team.java (연관관계의 주인이 아님)
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team") // 주인이 아님을 명시
private List<Member> members = new ArrayList<>();
// Getter, Setter
}
🚨 주인을 잘못 지정했을 때 발생하는 문제
만약 Team을 연관관계의 주인으로 설정하면 어떻게 될까요?
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "team_id") // ❌ 잘못된 주인 설정
private List<Member> members = new ArrayList<>();
}
실제 외래키(team_id)는 MEMBER 테이블에 존재합니다.
그런데 Team을 주인으로 설정하면 JPA는 MEMBER.team_id를 제대로 업데이트하지 못합니다.
📌 예시: Member의 소속 팀 변경
아래 코드를 통해 Member의 소속 팀을 변경해보겠습니다.
// 새로운 팀 생성
Team teamA = new Team("Team A");
Team teamB = new Team("Team B");
em.persist(teamA);
em.persist(teamB);
// 멤버 생성 및 Team A에 소속
Member member = new Member("member1");
member.setTeam(teamA);
em.persist(member);
// 이후 member의 소속을 Team B로 변경
member.setTeam(teamB);
- ✅ 올바르게 주인을 설정한 경우:
- member.setTeam(teamB) 호출 시 JPA가 MEMBER.team_id 값을 Team B의 ID로 업데이트합니다. - ❌ Team을 주인으로 잘못 설정한 경우:
- member.setTeam(teamB)를 호출해도 MEMBER.team_id 컬럼은 업데이트되지 않습니다.
- DB 상에서는 여전히 member1은 Team A에 소속된 상태로 남아 있게 됩니다.
- 주인이 아닌 쪽(mappedBy)은 읽기 전용 뷰이기 때문에 쓰기(UPDATE) 대상으로 취급하지 않습니다.
✔ 정리
- 양방향 연관관계에서는 반드시 외래키가 있는 엔티티를 연관관계의 주인으로 설정해야 합니다.
- mappedBy는 반대쪽 엔티티에서 "나는 주인이 아니다"라고 선언하는 역할을 합니다.
- 주인을 잘못 지정하면 DB의 FK가 업데이트되지 않아 데이터 불일치 문제가 발생할 수 있습니다.
반응형
'Back end > Spring Project' 카테고리의 다른 글
| [Spring] JPA - 프록시(Proxy) (0) | 2025.08.29 |
|---|---|
| [Spring] JPA - @MappedSuperclass (0) | 2025.08.27 |
| [Spring] JPA 준영속 상태(Detached) (0) | 2025.08.15 |
| [Spring] JPA flush (0) | 2025.08.14 |
| [Spring] JPA 기본 CRUD 동작 예제 (0) | 2025.08.13 |