[JPA] 엔티티 매핑

19·2022년 9월 21일
0

JPA

목록 보기
7/18
post-custom-banner

엔티티 매핑

  • 객체와 테이블 매핑
    • @Entity, @Table
  • 필드와 컬럼 매핑
    • @Column
  • 기본 키 매핑
    • @Id
  • 연관관계 매핑
    • @ManyToOne, @JoinColumn ...

객체와 테이블 매핑

@Entity / @Table


@Entity

@Entity가 붙은 클래스는 JPA가 관리한다. (엔티티)
JPA를 사용해서 테이블과 매핑할 클래스는 반드시 @Entity를 붙여야 한다.

@Entity
public class Member {
    ...
}
  • Member 엔티티와 Member 테이블을 매핑한다.

주의할 점

  • 기본 생성자 필수 (public / protected)
  • final/enum/inner 클래스 x, 인터페이스 x
  • 필드에 final 사용 x

@Table

엔티티와 매핑할 테이블을 지정한다.

@Entity
@Table(name = "MBR")
public class Member {
    ...
}
  • Member 엔티티와 MBR 테이블을 매핑한다.

필드와 컬럼 매핑

DDL 생성 기능을 사용할 수 있다.

@Entity
public class Member {
    
    @Column(nullable = false, length = 10)
    private String name;
    ...
}
  • 필드에 제약조건을 추가할 수 있다
  • DDL이 자동 생성될 때만 사용되며, JPA 실행 로직에는 영향을 미치지 않는다.

@Column

  • unique는 거의 사용하지 않는다 (제약조건 이름이 알아보기 힘들어서)
    • @Table의 uniqueConstraints를 사용한다

@Enumerated

자바 enum 타입을 매핑할 때 사용한다.

  • 기본값이 ORDINAL이지만, 명시적으로 STRING으로 사용해야 한다.
    • ORDINAL로 하면 순서(INT형)로 저장된다
      • Enum 클래스에 필드가 추가되면 순서가 꼬이게 된다.

ORDINAL 사용 X


@Temporal

날짜 타입을 매핑할 때 사용한다.

LocalDate, LocalDateTime을 사용할 때는 @Temporal 어노테이션 생략 가능

최근엔 LocalDate, LocalDateTime을 사용해서 @Temporal 어노테이션을 거의 쓸 일이 없다.


@Lob

BLOB, CLOB으로 구분된다.
필드 타입이 문자면 CLOB, 나머지는 BLOB으로 매핑된다.

CLOB: String, char[], java.sql.CLOB
BLOB: byte[], java.sql.BLOB


@Transient

컬럼과 매핑하지 않으려는 필드에 붙인다.
DB에 저장되지 않고, 조회도 되지 않는다.


기본 키 매핑

기본 키 매핑 어노테이션으로는 2가지가 존재한다.

  • @Id
  • @GeneratedValue

@Id

키값을 직접 할당한다


@GeneratedValue

키값을 자동으로 생성해서 할당한다.
전략에 따라 작동하는 방식이 다르다.

전략 종류
- IDENTITY
  - 데이터베이스에 위임, MYSQL
  
- SEQUENCE
  - 데이터베이스 시퀀스 오브젝트 사용, ORACLE
  - @SequenceGenerator 필요
  
- TABLE
  - 키 생성용 테이블 사용, 모든 DB에서 사용 가능
  - @TableGenerator 필요
  
- AUTO
  - 방언에 따라 자동 지정, 기본값

예시)

@Id @GeneratedValue(strategy = GenerationType.[전략 종류])
private String username;

IDENTITY 전략

기본 키 생성을 데이터베이스에 위임한다.
MySQL의 AUTO_INCREMENT

전략이 IDENTITY면 예외적으로, persist할 때 DB에 Insert 쿼리가 날라가고 DB에서 ID값을 가져온다.
JPA는 보통 commit할 때 DB로 쿼리가 날라가지만, auto_increment는 DB에 Insert가 된 후에야 ID값을 알 수 있기 때문에 전략이 IDENTITY일 때만 persist시, ID값 세팅을 위해 DB쿼리가 날라간다.
그리고 나서, 영속성 컨텍스트에 저장한다


SEQUENCE 전략

유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
시퀀스 오브젝트를 생성하고 가져와서 세팅한다.

@Entity
@SequenceGenerator(name = "MEMBER_SEQ_GENERATOR", sequenceName = "MEMBER_SEQ")
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
    private Long id;
    ...
}

MEMBER_SEQ를 이름으로 한 데이터베이스 시퀀스가 생성된다.
이 시퀀스를 가져와서 ID값으로 세팅하는 것


persist할 때, 데이터베이스 시퀀스에서 값을 얻어온 후, ID값으로 세팅하고 영속성 컨텍스트에 저장하는 순으로 동작한다. (아직 DB에 쿼리가 날라간 것은 아님)
commit 시점에 DB 쿼리가 날라간다.


TABLE 전략

키 생성 전용 테이블을 하나 만들어서 테이터베이스 시퀀스를 흉내내는 전략이다.
모든 DB에 적용 가능하다는 장점이 있다.


권장하는 식별자 전략

기본 키 제약조건에 부합해야 한다.
null이면 안되고, 유일해야 하며, 변하면 안되는 속성!
그런데, 이 조건을 미래까지 만족시킬 자연키를 찾기는 어렵다.

자연키

비즈니스적으로 의미있는 식별할 수 있는 정보들
ex) 주민등록번호. 전화번호등

대체키(대리키)

비즈니스와 전혀 상관없는 시퀀스값
ex) 랜덤값, uuid등

예를 들어, 주민등록번호가 PK인 테이블이 있는데, 주민등록번호를 테이블에 담으면 안된다는 지침이 내려온다면?
PK가 바뀌게 되고, 헤딩 PK를 참조하는 다른 테이블까지 영향을 끼치게 된다.
이렇게 변경 가능성이 많으니 되도록 대체키를 PK로 삼도록 하자!

권장하는 방식 : Long형 + 대체키 + 키 생성전략 사용(IDENTITY, SEQUENCE)



참고

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 김영한

profile
하나씩 차근차근
post-custom-banner

0개의 댓글