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 스터디 5주차  (0) 2022.02.11
JPA 스터디 4주차  (0) 2022.02.02
JPA 스터디 3주차  (0) 2022.01.26
JPA 스터디 2주차  (0) 2022.01.20

댓글(0)

Designed by JB FACTORY