T_era
연관관계 매핑 본문
객체지향 모델과 관계형 데이터베이스 모델 간의 불일치를 해결하고, 데이터베이스 테이블 간의 관계를 객체 간의 관계로 표현하는 데 사용된다.
연관관계 매핑의 종류
- 일대일(One-to-One): 하나의 엔티티가 다른 엔티티 하나와 연관되는 관계다. @OneToOne 어노테이션을 사용하여 매핑한다. 주 테이블에 외래 키를 두거나, 대상 테이블에 외래 키를 두는 방식이 있다.
- 일대다(One-to-Many): 하나의 엔티티가 여러 개의 다른 엔티티와 연관되는 관계다. @OneToMany 어노테이션을 사용하며, 일반적으로 대상 테이블에 외래 키를 가진다. 컬렉션(List, Set 등)을 사용하여 연관된 엔티티들을 관리한다.
- 다대일(Many-to-One): 여러 개의 엔티티가 하나의 다른 엔티티와 연관되는 관계다. @ManyToOne 어노테이션을 사용하며, 현재 테이블에 외래 키를 가진다.
- 다대다(Many-to-Many): 여러 개의 엔티티가 여러 개의 다른 엔티티와 연관되는 관계다. @ManyToMany 어노테이션을 사용하며, 일반적으로 중간 테이블을 사용하여 관계를 표현한다.
연관관계 매핑 시 고려사항
- 방향성: 단방향 연관관계와 양방향 연관관계가 있다. 단방향은 한쪽 엔티티에서만 다른 엔티티로의 참조를 가지는 것이고, 양방향은 양쪽 엔티티 모두 서로를 참조하는 것이다. 양방향 연관관계는 @OneToMany, @ManyToMany에서 mappedBy 속성을 사용하여 주인이 아닌 쪽을 명시해야 한다.
- 연관관계의 주인: 양방향 연관관계에서 데이터베이스에 외래 키를 관리하는 쪽을 연관관계의 주인이라고 한다. 주인만이 데이터베이스 연관관계를 변경할 수 있다. @JoinColumn 어노테이션을 사용하여 외래 키를 매핑한다.
- 고아 객체 제거: 부모 엔티티와의 연관관계가 끊어진 자식 엔티티를 자동으로 삭제하고 싶을 경우 @OneToMany, @OneToOne 어노테이션의 orphanRemoval = true 옵션을 사용할 수 있다.
- 지연 로딩과 즉시 로딩: 연관된 엔티티를 언제 로딩할 것인지 결정하는 전략이다. @ManyToOne, @OneToOne은 기본이 즉시 로딩(EAGER)이고, @OneToMany, @ManyToMany는 기본이 지연 로딩(LAZY)이다. 필요에 따라 @Fetch 어노테이션 등을 사용하여 로딩 전략을 변경할 수 있다.
매핑 예시 (다대일 단방향)
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
// ... (getter, setter 등)
}
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
// ... (getter, setter 등)
}
위 예시는 Member 엔티티가 Team 엔티티와 다대일 단방향 연관관계를 맺는 것을 보여준다. Member 테이블에는 team_id라는 외래 키가 존재하여 Team 테이블의 기본 키를 참조한다.
매핑 예시 (다대일 양방향)
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
// 연관관계 편의 메소드 (선택 사항)
public void setTeam(Team team) {
if (this.team != null) {
this.team.getMembers().remove(this);
}
this.team = team;
if (team != null) {
team.getMembers().add(this);
}
}
// ... (getter, setter 등)
}
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
// ... (getter, setter 등)
}
설명:
- Member 엔티티: @ManyToOne 어노테이션과 @JoinColumn(name = "team_id")를 사용하여 Team 엔티티와의 다대일 관계를 설정한다. 이는 이전 단방향 예시와 동일하다. team_id 외래 키가 Member 테이블에 생성된다.
- Team 엔티티: @OneToMany(mappedBy = "team") 어노테이션을 사용하여 Member 엔티티와의 일대다 관계를 설정한다.
- mappedBy = "team": 이 속성은 양방향 연관관계에서 주인이 아닌 쪽을 명시한다. "team"은 Member 엔티티의 @ManyToOne으로 매핑된 필드 이름이다. 즉, Member 엔티티의 team 필드가 이 연관관계의 주인이 되어 데이터베이스의 외래 키를 관리한다.
- List<Member> members = new ArrayList<>();: Team 엔티티는 해당 팀에 소속된 Member 엔티티들의 목록을 members 필드를 통해 관리한다.
- 연관관계 편의 메소드 (setTeam in Member): 양방향 연관관계 시 객체 그래프의 일관성을 유지하기 위해 편의 메소드를 작성하는 것이 좋다. 이 메소드는 Member의 team을 설정함과 동시에 Team의 members 컬렉션에도 해당 Member를 추가하거나 제거하는 로직을 포함한다. 이렇게 하면 개발자가 실수로 한쪽의 연관관계만 설정하는 상황을 방지할 수 있다.
연관관계 매핑은 JPA에서 데이터베이스와 객체 간의 관계를 효과적으로 관리하는 데 중요한 개념이다. 각 연관관계의 특징과 매핑 방법을 정확히 이해하고 사용하는 것이 중요하다.
'Programing > Spring' 카테고리의 다른 글
| Spring Data JPA Query Methods 및 JPA Auditing 정리 (0) | 2025.05.16 |
|---|---|
| JPA vs Spring Data JPA (0) | 2025.05.16 |
| JPA 기본 키(Primary Key) 매핑 (0) | 2025.05.15 |
| JPA 필드 매핑 상세 정리 (0) | 2025.05.15 |
| JPA @Entity와 @Table 어노테이션 정리 (0) | 2025.05.15 |