JPA 스터디 5주차
- JPA
- 2022. 2. 11. 00:53
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 |