@MappedSupperclass
@MappedSupperclass는 상속 관계 매핑에서 사용되는 어노테이션이다.
@MappedSuperclass
public abstract class Timestamped {
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
...
}
@Entity
public class Member extends BaseEntity {
...
}
해당 어노테이션에 선언된 클래스는 테이블과 매핑되지 않으며, 자식 클래스에게 매핑 정보만 제공한다.
이를 통해 자식 클래스는 부모 클래스의 필드를 상속받아 사용할 수 있다.
→ 중복 코드를 줄이고 객체 지향적인 설계를 할 수 있다.
@Embedded & @Embeddable
기본 값 타입을 모아서 새로운 값 타입을 직접 정의할 수 있으며, JPA에서는 임베디드 타입(embedded type)이라고 한다.
@Embedded와 @Embeddable은 값 타입 매핑에서 사용되는 어노테이션이다.
@Embeddable
public class Timestamped {
private LocalDateTime createdDate;
private LocalDateTime modifiedDate;
...
}
@Entity
public class Member {
@Embedded
private Timestamped timestamped;
...
}
@Embeddable는 값 타입 클래스로 매핑 정보를 제공하는 어노테이션으로, 여러 엔티티에 공유하여 사용할 수 있다.
@Embedded은 값 타입 객체를 엔티티에 매핑할 때 사용하는 어노테이션이다.
→ 객체의 책임에 대한 응집도를 높일 수 있으며, 높은 재사용성을 가진다.
@MappedSuperclass vs @Embedded
두 애노테이션 모두 엔티티의 비슷한 속성을 분리하여 효과적으로 관리할 수 있는 공통점이 있다.
이 둘이 가장 큰 차이점은 바로 @MappedSupperclass는 상속을 사용하는 것과 @Embedded는 위임을 사용하는 것이다.
객체지향의 일반적인 법칙에 따르면 보다 유연한 객체를 다루기 위해 부모 클래스와 의존성이 강하게 엮인 상속 보단 위임을 사용하는 것을 추천한다.
💡 상속, 무엇이 문제인가?결론부터 먼저 말하자면 상속은 캡슐화를 깨트리게 되며, 상위 클래스에 의존적이어서 결합도가 높아진다.
상위 클래스의 구현이 하위 클래스에게 노출되기 때문에 자바의 원칙 중 하나인 캡슐화가 깨지게 된다.
또한, 상위 클래스와 하위 클래스의 관계가 컴파일 시점에 결정되어 구현에 의존하기 때문에 실행시점에 객체의 종류를 변경하는 것이 불가능하며 다형성과 같은 객체지향의 이점을 활용할 수 없다.
정리하자면, 하위 클래스가 상위 클래스에 강하게 의존 및 결합이 되는 설계가 되는 것이다.
- 이펙티브 자바 -
하지만 몇 가지 경우에서는 상속을 사용하는 것이 더 편할 때가 있다.
1. 수정/등록 시간, 수정/등록자 처럼 대부분의 엔티티가 공통으로 사용하는 속성일 경우
2. 편리함과 직관성을 위해
- 임베디드 타입을 사용했을 때 JPQL
select m from Member m where m.Timestamped.createdDate > ?
이같은 경우 m.Timestamped.createdDate와 같이 임베디드 타입을 명시해주어야 한다.
- 상속을 사용했을 때 JPQL
select m from Member m where m.createdDate > ?
Reference
https://velog.io/@rudwnd33/JPA-MappedSuperclass-vs-Embedded-Type
'Framework > JPA' 카테고리의 다른 글
[JPA] 페이징 처리 성능 최적화하기 (1) | 2024.02.11 |
---|---|
[QueryDSL] DTO로 조회하기 (0) | 2023.10.15 |
[JPA] 다대일 매핑에서 @JoinColumn의 역할 (0) | 2023.10.05 |
[JPA] 순한 참조 문제 해결하기 (0) | 2023.10.01 |