[JPA] 엔티티 매핑과 기본키 매핑 전략

leehyunjon·2022년 7월 15일
0

JPA

목록 보기
5/10

Entity 매핑

JPA를 이용함에 있어서 가장 먼저 해야할 것은 엔티티로 사용할 객체와 데이터베이스 테이블을 정확하게 매핑하는 것이다.

매핑에 필요한 기본 어노테이션

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

@Entity

JPA를 통해 데이터베이스 테이블과 매핑할 엔티티 클래스는 @Entity 어노테이션을 필수로 붙여주어야 한다.

@Entity 어노테이션이 붙어있는 클래스는 JPA가 관리한다.

@Entity
public class Member{

	//...
    long id;
}

주의사항

  • 기본생성자 필수
  • final, enum, interface 클래스에서는 사용 불가
  • final 멤버변수는 사용할 수 없다.

기본키 매핑

기본키 생성 전략

IDENTITY 전략

@Entity
public class Member{

	@Id
    @GeneratedValue(strategy = GenerationType.INDENTITY)
    Long id;
}
  • @GeneratedValue(strategy = GenerationType.INDENTITY)
  • 기본키 생성 및 관리 권한을 데이터베이스에 위임
  • id가 null로 데이터베이스에 INSERT되어도 자동으로 AUTO_INCREMENT가 된다.
  • MySQL, PostgreSQL에서 사용된다.

특징

기본키 생성을 데이터베이스가 관리하기 때문에 em.persist()시 엔티티에는 id==null 인 상태이다.

그렇기 때문에 em.persist()를 하여도 영속성 컨텍스트의 1차캐시에 저장되지 않는다.

하지만 IDENTITY 전략만 예외적으로 em.persist()시 바로 INSERT SQL을 생성하여 데이터베이스에 전달하여 해당 엔티티의 id를 조회하여 엔티티에 적용 후 1차 캐시에 저장하게 된다.

SEQUENCE 전략

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

	@Id
    @GeneratedValue(
    	strategy = GenerationType.SEQUNECE, 
    	generator = "MEMBER_SEQ_GENERATOR")
    )
    Long id;
}
  • @GeneratedValue(strategy = GenerationType.SEQUNECE, generator = "[식별자 생성기 이름]")
  • @SequenceGenerator(name="[식별자 생성기 이름]", sequenceName="[데이터베이스 시퀀스 이름]")
    • name : 식별자 생성기 이름
    • sequenceName : 데이터베이스 시퀀스 이름
    • initValue : 시퀀스 초기 값(default : 1)
    • allocationSize : 시퀀스 한 번 호출에 증가하는 수(default : 50)
  • 데이터베이스 SEQUENCE사용
    • 유일한 값을 순서대로 생성하는 특별한 데이터베이스 object
  • ORACLE

특징

id값을 데이터베이스 시퀀스(sequenceName)에서 가져온다.

SEQUENCE전략도 id==null이기 때문에 1차 캐시에 해당 엔티티를 저장할 수 없다. 하지만 SEQUENCE전략은 em.persis()를 호출하기 전 데이터베이스의 SEQUENCE에서 기본값을 가져온다(hibernate: call next value for "[데이터베이스 시퀀스 이름]").
그 후 엔티티를 데이터베이스 SEQUENCE에서 가져온 시퀀스를 기본키로 적용 후 em.persist()가 수행되기 때문에 1차 캐시에 저장되어 영속상태가 될 수 있다.

IDENTITY전략과 다르게 em.persist()가 호출될 때 id값이 있으므로 쓰기 지연이 가능하다.

allocationSize의 default가 50인 이유

SEQUENCE전략은 데이터베이스 SEQUENCE에서 id를 받아와 영속상태로 저장하게 되는데, 이는 실질적으로 두번의 데이터베이스와의 통신이 있어야 한다. 그렇기 때문에 성능상 이슈가 발생할 수 있다.

이를 해결하기 위해 allocationSize를 사용한다. 이는 allocationSize가 50일 때, 데이터베이스 SEQUENCE와 1번 통신했을 때 메모리상에 50개를 저장해두고(SEQUENCE에는 51로 갱신된다.) 시퀀스가 필요할 때 데이터베이스 SEQUENCE와의 통신 대신에 메모리에 있는 시퀀스를 사용하게된다.

메모리상의 기본키를 모두 사용하게 되었을 때, 데이터베이스 SEQUENCE와 통신하여 시퀀스를 갱신하여 사용하게 된다.

allocationSize를 너무 크게 잡게되면 중간에 애플리케이션을 중지하게 되면 사용되지 않는 시퀀스가 삭제가 되기 때문에 사용되지 않는 값들이 버려지게 된다.

TABLE 전략

@Entity
@TableGenerator(name = "MEMBER_SEQ_GENERATOR", table="MEMBER_SEQ")
public class Member{

	@Id
    @GeneratedValue(
    	strategy = GenerationType.TABLE, 
    	generator = "MEMBER_SEQ_GENERATOR")
    )
    Long id;
}
  • @GeneratedValue(strategy = GenerationType.TABLE, generator="MEMBER_SEQ_GENERATOR")
  • @TableGenerator(name = "MEMBER_SEQ_GENERATOR", table="[데이터베이스 이름]")
    • name : 식별자 생성기 이름
    • table : 식별자 생성 테이블 이름
    • initValue : 식별자 초기값
    • allocationSize : 시퀀스 한 번 호출에 증가하는 수

AUTO 전략

@Entity
public class Member{

	@Id
    @GeneratedValue(
    	strategy = GenerationType.AUTO)
    )
    Long id;
}
  • @GeneratedValue(strategy = GenerationType.AUTO)
  • 데이터베이스 특징에 따라 위 3가지 전략 중 하나를 자동 선택
  • 데이터베이스를 변경해도 수정할 필요가 없다.
  • 기본키 생성전략을 정하지 못한 개발 초기단계나 프로토타임에서 사용
  • ORACLE : SEQUENCE
  • MySQL : IDENTITY
  • H2 : SEQUENCE

기본키 선택 전략

자연키

  • 비즈니스적으로 의미가 있는 키
  • 전화번호, 주민번호, 이메일

대리키

  • 비즈니스적으로 의미가 없는 키
  • AUTO_INCREMENT 키, Oracle Sequence

기본키 제약 조건

  • null이 아니다.
  • 유일하다.
  • 수정되지 않는다.

자연키는 환경에 따라서 값이 변경될 수 있다.(개인정보 보호에 의해서 주민번호의 저장이 의무가 되지 않는다면 null이 가능해진다.)

그렇기 때문에 기본키 제약 조건을 모두 만족하는 대리키를 기본키로 선택하는 것이 좋다.


권장하는 식별자 전략

Long + 대리키 + 기본키 생성 전략

Long

int 타입보다 더 많은 정수를 표현할 수 있다.

대리키

자연키보다 기본키 제약 조건을 만족하는 조건을 가지고 있다.

기본키 생성 전략

데이터베이스에 맞는 기본키 생성 전략을 사용해야한다.(IDENTITY, SEQUENCE ...)


Reference

https://github.com/hyunjong-96/SpringBoot_Study/blob/main/JPA/3.%EC%97%94%ED%8B%B0%ED%8B%B0%20%EB%A7%A4%ED%95%91.md

https://gmlwjd9405.github.io/2019/08/12/primary-key-mapping.html

https://velog.io/@conatuseus/%EC%97%94%ED%8B%B0%ED%8B%B0-%EB%A7%A4%ED%95%91-2-msk0kq84v5

profile
내 꿈은 좋은 개발자

0개의 댓글