[JPA] 7. 연관관계 매핑 고급

최진민·2021년 6월 6일
0

JPA

목록 보기
7/11
post-thumbnail

상속관계 매핑

  • 관계형 DB는 상속 관계 X

  • 슈퍼타입 - 서브타입 관계 : 객체 상속과 유사

  • 상속관계 매핑 : 객체상속 구조 / DB슈퍼타입 - 서브타입 관계를 매핑

  • 주요 @

    • @Inheritance(stategy = InheritanceType.XXX)
      • 1) JOINED
      • 2) SINGLE_TABLE
      • 3) TABLE_PER_CLASS
    • @DiscriminatorColumn
      • name : "DTYPE" (defalut)
      • ✨DTYPE에 엔티티명이 들어간다.
    • @DiscriminatorValue
      • 자식 클래스의 DTYPE의 값을 변경할 수 있다.
  • 🧨슈퍼타입 - 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법 3가지

    • ⭕1) 조인 전략 (각각 테이블로 변환) - 정석

      • 상품

        @Entity
        @Inheritance(strategy = InheritanceType.JOINED)
        @DiscriminatorColumn
        public class Item {
        
            @Id
            @GeneratedValue
            @Column(name = "item_id")
            private Long id;
        
            private String name;
            private int price;
        }
      • 앨범, 영화, 책

        @Entity
        public class Album extends Item{
        
            private String artist;
        }
        
        @Entity
        public class Book extends Item {
            private String author;
            private String isbn;
        }
        
        @Entity
        public class Movie extends Item {
            private String director;
            private String actor;
        }
      • 메인

        try {
        
                    Movie movie = new Movie();
                    movie.setDirector("aaaa");
                    movie.setActor("bbbb");
                    movie.setName("바람과 함께 사라지다");
                    movie.setPrice(10000);
        
                    em.persist(movie);
        
                    tx.commit();
                }
      • DB 결과

      • 장점

        • 정규화
        • 외래 키 참조 무결성 제약조건 활용 가능(null x)
        • 저장공간 효율화
      • 단점 (SINGLE_TABLE 전략과 비교)

        • 조회 시 많은 조인 (성능 저하)
        • 조회 쿼리 복잡
        • INSERT 2번
    • ⭕2) 단일 테이블 전략 (통합 테이블 변환) - 단순할 때 사용

      • DTYPE을 사용해 구분 ⇒ If, @DiscriminatorColumn 없다면? 저절로 생긴다. 꼭 필요하기 때문이다.

      • Item.class상속 전략SINGLE_TABLE로 변경, 메인 그대로 실행

      • DB 결과

      • 장점

        • 성능 빠름
        • 조회 쿼리 단순
      • 단점

        • 자식 엔티티가 매핑한 컬럼(필드값)은 모두 null 허용
        • 테이블이 커질 가능성(조회 성능이 느려질 수도 있음)
    • ⭕3) 구현 클래스마다 테이블 전략 (서브타입 테이블로 변환) - 쓰지 마세용!

      • Item.class를 추상화(abstract)하고 상속 전략을 TABLE_PER_CLASS로 변경 + DTYPE 필요 없음

        @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;
        }
        • ITEM 테이블이 존재하지 않는다.
      • 쓰지 말아야 하기 때문에, 장/단점 X


Mapped Superclass - 매핑 정보 상속

  • 공통 매핑 정보가 필요할 때 사용(id, name)

    • 귀찮음을 타개하기 위해 추상 클래스를 통해 속성만 공동적으로 묶는다.

    • 예를 들어, 등록/수정에 필요한 정보가 있다.

      • BaseEntity

        @MappedSuperclass
        public abstract class BaseEntity {
        
            private String createdBy;
            private LocalDateTime createdDate;
            private String lastModifiedBy;
            private LocalDateTime lastModifiedDate;
        }
      • Member

        @Entity
        public class Member extends BaseEntity{
        	...
        }
        • extends BaseEntity사용
  • 특징

    • 상속 관계 매핑 X, 엔티티 X → 테이블과 매핑 X
    • 자식 클래스에 매핑 정보만 제공
    • 조회 불가(em.find(BaseEntity.class, PK)불가)
    • 추상 클래스 권장
    • 테이블과 관계 X, 단순 공통 속성 모으기
    • 전체 엔티티에서 공통으로 적용되는 정보를 모으기

예제 4) 상속관계 매핑

  • 요구사항

    • 상품에는 음반, 도서, 영화가 있고 확장할 수 있다.
    • 모든 데이터는 등록일, 수정일 필수
  • 도메인 모델

  • 테이블 설계

  • Item

    @Entity
    @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
    @DiscriminatorColumn
    public abstract class Item extends BaseEntity {
    
        @Id
        @GeneratedValue
        @Column(name = "item_id")
        private Long id;
    
        private String name;
        private int price;
        private int stockQuantity;
    
        @OneToMany(mappedBy = "item")
        private List<CategoryItem> categoryItems = new ArrayList<>();
    }
  • 음반, 책, 영화

    @Entity
    public class Album extends Item {
    
        private String artist;
        private String etc;
    }
    
    @Entity
    public class Book extends Item {
    
        private String author;
        private String isbn;
    
        public String getAuthor() {
            return author;
        }
    
        public void setAuthor(String author) {
            this.author = author;
        }
    
        public String getIsbn() {
            return isbn;
        }
    
        public void setIsbn(String isbn) {
            this.isbn = isbn;
        }
    }
    
    @Entity
    public class Movie extends Item {
    
        private String director;
        private String actor;
    
    }
  • BaseEntity (등록일, 수정일)

    @MappedSuperclass
    public abstract class BaseEntity {
    
        private LocalDateTime createdDate;
        private LocalDateTime updatedDate;
    
    }
  • 메인

    try{
    
        Book book = new Book();
        book.setName("JPA");
        book.setAuthor("jinmin");
        em.persist(book);
    
        tx.commit();
    }
  • DB 결과

    • DTYPE에 따라 없는 데이터는 null(String) or 0(int)
    • BaseEntity에 속한 매핑 정보(등록일, 수정일)가 나타남
profile
열심히 해보자9999

0개의 댓글