본문 바로가기
Spring

Spring Data JPA: 고급 매핑

by S2채닝S2 2023. 3. 22.

조인 테이블 전략

  - 테이블 생성 시 FK 기반으로 상속관계를 매핑하고 자동으로 스키마를 생성한다

  - JPA에서 상속에 쓰이는 부모 클래스는 추상 클래스로 만들어야 한다.

  - @Inheritance(strategy = InhreitanceType.JOINED)

 

//부모 클래스: abstract class
@Entity
@Getter
@Setter
@Inheritance(strategy = InheritanceType.JOINED) //조인 전략
@Table(name = "item")
public abstract class Item { 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private int price;
    private int stockQuantity;

    @ManyToOne
    @JoinColumn(name = "order_item_id", referencedColumnName = "id")
    private OrderItem orderItem;

    public void setOrderItem(OrderItem orderItem) {
        if (Objects.nonNull(this.orderItem)) {
            this.orderItem.getItems().remove(this);
        }

        this.orderItem = orderItem;
        orderItem.getItems().add(this);
    }
}

//자식 클래스
@Entity
public class Car extends Item {
    private int power;
}

@Entity
public class Food extends Item{
    private String chef;
}

@Entity
public class Furniture extends Item{
    private int width;
    private int height;
}

 

싱글테이블 전략

  - 상속관계를 테이블 하나로 표현

  - @DiscriminatorColumn(name = "DTYPE") DTYPE를 통해 자식 entity가 어디에 매핑되는지 찾는다.

//부모 클래스: abstract class
@Entity
@Getter
@Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) //싱글 테이블 전략
@DiscriminatorColumn(name = "DTYPE") // 싱글 테이블 전략: "DTYPE"이 구분자가 된다.
@Table(name = "item")
public abstract class Item { 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private int price;
    private int stockQuantity;

    @ManyToOne
    @JoinColumn(name = "order_item_id", referencedColumnName = "id")
    private OrderItem orderItem;

    public void setOrderItem(OrderItem orderItem) {
        if (Objects.nonNull(this.orderItem)) {
            this.orderItem.getItems().remove(this);
        }

        this.orderItem = orderItem;
        orderItem.getItems().add(this);
    }
}

//자식 클래스
@Entity
@DiscriminatorValue("CAR") //싱글 테이블 전략에 사용
public class Car extends Item {
    private int power;
}

@Entity
@DiscriminatorValue("FOOD") 
public class Food extends Item{
    private String chef;
}

@Entity
@DiscriminatorValue("FURNITURE")
public class Furniture extends Item{
    private int width;
    private int height;
}

 

@MappedSuperClass

  - 실제 entity 클래스는 아니지만 @MappedSuperClass 어노테이션이 붙은 클래스를 상속받게 되면 자식 클래스에서 MappedSuperClass 에 있는 필드와 동일한 이름의 필드(&컬럼)이 추가된다.

  - 공통적으로 관리(추가)되는 필드를 MappedSuperClass에 정의하고, 상속받아 사용하면 편리하다.

@Getter
@Setter
@MappedSuperclass
public class BaseEntity {
    @Column(name = "created_by")
    private String createdBy;
    @Column(name = "created_at", columnDefinition = "TIMESTAMP")
    private LocalDateTime createdAt;

}

//상속
@Entity
@Getter
@Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
@Table(name = "item")
public abstract class Item extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private int price;
    private int stockQuantity;

    @ManyToOne
    @JoinColumn(name = "order_item_id", referencedColumnName = "id")
    private OrderItem orderItem;

    public void setOrderItem(OrderItem orderItem) {
        if (Objects.nonNull(this.orderItem)) {
            this.orderItem.getItems().remove(this);
        }

        this.orderItem = orderItem;
        orderItem.getItems().add(this);
    }

}

 

식별자 클래스

  - JPA에서 식별자를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야 한다.

  - 식별자를 조합하여 사용해야 할 경우 사용.

  - @Id 어노테이션을 두개로 설정하면 runtime error가 발생한다. 

   >> 영속성 컨텍스트에서 1차 캐시로 id 컬럼을 key로 entity를 관리하기 때문

 

@IdClass

  - entity에서 사용할 id 필드명과 idclass의 필드명은 동일해야 한다.

  * 반드시 지켜야할 점

    - Serializable 인터페이스를 구현해야한다(즉, implements 해야 함)

    - equals, hashCode를 구현해야 한다(영속성 컨텍스트에서 키값을 구분하기 위함)

    - 기본 생성자가 있어야 한다

    - 식별자 클래스는 public이어야 한다

@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable {
    private String id1;
    private String id2;
}
@Entity
@IdClass(ParentId.class) // 식별자로 IdClass를 사용할 것임.
public class Parent {
    @Id
    private String id1;
    @Id
    private String id2;
}
//조회
entityManager.find(Parent.class, new ParentId("id1", "id2"))

 

@EmbeddedId

  - 현업에서 많이 사용

  - Id로 식별자 객체 자체를 사용.

@Entity
public class Parent {
    @EmbeddedId
    private ParentId parentId;
}

@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Embeddable
public class ParentId implements Serializable {
    private String id1;
    private String id2;
}

최근댓글

최근글

skin by © 2024 ttuttak