che01 님의 블로그
JPA 1:N 관계 완전 정리 본문
1:N 연관관계란?
한 엔티티가 여러 개의 다른 엔티티를 참조하는 관계입니다.
예시: 하나의 Team이 여러 명의 Player를 가지는 경우
- DB에서는 외래 키가 항상 N쪽(Player)에 위치
- 객체에서는 1쪽(Team)에서 List로 N쪽을 참조
1:N 단방향 관계
개념
- Team → List<Player> 로만 참조
- Player는 Team을 참조하지 않음
- 연관관계의 주인은 Team (1쪽)
코드 예시
@Entity
@Table(name = "team")
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "team_id") // 외래 키 직접 지정 필수
private List<Player> players = new ArrayList<>();
// 생성자, getter 등...
}
@Entity
@Table(name = "player")
public class Player {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// Team 참조 없음 (단방향)
}
사용 예시
// Player 생성 및 저장
Player player = new Player("messi");
em.persist(player);
// Team 생성 및 Player 추가
Team team = new Team("barcelona");
team.getPlayers().add(player); // List에 추가
em.persist(team);
문제점
1. 추가 UPDATE 쿼리 발생
-- 1. Team INSERT
INSERT INTO team (name) VALUES ('barcelona');
-- 2. Player는 이미 저장되어 있음
-- 3. 추가 UPDATE 쿼리 발생 (성능 문제)
UPDATE player SET team_id = 1 WHERE id = 1;
2. 객체와 테이블의 불일치
- Team 엔티티를 수정했는데 → Player 테이블이 수정됨
- 직관적이지 않고 혼란스러운 구조
3. @JoinColumn 필수 사용
@OneToMany
// @JoinColumn 생략 시 중간 테이블 생성됨 (원하지 않는 결과)
private List<Player> players = new ArrayList<>();
1:N 양방향 관계
개념
- Team → List<Player> 참조
- Player → Team 참조 (양방향)
- 연관관계의 주인은 여전히 Team (1쪽)
코드 예시
@Entity
@Table(name = "team")
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "team_id")
private List<Player> players = new ArrayList<>();
}
@Entity
@Table(name = "player")
public class Player {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// 읽기 전용 매핑 (수정 불가)
@ManyToOne
@JoinColumn(name = "team_id", insertable = false, updatable = false)
private Team team;
}
주의사항
1. Player 쪽은 읽기 전용
- insertable = false, updatable = false 설정 필수
- 양쪽에서 수정 가능하면 예측 불가능한 결과 발생
2. 여전히 비효율적
- 1:N 단방향과 동일한 문제점들이 그대로 존재
- 추가 UPDATE 쿼리, 객체-테이블 불일치 등
1:N 관계 정리
1:N 단방향 vs 1:N 양방향
구분 1:N 단방향 1:N 양방향
| 참조 방향 | Team → Player만 | Team ↔ Player |
| 연관관계 주인 | Team (1쪽) | Team (1쪽) |
| 성능 | 비효율적 | 비효율적 |
| 사용 권장도 | 권장하지 않음 | 권장하지 않음 |
결론
실무에서는 1:N 관계 대신 N:1 양방향을 사용하는 것을 강력히 권장
이유
- 성능: 추가 UPDATE 쿼리 없음
- 직관성: 외래 키가 있는 쪽에서 관계 관리
- 유지보수성: 예측 가능하고 명확한 구조
권장 방식
// N:1 양방향 (권장)
@Entity
public class Player {
@ManyToOne
@JoinColumn(name = "team_id")
private Team team; // 연관관계의 주인
}
@Entity
public class Team {
@OneToMany(mappedBy = "team")
private List<Player> players; // 읽기 전용
}
'Spring' 카테고리의 다른 글
| JPA N:M 관계 완전 정리 (0) | 2025.06.09 |
|---|---|
| JPA 1:1 관계 완전 정리 (0) | 2025.06.09 |
| Spring 데이터 변환 메커니즘 완벽 정리 (0) | 2025.06.06 |
| Spring Formatter란 ? (0) | 2025.06.06 |
| ConversionService란? (1) | 2025.06.05 |