ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CS 100문 100답 Q.014(JPA의 상속 관계 매핑)
    카테고리 없음 2022. 10. 16. 22:18

    키워드 풀이

    관계형 데이터베이스에는 상속의 개념이 없다. 그래서 ORM에서는 객체의 상속 구조와 데이터베이스의 슈퍼타입 서브타입 관계를 매핑하여 사용한다.

    이번에는 핑전략중 조인 전략, 단일 테이블 전략, 구현 클래스마다 테이블 전략에대해 알아보자.

     

     

    조인 전략

    엔티티 각각을 모두 테이블로 만들고 자식 테이블이 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략이다. 객체는 타입으로 구분이 가능하지만 테이블은 타입의 개념이 없기때문에 타입을 구분할 수 있는 별도의 컬럼을 추가해주어야 한다.

    @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @DiscriminatorColumn(name = "DTYPE")
    public abstract class Item {
    
    	@Id 
    	@GeneratedValue
    	@Column(name = "ITEM_ID")
    	private Long id;
    	private String name; //이름
    	private int price;   //가격
    
    }
    
    @Entity
    @DiscriminatorValue("A")
    public class Album extends Item {
    
    	private String artist;
    
    }
    
    @Entity
    @DiscriminatorValue("M")        
    public class Movie extends Item {
    
    	private String director; //감독 
    	private String actor; //배우
    
    }
    
    •  장점
      • 테이블이 정규화 된다
      • 외래 키 참조 무결성 제야조건을 활용할 수 있다
      • 저장공간을 효율적으로 사용한다
    • 단점
      • 조회할 때 조인이 많이 사용되므로 성능이 저하될 수 있다
      • 조회 쿼리가 복잡하다
      • 데이터를 등록할 INSERT SQL을 두 번 실행한다

     

    단일 테이블 전략

    테이블 하나만을 사용하는 전략이다. 구분 컬럼으로 어떤 자식 데이터가 저장되었는지 구분 한다. 조회할 때 조인문을 사용하지 않으므로 일반적으로는 가장 빠르다. 특징으로는 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다. 테이블 하나에 모든 것을 통합하므로 구분 컬럼을 필수로 사용해야 한다.

     

     

     

    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
    @DiscriminatorColumn(name = "DTYPE")
    public abstract class Item {
    
    	@Id 
    	@GeneratedValue
    	@Column(name = "ITEM_ID") 
    	private Long id;
    	private String name; //이름 
    	private int price; //가격
    
    }
    
    @Entity
    @DiscriminatorValue("A")
    public class Album extends Item {   ... } 
    
    @Entity
    @DiscriminatorValue("M")
    public class Movie extends Item {   ... } 
    
    @Entity
    @DiscriminatorValue("B")
    public class Book extends Item {   ... }
    
    •  장점
      • 조인이 필요 업으므로 일반적으로 조회 성능이 빠르다
      • 조회 쿼리가 단순하다
    • 단점
      • 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다
      • 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있어 상황에 따라서는 조회 성능이 오히려 느려질 수 있다.

     

    구현 클래스마다 테이블 전략

    자식 엔티티마다 테이블을 만든다. 그리고 자식 테이블 각각에 필요한 컬럼이 모두 있다. 일반적으로는 추천하지 않는 전략이다.

    @Entity
    @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 
    public abstract class Item {
    
    	@Id 
    	@GeneratedValue 
    	@Column(name = "ITEM_ID")
    	private Long id;
    	private String name; //이름
    	private int price;   //가격
    
    }
    
    @Entity
    public class Album extends Item { ... } 
    
    @Entity
    public class Movie extends Item { ... } 
    
    @Entity
    public class Book extends Item { ... }
    
    •  장점
      • 서브 타입을 구분해서 처리할 때 효과적이다
      • not null 제약조건을 사용할 수 있다.
    • 단점
      • 여러 자식 테이블을 함께 조회할 때 성능이 느리다(SQL에 UNION을 사용해야 함)
      • 자식 테이블을 통합해서 쿼리하기 어렵다

     

    참고자료

    • 자바 ORM표준 JPA 프로그래밍 - 김영한 

     

    스스로 생각해보기!

    현재 진행중인 스터디 프로젝트에서 "구현 클래스마다 테이블 전략"을 적용하여 개발중 이다. 초기 테이블 전략을 결정하는 과정에서 상기 3가지 전략을 놓고 JMeter를 활용해 100만건 데이터를 조회하여 성능 비교를 한 결과 "구현 클래스마다 테이블 전략"으로 선정하였다. 추천하지 않는 방식이라는것을 알고 있었지만 직접 개발을 하면서 문제점을 파악하고 싶었다. 현재 MVP기능이 마무리 되어 가는 시점에서 내가 느꼈던 해당 전략의 문제점으로는 개발 과정에서 불편함이 있었다. 테이블이 전부 나누어져있다보니 코드 작성하는 과정에서 객체지향적인 코드를 짜는것이 불편하다는 생각이 들었다. 기술적인 단점은 다음달 진행되는 고도화 작업에서 깊이있게 스터디할 예정이다.

    댓글

Designed by Tistory.