JPA 스터디 5주차

반응형
반응형

1. 조인 테이블 전략 : 부모 테이블의 기본 키를 받아서 기본 키 + 외래 키로 사용하는 전략

        장점 : 
                    - 테이블이 정규화된다.
                    - 외래 키 참조 무결성 제약조건을 활용할 수 있다.
                    - 저장공간을 효율적으로 사용한다.
       
       단점 :
                     - 조인할 때 조인이 많이 사용되므로 성능이 저하 될 수 있다.
                     - 조회 쿼리가 복잡하다.
                     - 데이터를 등록할 INSERT SQL을 두번 실행한다.

        특징: 
                    구분 칼럼
                   

@DiscriminatorColumn(name = "DTYPE")
/**
 * (Optional) The name of column to be used for the discriminator.
 */
String name() default "DTYPE";

/**
 * (Optional) The type of object/column to use as a class discriminator.
 * Defaults to {@link DiscriminatorType#STRING DiscriminatorType.STRING}.
 */
DiscriminatorType discriminatorType() default STRING;

/**
 * (Optional) The SQL fragment that is used when generating the DDL 
 * for the discriminator column.
 * <p> Defaults to the provider-generated SQL to create a column 
 * of the specified discriminator type.
 */
String columnDefinition() default "";

/** 
 * (Optional) The column length for String-based discriminator types. 
 * Ignored for other discriminator types.
 */
int length() default 31;

확인해봤는데 전부 optional이다.
칼럼에 적용이 된다는 걸 확인 가능하다.

2. 싱글 테이블 전략 : 

        장점 : 
                    - 조인이 필요 없으므로 일반적으로 조회 성능이 빠르다.
                    - 조회 쿼리가 단순하다.
       
       단점 :
                     - 자식 엔티티가 매핑한 컬럼은 모두 null을 허용해야 한다.
                     - 단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있다.상황에 따라 조회 성능이 느려질 수 있다.   

        특징: 
                    구분 칼럼반드시 필요

  - 참고 서적: 자바 ORM표준 JPA프로그래밍                    


3. 구현 테이블 전략
  - 이거는 사용하지 말자.

이렇게 되면 조인 테이블 전략이냐 아니면 싱글 테이블이냐인데
어떨때는 조인 테이블로 정하고 
어떨때는 싱글 테이블로 하는 것이 좋을까?

무조건 조인이 좋냐 아니면 싱글이 좋냐는 없는 것 같다.
상황에 따라 달라질 수 도 있겠지만
어디었는지는 정확히 기억은 않나지만 칼럼은 최소한으로 두는게 좋다고 했다.
즉, 지나치게 칼럼이 많다면 조인 테이블 전략을 사용하고
칼럼 수가 그리 많지 않는다면 싱글 테이블을 사용하는게 좋다고 생각이 든다.

@MappedSuperclass

@Entity가 테이블의 느낌이라면 이거는 객체스러운 느낌이다.

@MappedSuperclass
public class BaseTime {
  private LocalDateTime createTime;
  private LocalDateTime endTime;
 }

요렇게 붙여주고
이것을 상속해서 바로 사용해주면 끝이다.

@AttributeOverrides({
    @AttributeOverride(name = "createTime", column = @Column(name = "good"))
})

요렇게 사용하면 createTime이 good으로 변경되어진다.

- 이 클래스는 테이블과 매핑되지 않고 자식 클래스에 엔티티의 매핑 정보를 상속하기 위해 사용한다.
- @MappedSuperclass로 지정한 클래스가 아니므로 em.find()나 JPQL에서 사용할 수 없다.
   - em.find()를 할 수 없는 이유: pk가 없다.

- 직접 사용할 일이 없기 때문에 추상 클래스로 만들 것을 권장한다.

식별 관계 vs 비 식별 관계

 - 식별 관계 : 부모테이블의 기본 키를 내려 받아서 자식 테이블의 기본키 + 외래키로 사용하는 관계다.


 - 비식별 관계 : 부모테이블의 기본키를 받아서 자식 테이블의 외래키로만 사용하는 관계
      -필수적 비식별 관계 : null 허용 안함, 연관관계 필수로 맺어야 함


      - 선택적 비식별 관계 : 외래키에 null을 허용한다.

점선이냐 실선이냐에 따라 식별관계를 파악할 수 있다.

복합키 : 식별자 관계 매핑
  - JPA에서 식별자를 둘 이상 사용하려면 별도의 식별자 클래스를 만들어야 한다.

@IdClass 

@Entity
@IdClass(ParentId.class)
public class Parent {

  @Id
  @Column(name = "P1")
  private String id1;

  @Id
  @Column(name = "P2")
  private String id2;

  private String name;
public class ParentId implements Serializable {
  private String id1;
  private String id2;

  public ParentId() {
  }

  public ParentId(String id1, String id2) {
    this.id1 = id1;
    this.id2 = id2;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    ParentId parentId = (ParentId) o;
    return Objects.equals(id1, parentId.id1) && Objects.equals(id2, parentId.id2);
  }

  @Override
  public int hashCode() {
    return Objects.hash(id1, id2);
  }
}

조건 
  1. Serializable 인터페이스 구현
  2. hashcode, equals 구현
  3. Idclass에서 사용하는 키값과 엔티티에서 사용하는 값이 같아야 한다.  (Id1, Id2)

Parent parent1 = em.find(Parent.class, parent);  X
Parent parent1 = em.find(Parent.class, new ParentId("myId1", "myId2")); O

이 방법은 데이터베이스에 맞춘 방법이라고 한다.

@EmbeddedId

@Entity
public class Parent {

  @EmbeddedId
  private ParentId id;
public class ParentId implements Serializable {
  @Column(name = "P1")
  private String id1;
  @Column(name = "P2")
  private String id2;

이것도 조건은 비슷하다.

이렇게 하면 복합키를 만들 수 있다.

어떤 방법이 더 좋을까?

식별 관계 매핑

@Id
  @ManyToOne
  @JoinColumns({
      @JoinColumn(name = "PARENT_ID"),
      @JoinColumn(name = "CHILD_ID")
  })
  private Child child;

요런 식으로 조인된 칼럼들을 가져오고 (FK)
그 값들을 PK로 활용하는 것을 확인 할 수 있다. 이런게 식별관계라 생각이 든다. 이거는 SQLD를 공부하면서 더 자세하게 작성할예정이다.
여기에서는 어떤 느낌인지만 작성할 예정이다.

비 식별 관계 매핑

@Entity
public class Child {

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

  @ManyToOne
  @JoinColumn(name = "PARENT_ID")
  private Parent parent;

}

지금보면 PK랑 FK가 서로 다르게 세팅이 된다는 것을 확인 할 수 있다.

코드를 보면 식별관계로 무언가를 만들려면
@IdClass 또는 @EmbeddedId를 사용해야 되는것 같다.

식별 관계를 사용할때 기본 키로 비즈니스 의미가 있는 자연 키 컬럼을 조합하는 경우가 많다고 한다.
식별 관계를 가지게 되면 특정 상황에서 
즉, 조인 없이 하위 테이블만으로 검색을 완료 할 수 있다고 한다.

조인 테이블
칼럼으로 조인하는 것 말고
테이블 자체로 조인을 하는 방법을 말한다.
조인 테이블을 연결 또는 링크 테이블이라고 부른다.

저번주 쯤에 다대다 설명하면서 그린 그림이 있다. 지금 생각해보면 이걸 사용하면 조금더 좋을지도 모르겠다는 생각이 갑자기 들었다.

  @OneToOne
  @JoinTable(name = "PARENT_CHILD",
  joinColumns = @JoinColumn(name = "PARENT_ID"),
  inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
  private Child child;

 요렇게 하면, 1:1관계 조인 테이블이 만들어진다고 한다.
나는 이것도 모르고 직접 테이블을 만들었는데 ㅜㅜ

  @ManyToMany
  @JoinTable(name = "PARENT_CHILD",
      joinColumns = @JoinColumn(name = "PARENT_ID"),
      inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
  private List<Child> child = new ArrayList<>();

요런게 양쪽에 있으면 서로 데이터를 주고 받고 할 수 있다.
조인 테이블에 컬럼을 추가하려면 @JoinTable 전략을 사용할 수 없다고 한다. 이때는 어쩔 수 없이 엔티티를 새로 만드는게 좋을 것 같다,

엔티티 하나에 여러 테이블 매핑

@Entity
@Table(name = "BOARD")
@SecondaryTable(name = "BOARD_DETAIL",
pkJoinColumns = @PrimaryKeyJoinColumn(name = "BOARD_DETAIL_ID"))
public class Board {

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

  private String title;

  @Column(table = "BOARD_DETAIL")
  private String content;

하나의 엔티티에 여러 테이블을 넣을 수 도 있다고 한다. 근데 좀 가독성이 

반응형

'JPA' 카테고리의 다른 글

JPA 스터디 7주차  (0) 2022.02.26
JPA 스터디 6주차  (1) 2022.02.20
JPA 스터디 4주차  (0) 2022.02.02
JPA 스터디 3주차  (0) 2022.01.26
JPA 스터디 2주차  (0) 2022.01.20

댓글

Designed by JB FACTORY