@Inheritance
를 통한 상속 관계 매핑은 부모 클래스와 자식 클래스 모두 데이터베이스 테이블과 매핑했다. 그러나 부모 클래스는 테이블과 매핑하지 않고, 자식 클래스만 매핑하고 싶은 경우 @MappedSuperclass
를 사용하면 된다.
@MappedSuperclass
는 추상 클래스와 비슷하다. @Entity
는 실제 테이블과 매핑되지만 @MappedSuperclass
는 실제 테이블과 매핑되지 않는다. 따라서 여러 자식 클래스들이 공통으로 가지는 속성들을 묶어서 하나의 추상 클래스로 정의하고 @MappedSuperclass
어노테이션을 붙여준 뒤, 자식 클래스들이 해당 클래스를 상속하면 된다. 그 결과 부모 클래스는 데이터베이스 테이블과 매핑되지는 않지만, 자식 엔티티에게 공통으로 사용되는 매핑 정보를 제공할 수 있게 된다. 즉 테이블과 관계가 없고 단순히 자식 엔티티들이 공통으로 사용하는 매핑 정보들을 묶어주는 역할을 한다.
@MappedSuperclass
public abstract class BaseEntity { //@Entity 어노테이션을 붙이지 않는다.
@Id @GeneratedValue
private Long id;
private String name;
}
@Entity
public class Member extends BaseEntity {
//id, name 상속
private String email;
}
@Entity
public class Seller extends BaseEntity {
//id, name 상속
private String shopName;
}
BaseEntity에는 객체들이 주로 사용하는 공통 매핑 정보를 정의했다. 그리고 자식 엔티티들은 상속을 통해 BaseEntity의 매핑 정보를 물려받았다.
이때 BaseEntity는 테이블과 매핑할 필요가 없고 자식 엔티티에게 매핑 정보만 제공하면 된다. 따라서 @MappedSuperclass
를 사용했다.
@Entity
@AttributeOverride (name = "id", column = @Column(name = "member_id"))
public class Member extends BaseEntity {}
@Entity
@AttributeOverrides ({
@AttributeOverride (name = "id", column = @Column(name = "member_id")),
@AttributeOverride (name = "name", column = @Column(name = "member_name"))
})
public class Member extends BaseEntity {}
부모에게 상속받은 매핑 정보를 재정의하려면 @AttributeOverride
나 @AttributeOverrides
를 사용하면 된다.
부모에게 상속받은 컬럼의 컬럼명을 id에서 member_id로, name에서 member_name으로 재정의했다.
@MappedSuperclass
가 붙은 클래스는 테이블과 매핑되지 않고, 자식 클래스에 엔티티 매핑 정보를 상속하기 위한 클래스이다.
@MappedSuperclass
가 붙은 클래스는 엔티티가 아니므로 em.find()나 JPQL에서 사용할 수 없다.
이 클래스를 직접 생성해서 사용하는 일은 거의 없으므로 추상 클래스로 정의하는 것이 좋다.
참고
엔티티(@Entity)는 엔티티(@Entity)이거나 @MappedSuperclass로 지정된 클래스만 상속받을 수 있다.