본문 바로가기

JPA/상속관계 매핑

상속관계 매핑 코드 실습

github 전체코드(branch: InheritanceMapping)

2021.08.16 - [JPA/상속관계 매핑] - 슈퍼타입 서브타입 논리 모델 구현 전략

 

슈퍼타입 서브타입 논리 모델 구현 전략

객체의 상속과 DB의 슈퍼타입 서브타입 객체에는 상속이라는 개념이 존재한다. 하지만 관계형 DB에는 상속이라는 개념이 존재하지 않는다. 대신 슈퍼타입, 서브타입 관계라는 상속과는 다르지만

code-mania.tistory.com

2021.08.18 - [JPA/상속관계 매핑] - 상속관계 매핑

 

상속관계 매핑

슈퍼타입 서브타입 논리 모델 구현 전략 슈퍼타입 서브타입 논리 모델 구현 전략 객체의 상속과 DB의 슈퍼타입 서브타입 객체에는 상속이라는 개념이 존재한다. 하지만 관계형 DB에는 상속이라

code-mania.tistory.com

이번 시간에는 위 두 글을 통해 공부한 이론을 바탕으로 코드를 살펴보겠다.


Appliance.java

package hellojpa;

import lombok.Data;

import javax.persistence.*;

@Data
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "KIND")
public abstract class Appliance {

    @Id @GeneratedValue
    private Long id;

    private String name;

    private int price;
}

 

AcousticEquipment.java

package hellojpa;

import lombok.Data;
import lombok.ToString;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Data @ToString(callSuper = true)
@DiscriminatorValue("A")
public class AcousticEquipment extends Appliance {
    // 무선여부
    private boolean wireless;
}

Kitchenware.java

package hellojpa;

import lombok.Data;
import lombok.ToString;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Data @ToString(callSuper = true)
@DiscriminatorValue("K")
public class Kitchenware extends Appliance { //주방용품

    // 제조사
    private String manufacturer;

    // 용도
    private String purpose;
}

Thermostat.java

package hellojpa;

import lombok.Data;
import lombok.ToString;

import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;

@Entity
@Data @ToString(callSuper = true)
@DiscriminatorValue("T")
public class Thermostat extends Appliance {

    // 냉방 여부
    private boolean cooling;

    // 난방 여부
    private boolean heating;
}

JpaMain.java

package hellojpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class JpaMain {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");

        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();

        tx.begin();

        try {
            Kitchenware kitchenware = new Kitchenware();
            kitchenware.setName("냄비");
            kitchenware.setPrice(20000);
            kitchenware.setManufacturer("code-mania");
            kitchenware.setPurpose("무수분, 저수분 웰빙요리에 적합한 스테인리스 냄비");
            em.persist(kitchenware);

            em.flush();
            em.clear();

            Appliance appliance = em.find(Appliance.class, kitchenware.getId());
            System.out.println("appliance = " + appliance);

            if(appliance instanceof Kitchenware) {
                Kitchenware findKitchenware = (Kitchenware) appliance;
                System.out.println("kitchenware.getPurpose() = " + findKitchenware.getPurpose());
            } else if(appliance instanceof AcousticEquipment) {
                AcousticEquipment acousticEquipment = (AcousticEquipment) appliance;
                System.out.println("acousticEquipment.isWireless() = " + acousticEquipment.isWireless());
            } else if(appliance instanceof Thermostat) {
                Thermostat thermostat = (Thermostat) appliance;
                System.out.println("thermostat.isCooling() = " + thermostat.isCooling());
            }

            tx.commit();
        } catch (Exception e) {
            tx.rollback();
            e.printStackTrace();
        } finally {
            em.close();
        }

        em.close();
        emf.close();
    }
}

 

해당 코드는 어떤 전략을 사용해도 정상적으로 돌아가는 것을 확인할 수 있다.
(하지만 이 글에서 모든 전략을 번갈아가면서 코드를 확인하기에는 한계가 있기때문에 JOINED만을 살펴보겠다.)
또한 부모 타입을 통해 코드를 조회한 뒤 instanceof를 통해 어떤 타입의 객체인지 확인하고,
다운캐스팅하여 데이터를 출력하고 있는 것을 볼 수 있다.

DB에는 위와 같이 테이블이 생성됐고, 값이 들어갔다.
간단하게 왜 이렇게 테이블이 생성됐고 값이 설정됐는지 살펴보겠다.

먼저 @Inheritance 어노테이션에 의해 조인 전략으로 테이블들이 생성됐다.
@DiscriminatorColumn 어노테이션에 의해 타입판별컬럼명은 KIND로 설정되었다. 
또한 KIND 컬럼의 값으로 `K`가 들어가있는데, 이는 Kitchenware Entity의 @DiscriminatorValue가 K로 설정되었기때문이다.

ID는 자동으로 생성됐고, 그 외의 값들은 setter에 의해 설정된 것을 알 수 있다.

 

직접 코드를 고쳐보며 우리가 지금까지 알아본 @Inheritance나 @DiscriminatorColumn 어노테이션에 의해 테이블이 어떻게 변하는지,
@DiscriminatorValue에 따라 DTYPE(타입판별컬럼)에 값이 어떻게 들어가는지 살펴보자!!!

 

'JPA > 상속관계 매핑' 카테고리의 다른 글

상속관계 매핑  (0) 2021.08.18
슈퍼타입 서브타입 논리 모델 구현 전략  (0) 2021.08.16