Database & ORM/JPA 프로젝트

5. JPA 상속 관계 매핑, Enum 사용

MJ.Lee 2022. 3. 11. 09:06

도메인 모델과 테이블

Entity에선 Item을 Album, Book, Movie가 상속받는다.

상속 전략으로 하나의 테이블 전략을 사용하여 Album, Book, Movie 정보 모두 Item 테이블에 저장된다. DTYPE으로 Album, Book, Movie를 구분한다.

참고로, 상속 전략에는 아래와 같이 조인 전략도 있다. 조인 전략은 저장 공간을 효율적으로 사용하지만, 조회할 때 조인을 많이 사용하므로 하나의 테이블 전략보단 속도가 느리다.

추천하지 않지만, 아래와 같이 클래스마다 테이블 전략도 있다.

Domain

부모 Entity

@Inheritance

  • 부모 엔터티에 선언한다.
  • strategy로 상속 전략을 선택한다.
    • SINGLE_TABLE: 단일 테이블 전략
    • JOINED: 조인 전략
    • TABLE_PER_CLASS: 클래스마다 테이블 전략

@DiscriminatorColumn

  • 구분 컬럼 지정
  • 부모 클래스가 매핑된 테이블에서 자식을 구분하기 위해 사용한다.
  • name 속성은 DTYPE이 기본 값으로 지정되어 있다.

자식 Entity

부모 클래스인 Item을 상속받아 구현했다.

@DiscriminatorValue

  • 엔티티를 저장할 때, 부모 클래스를 매핑한 테이블의 구분 컬럼에 들어갈 값을 지정
  • Album은 A, Book은 B, Movie는 M으로 정했다. Item 테이블의 DTYPE에 저장된다.

super로 부모 클래스인 Item 생성자를 호출하여, Item 필드의 값을 초기화한다.

DTO

DTO

화면 단에서 Item의 값을 받아올 수 있도록, Album, Book, Movie의 모든 필드를 포함한 DTO를 만들었다.

ItemDTO에서 Album, Book, Movie Entity를 만들 수 있도록 함수를 만들고, enum을 사용했다.

Enum

Item의 Type을 A, B, M 값으로 구분하되, 보기 쉽게 enum을 만들었다.

public enum ItemType {

    ALBUM("A"),
    BOOK("B"),
    MOVIE("M");

    private final String itemTypeKey;

    ItemType(String itemTypeKey) {
        this.itemTypeKey = itemTypeKey;
    }

//String인 Item Type Key를 넣으면 ItemType으로 변환해준다.
//예를 들어 "A"를 넣으면 ItemType인 ALBUM으로 바꿔준다.
    public static ItemType fromString(String itemTypeKey) {
        for (ItemType i : ItemType.values()) {
            if (i.itemTypeKey.equalsIgnoreCase(itemTypeKey)) {
                return i;
            }
        }
        return  null;
    }
}

View

상품 종류를 선택하면, 종류에 따라 폼이 달라지게 만들었다.

var itemMain = {
    init : function () {

        var _this = this;
        $("#itemType").on("change", function(){
                _this.itemTypeChange();
        });

        _this.itemTypeChange();
    },

    itemTypeChange : function(){
        var itemType = $("#itemType option:selected").val();

       switch(itemType){
            case 'A':
                $("#div-album").css("display", "block");
                $("#div-book").css("display", "none");
                $("#div-movie").css("display", "none");
                break;

            case 'B':
                $("#div-album").css("display", "none");
                $("#div-book").css("display", "block");
                $("#div-movie").css("display", "none");
                break;

            case 'M':
                $("#div-album").css("display", "none");
                $("#div-book").css("display", "none");
                $("#div-movie").css("display", "block");
                break;
       }
    }

}

itemMain.init();

Controller

VIEW에서 ItemDTO에 Item 정보를 받아 Service에 넘겨준다.

Service

서비스에서 ItemDTO를 Entity로 변경하여 Repository에 넘겨준다.

Repository

Item을 등록한다.

Select할 때, Item.class로 설정해줘도 DTYPE에 따라 Album, Book, Movie 클래스에 데이터를 담아서 반환해준다.

Database

DB를 확인해보면 아래와 같이 하나의 테이블에 DTYPE으로 Item Type이 구분되어 들어간 것을 확인할 수 있다.