일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- spring
- tomcat
- 디자인패턴 #싱글톤
- 외장톰캣
- Spring Framework
- autocomplete
- 톰캣
- LiveTemplate
- Mockito #Reflection #Sigleton #Test #JUnit
- Today
- Total
자라선
[자바 ORM 표쥰 JPA 프로그래밍] 13일차 - 엔티티 상속 본문
객체는 extends 예약어를 사용하여 객체간 상속을 사용해 재사용성을 올리거나 다양한 참조가 가능해진다.
상속은 객체지향언어의 장점인데. 문제는 관계형 데이터베이스는 이러한 상속이 불가능하다는 것이다.
아니 정확히 말하자면 아예 테이블간의 상속이라는 개념이 없다보니 패러다임의 불일치가 발생한 것
Item 객체를 Album과 Movie 객체가 상속받고 있다.
이러한 상태의 객체를 테이블과 매핑하려고 한다면 조인전략을 선택해야한다.
1. Join 전략
상위 엔티티와 하위 엔티티를 조인하도록 하여 사용하는 방식이 Join 전략이다.
@Entity
@Inheritance(strategy = InheritanceType.JOINED) // 전략 선택 JOIN
@DiscriminatorColumn(name = "DTYPE") // 구분자 컬럼을 DTYPE 이라 명시
public abstract class Item {
@Id
@GeneratedValue
@Column(name = "ITEM_ID")
private long id;
@Column(name = "ITEM_NAME")
private String name;
@Column(name = "PRICE")
private int price;
}
@Entity
@DiscriminatorValue("A") // 구분자 값을 A 라고 명시
public class Album extends Item{
private String artist;
}
@Entity
@DiscriminatorValue("M") // 구분자 값을 M 이라 명시
class Movie extends Item{
private String director;
}
상위 엔티티인 Item 엔티티에 @Inheritance 라는 어노테이션을 정의하여 속성값에 InheritanceType.JOINED 라고 해놓는다.
그러면 이러한 상속 엔티티끼리는 조인전략으로 사용하겠다고 알리게 되고
@DiscrimiatorColum 은 Item 엔티티에 구분자 컬럼을 추가하고 컬럼명을 명시하는 것이다.
DTYPE 이라는 컬럼명으로 테이블에서는 구분자로 사용될 것이다.
그리고 상속받은 Album과 Movie 엔티티는 @DiscriminatorValue를 각각 구분자 를 'A', 'M' 으로 하여 해당 값으로 저장시 DTYPE에 구분자 값으로 저장되도록 해준다.
Album album = new Album();
album.setArtist("아티스트");
album.setName("이름");
album.setPrice(1000);
em.persist(album);
Movie movie = new Movie();
movie.setName("무비이름");
movie.setDirector("디렉터");
movie.setPrice(9000);
em.persist(movie);
직관적이며 간편하며 외래키 참조 무결성 제약조건을 활용할수 있으나
INSERT 시 SQL를 2번 실행하거나 조회 또한 조인을 통해 실행되기 때문에
성능적인 면에서는 저하가 발생할 수도 있다.
2. SINGLE TABLE 전략
조인 전략이 상위 엔티티를 생성하여 상속받는 엔티티끼리의 조인을 통해 사용된다면
단일 테이블 전략은 하나의 테이블에 모든 컬럼을 몰아넣어 사용하는 방식이다.
@Data
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) // 전략 선택 SINGLE_TABLE
@DiscriminatorColumn(name = "DTYPE") // 구분자 컬럼을 DTYPE 이라 명시
public abstract class Item {
....
JOIN 테이블에서 InheritanceType의 값만 SINGLE_TABLE 로 변경만 해주면 된다.
JOIN에 비해 테이블 생성 수가 줄어들어 관리에 있어서 편하며
JOIN을 하지 않기 때문에 상대적으로 성능에 있어서 좋다.
하지만 상속받는 컬럼이 들어나면 늘어날수록 상위 테이블의 컬럼수가 늘어나 성능 저하와 관리가 힘들어질수 있다.
3. @MappedSuperclass
객체의 상속이 공통된 필드나 메소드들을 재사용할 수 있는 장점을 갖고 있는데
DB의 테이블은 그러한 방법이 없다. 그렇기 때문에 JPA는 공통화된 컬럼을 한꺼번에 관리해주기 위해
@MappedSuperclass 라는 기능을 제공해주고 있다.
@Data
@MappedSuperclass // 이 객체는 다른 엔티티에서 공용으로 사용될 컬럼을 작성
public abstract class BaseEntity {
@Id
@Column(name = "ID")
private long id;
@Column(name = "CREATE_DT")
@Temporal(TemporalType.DATE)
private Date createDt;
}
@Data
@Entity
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = "MEMBER_ID")),
@AttributeOverride(name = "createDt", column = @Column(name = "MEMBER_JOIN"))
}) // 부모 객체의 컬럼을 수정하여 적용할 수 있다.
public class Member extends BaseEntity{
@Column(name = "EMAIL")
private String email;
}
@Data
@Entity
public class Seller extends BaseEntity{
@Column(name = "SHOP_NAME")
private String shopName;
}
BaseEntity 객체에서는 이 객체를 상속받은 엔티티는 공용으로 사용할 필드를 작성해준다.
예를 들어 id(PK) 나 createDt 와 같은 웬만해서는 공통적으로 들어가는 필드는 위 코드와 같이 작성해준다.
당연한 말이지만 BaseEntity 는 공용으로 사용되기 위한 용도라 테이블이 생성되지 않는다.
추가로 @AttributeOverrides 를 사용해 상위 객체의 컬럼을 수정하여 적용 할수도 있다.
'Develop > JPA' 카테고리의 다른 글
[자바 ORM 표쥰 JPA 프로그래밍] 14일차 - 복합키 매핑과 1:1 매핑 (0) | 2021.08.30 |
---|---|
[자바 ORM 표쥰 JPA 프로그래밍] 14일차 - 복합키 엔티티 (0) | 2021.08.27 |
[자바 ORM 표쥰 JPA 프로그래밍] 12일차 - 엔티티 매핑 (0) | 2021.08.26 |
[자바 ORM 표쥰 JPA 프로그래밍] 11일차 - 엔티티 및 테이블 연관관계 (0) | 2021.08.24 |
[자바 ORM 표쥰 JPA 프로그래밍] 10일차 - 객체와 DB의 불일치성 (0) | 2021.08.19 |