JPA(Java Persistence API)

[JPA] Part 9. @MappedSuperclass

cwchoiit 2023. 10. 22. 15:38
728x90
반응형
SMALL
728x90
반응형
SMALL

이건 Part 8에서 알아본 상속 관계 매핑이랑은 다른데 (느낌은 비슷하다) 어떤 거냐면 테이블들이 공통으로 사용하는 필드들을 편하게 가져다 쓰기 위해 한 클래스에서 그 필드들을 선언하고 필요한 엔티티가 가져다가 사용하는 것을 말한다.

 

자주 사용되며 아주 대표적인 예시가 createdDate, createdBy, lastModifiedBy, lastModifiedDate같은 필드를 다룰 때이다. 바로 코드를 보자. Part 8에서 사용했던 Item, Movie, Album, Book 테이블을 활용해서 적용해보자. 

Base Entity

package org.example.entity.inheritance;

import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

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

    public String getCreatedBy() {
        return createdBy;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    public LocalDateTime getCreatedDate() {
        return createdDate;
    }

    public void setCreatedDate(LocalDateTime createdDate) {
        this.createdDate = createdDate;
    }

    public String getLastModifiedBy() {
        return lastModifiedBy;
    }

    public void setLastModifiedBy(String lastModifiedBy) {
        this.lastModifiedBy = lastModifiedBy;
    }

    public LocalDateTime getLastModifiedDate() {
        return lastModifiedDate;
    }

    public void setLastModifiedDate(LocalDateTime lastModifiedDate) {
        this.lastModifiedDate = lastModifiedDate;
    }
}

BaseEntity라는 추상클래스를 만들고 공통적으로 사용될 데이터를 모두 작성한 후 이 클래스에 @MappedSuperclass 어노테이션을 추가해준다. 그럼 JPA는 아 이 클래스가 테이블로 만들어지는 클래스가 아니고 메타데이타성 클래스구나를 인지한다.

 

Item Class

package org.example.entity.inheritance;

import javax.persistence.*;

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn
public abstract class Item extends BaseEntity {

    @Id @GeneratedValue
    @Column(name = "ITEM_ID")
    private Long id;

    private String name;
    private int price;

    public Item() {}

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }
}

이제 Album, Book, Movie가 상속받는 Item 클래스는 BaseEntity를 부모로 선언한다. 그렇게 되면 나머지 Album, Book, Movie도 모두 가져다가 사용할 수 있게 된다.

 

확인

package org.example;

import org.example.entity.inheritance.Item;
import org.example.entity.inheritance.Movie;

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

public class Main {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
        EntityManager em = emf.createEntityManager();
        EntityTransaction tx = em.getTransaction();
        
        tx.begin();
        try {
            Movie movie = new Movie("반지의 제왕", 50000, "감독", "배우");
            movie.setCreatedBy("반지의제왕 감독");
            em.persist(movie);

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

            Item item = em.find(Item.class, movie.getId());
            
            System.out.println("Movie item = " + item.getName());
            System.out.println("Movie item createdBy = " + item.getCreatedBy());

            tx.commit();
        } catch (Exception e) {
            System.out.println(e.getMessage());
            tx.rollback();
        } finally {
            em.close();
            emf.close();
        }
    }
}

위 코드처럼 Movie 객체 하나를 추가해서 createdBy 값을 추가하고 DB에 저장한 뒤 DB로부터 데이터를 받아와보자.

다음과 같은 로그가 찍힌다.

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        Item
        (createdBy, createdDate, lastModifiedBy, lastModifiedDate, name, price, DTYPE, ITEM_ID) 
    values
        (?, ?, ?, ?, ?, ?, 'Movie', ?)
Hibernate: 
    insert 
    into
        Movie
        (actor, director, ITEM_ID) 
    values
        (?, ?, ?)
Hibernate: 
    select
        item0_.ITEM_ID as item_id2_3_0_,
        item0_.createdBy as createdb3_3_0_,
        item0_.createdDate as createdd4_3_0_,
        item0_.lastModifiedBy as lastmodi5_3_0_,
        item0_.lastModifiedDate as lastmodi6_3_0_,
        item0_.name as name7_3_0_,
        item0_.price as price8_3_0_,
        item0_1_.author as author1_1_0_,
        item0_1_.isbn as isbn2_1_0_,
        item0_2_.artist as artist1_0_0_,
        item0_3_.actor as actor1_6_0_,
        item0_3_.director as director2_6_0_,
        item0_.DTYPE as dtype1_3_0_ 
    from
        Item item0_ 
    left outer join
        Book item0_1_ 
            on item0_.ITEM_ID=item0_1_.ITEM_ID 
    left outer join
        Album item0_2_ 
            on item0_.ITEM_ID=item0_2_.ITEM_ID 
    left outer join
        Movie item0_3_ 
            on item0_.ITEM_ID=item0_3_.ITEM_ID 
    where
        item0_.ITEM_ID=?
Movie item = 반지의 제왕
Movie item createdBy = 반지의제왕 감독

 

728x90
반응형
LIST