JPA는 기본적인 엔티티 매핑 외에도 다양한 고급 매핑 기능을 지원하여 복잡한 객체-관계 매핑을 처리할 수 있도록 돕는다. 이 고급 매핑 기능을 통해 상속 관계, 복합 키, 식별 관계, 조인 테이블, 그리고 여러 테이블과의 매핑을 유연하게 설정할 수 있다.
1. 상속 관계 매핑
JPA는 객체 지향 언어의 상속을 관계형 데이터베이스와 매핑할 수 있는 기능을 제공한다. JPA에서는 상속 구조를 여러 가지 전략으로 데이터베이스에 매핑할 수 있다.
상속 매핑 전략
- 단일 테이블 전략(Single Table): 상위 클래스와 하위 클래스가 하나의 테이블에 모두 저장되는 방식이다.
- 조인 전략(Joined Table): 상위 클래스는 상위 클래스 테이블에, 하위 클래스는 하위 클래스 테이블에 저장하는 방식이다. 두 테이블은 조인을 통해 데이터를 조회한다.
- 구현 클래스마다 테이블 전략(Table per Concrete Class): 하위 클래스마다 별도의 테이블을 생성하는 방식이다.
예시: 조인 전략(Joined Table)
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 상속 매핑 전략 지정
@DiscriminatorColumn(name = "DTYPE") // 상위 테이블에 자식 구분 컬럼 생성
public abstract class Product {
@Id @GeneratedValue
private Long id;
private String name;
private int price;
}
@Entity
public class Book extends Product {
private String author;
private String isbn;
}
@Entity
public class Movie extends Product {
private String director;
private String actor;
}
- @Inheritance(strategy = InheritanceType.JOINED): 조인 전략을 통해 상속 매핑을 정의한다.
- @DiscriminatorColumn(name = "DTYPE"): 상위 테이블에 자식 타입을 구분하기 위한 컬럼을 생성한다. 이 컬럼을 통해 자식 엔티티가 무엇인지 구분할 수 있다.
2. @MappedSuperclass
- @MappedSuperclass는 공통 필드를 여러 엔티티에서 공유할 때 사용한다. 실제 테이블과 매핑되지 않으며, 상속받는 클래스에 매핑 정보를 전달하는 용도로 사용된다.
예시: 공통 필드 정의
@MappedSuperclass
public abstract class BaseEntity {
@Id @GeneratedValue
private Long id;
private String createdBy;
private LocalDateTime createdDate;
}
@Entity
public class Member extends BaseEntity {
private String name;
// BaseEntity로부터 id, createdBy, createdDate 상속
}
@Entity
public class Product extends BaseEntity {
private String name;
// BaseEntity로부터 id, createdBy, createdDate 상속
}
- @MappedSuperclass는 실제 엔티티는 아니지만, 다른 엔티티가 공통으로 사용하는 필드를 정의할 수 있다.
- 이 예시에서는 BaseEntity가 id, createdBy, createdDate와 같은 공통 필드를 가지고 있으며, 이를 상속받는 Member와 Product 엔티티는 이러한 공통 필드를 자동으로 가진다.
- 실제 테이블에 매핑되지 않으며, 직접 조회할 수 없는 슈퍼클래스이다.
3. 복합 키와 식별 관계 매핑
복합 키는 두 개 이상의 컬럼을 조합하여 기본 키를 구성하는 경우 사용한다. JPA에서 복합 키를 매핑할 때는 @IdClass 또는 @EmbeddedId를 사용하여 구현할 수 있다. 복합 키는 특히 식별 관계에서 자주 사용된다.
복합 키 매핑 방법
- @IdClass: 별도의 식별자 클래스를 만들어 사용한다.
- @EmbeddedId: 임베디드 타입을 사용하여 복합 키를 매핑한다.
예시: @IdClass를 사용한 복합 키 매핑
@Entity
@IdClass(OrderItemId.class) // 복합 키 클래스
public class OrderItem {
@Id
private Long orderId;
@Id
private Long itemId;
private int quantity;
}
public class OrderItemId implements Serializable {
private Long orderId;
private Long itemId;
// equals, hashCode 구현
}
- @IdClass(OrderItemId.class): 복합 키 클래스로 OrderItemId를 지정한다. 이 클래스는 Serializable 인터페이스를 구현해야 하며, equals()와 hashCode() 메서드를 재정의해야 한다.
- OrderItemId 클래스는 주 엔티티의 키를 구성하는 필드들과 동일한 필드를 가진다.
@EmbeddedId를 사용한 복합 키 매핑
@Embeddable
public class OrderItemId implements Serializable {
private Long orderId;
private Long itemId;
// equals, hashCode 구현
}
@Entity
public class OrderItem {
@EmbeddedId
private OrderItemId id; // 복합 키
private int quantity;
}
- @Embeddable: 임베디드 타입으로 사용될 수 있도록 정의된 복합 키 클래스이다.
- @EmbeddedId: OrderItem 엔티티의 복합 키로 OrderItemId를 지정한다. 임베디드 타입으로 복합 키를 지정할 때 사용된다.
4. 조인 테이블
조인 테이블은 두 엔티티 간의 관계를 관리하기 위해 중간 테이블을 사용하는 방식이다. 이는 주로 다대다 관계나 복잡한 관계에서 사용된다. 조인 테이블을 통해 두 엔티티를 간접적으로 연결하며, 추가적인 컬럼을 조인 테이블에 포함할 수도 있다.
예시: 학생과 강의의 다대다 관계에서 조인 테이블 사용
@Entity
public class Student {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToMany
@JoinTable(name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id"))
private List<Course> courses = new ArrayList<>();
}
@Entity
public class Course {
@Id @GeneratedValue
private Long id;
private String name;
@ManyToMany(mappedBy = "courses")
private List<Student> students = new ArrayList<>();
}
- @JoinTable: 조인 테이블을 생성하는 어노테이션이다. 여기서 student_course라는 조인 테이블을 생성하고, 두 엔티티 간의 관계를 연결한다.
- joinColumns: 현재 엔티티(Student)의 외래 키이다.
- inverseJoinColumns: 반대쪽 엔티티(Course)의 외래 키이다.
조인 테이블의 특징
- 양방향 매핑에서 조인 테이블은 관계를 관리하기 위해 사용된다.
- 중간 테이블을 통해 연결만 관리할 수도 있으며, 추가적인 정보를 저장할 수도 있다.
5. 엔티티 하나에 여러 테이블 매핑
JPA는 하나의 엔티티를 여러 개의 테이블에 매핑할 수 있는 기능을 제공한다. 이를 통해 엔티티의 데이터가 여러 테이블에 분산되어 있을 경우에도 JPA를 통해 편리하게 관리할 수 있다.
@SecondaryTable 사용 예시
@Entity
@Table(name = "member")
@SecondaryTable(name = "member_detail", pkJoinColumns = @PrimaryKeyJoinColumn(name = "member_id"))
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
@Column(table = "member_detail") // member_detail 테이블에 매핑
private String address;
@Column(table = "member_detail") // member_detail 테이블에 매핑
private String phone;
}
- @SecondaryTable: 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용한다.
- name: 보조 테이블의 이름을 지정한다.
- pkJoinColumns: 주 테이블과 보조 테이블 간의 연결 조건을 지정한다.
- @Column(table = "member_detail"): 특정 필드를 보조 테이블의 컬럼에 매핑할 수 있다.
특징
- 하나의 엔티티가 여러 테이블을 사용할 때, @SecondaryTable을 통해 보조 테이블을 추가할 수 있다.
- 이 방법을 통해 엔티티에 대한 데이터를 분산된 테이블로부터 조회하거나, 보조 테이블에 있는 데이터만 업데이트할 수도 있다.
JPA의 고급 매핑 기능을 통해 더욱 유연하고 다양한 엔티티 관계를 설정할 수 있다.
- 상속 관계 매핑: 객체 지향 상속 구조를 데이터베이스 테이블에 매핑할 수 있으며, 단일 테이블, 조인 테이블, 구현 클래스마다 테이블 등의 전략을 선택할 수 있다.
- @MappedSuperclass: 실제 테이블로 매핑되지 않으면서 공통 속성을 여러 엔티티에서 공유할 때 사용한다.
- 복합 키와 식별 관계 매핑: 두 개 이상의 필드를 합쳐서 기본 키로 사용하는 경우, @IdClass와 @EmbeddedId를 사용하여 복합 키를 설정할 수 있다.
- 조인 테이블: 두 엔티티 간의 관계를 관리하기 위한 중간 테이블을 생성하며, 다대다 관계에서 주로 사용된다.
- 엔티티 하나에 여러 테이블 매핑: 하나의 엔티티를 여러 테이블에 매핑할 때 @SecondaryTable을 사용하여 보조 테이블을 추가로 설정할 수 있다.
728x90
'Backend study > JPA' 카테고리의 다른 글
값 타입 (0) | 2024.11.01 |
---|---|
프록시와 연관관계 관리 (0) | 2024.10.30 |
다양한 연관관계 매핑 (0) | 2024.10.25 |
연관관계 매핑 기초 (1) | 2024.10.22 |
엔티티 매핑(Entity Mapping) (1) | 2024.10.21 |