[JPA] 엔티티 매핑 - 기본키 매핑

hyozkim·2020년 6월 26일
0

JPA

목록 보기
3/4
post-thumbnail

👋 엔티티 매핑 소개

  • 객체와 테이블 매핑 @Entity, @Table

  • 필드와 컬럼 매핑 @Column

  • 기본키 매핑 @Id

  • 연관관계 매핑 @ManyToOne, @JoinColumn

기본키 매핑 방법

  • 직접 할당: @Id만 사용

  • 자동 생성(@GeneratedValue)

    • IDENTITY - 데이터베이스에 위임. MYSQL, PostgreSQL, SQL Server, DB2 에서 사용.
    • SEQUENCE - 데이터베이스 시퀀스 오브잭트 사용. Oracle, DB2, H2 에서 사용. @SequenceGenerator 필요.
    • TABLE - 키 생성용 테이블 사용. 모든 DB에서 사용. @TableGenerator 필요.
    • AUTO - 방언에 따라 자동 지정. 기본값.

IDENTITY 전략 특징

IDENTITY 전략은 기본적으로 기본키 생성하는 일을 데이터베이스에게 전적으로 맡겨버린다.

그리고 보통 JPA는 트랜잭션 커밋 tx.commit() 시점에 INSERT SQL을 실행한다.

IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행하고 DB에서 식별자를 조회가 가능하다.

  • IDENTITY 전략 설정
// Member.java 
public class Member {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "MEMBER_ID")
  private Long id;
  • IDENTITY 전략 특징 테스트
// EntityMappingTest.java
Member member = new Member();
member.setUsername("member2");
System.out.println("=======================");

em.persist(member);
System.out.println("member.id = " + member.getId());
System.out.println("=======================");

tx.commit();     

tx.commit(); 이 실행하기 전인데 DB에서 식별자 id가 조회되는 것을 볼 수 있다.
즉, IDENTITY 전략은 tx.commit()이 아닌 em.persist() 시점에 즉시 INSERT SQL을 실행한다는 사실을 위 예제를 통해 확인해볼 수 있다.

SEQUENCE 전략 특징

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

  • SEQUENCE 전략 세팅
@Entity
@SequenceGenerator(name = “MEMBER_SEQ_GENERATOR",
		sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
		initialValue = 1, allocationSize = 1)

public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;

우선, 시퀀스 전략에 맞게 다음과 같은 create 문구가 출력되는 것을 확인할 수 있다.
initialValue = 1, allocationSize = 1

  • SEQUENCE 전략 테스트
Member member1 = new Member();
member1.setUsername("member1");

Member member2 = new Member();
member2.setUsername("member2");

Member member3 = new Member();
member3.setUsername("member3");

System.out.println("=======================");

em.persist(member1); 
em.persist(member2); 
em.persist(member3); 

System.out.println("member1.id = " + member1.getId());
System.out.println("member2.id = " + member2.getId());
System.out.println("member3.id = " + member3.getId());
System.out.println("=======================");

tx.commit();

다음과 같은 테스트 소스를 실행하게 되면 이런 결과를 얻게 된다.

여기에서 설정을 initialValue=1, allocationSize=1로 했기 때문에 JPA save가 이뤄질때마다 next value call이 발생한다.


만약 initialValue = 1, allocationSize = 50 (default 50)으로 설정했을때 결과를 보면 50개 공간을 메모리에 올려두고 호출하기 때문에 next call 하지 않는 것을 확인할 수 있다.

❗ 캡처를 보면 call next value for MEMBER_SEQ 가 1번 호출되어야 하는거 아닌가? 왜 2번 호출이 되는지 의아할 것이다.

이유

아무것도 저장하지 않았을때 Sequence는 위 그림처럼 되어있다.

여기에서 em.persist(); 즉, save가 실행되면 Sequence가 호출되어 DB_SEQ = 1 이 된다.
그리고 allocationSize=50이기 때문에 Sequence 호출이 또 발생하여 DB_SEQ = 51 가 된다.

즉, 미리 공간을 확보하기 위한 call이 발생한다.
그 다음엔 Memory 공간에 50개가 할당되어있기 때문에 call next value는 호출되지 않는다.

그럼 10,000개 정도로 미리 지정해두면 좋지 않나요?
웹 서버가 내리는 시점에 그게 날라가고 공간만큼 공간이 낭비되게 된다고 한다.
그렇게 크리티컬한 것은 아니지만 그래도 50-100개 정도를 권장한다.

TABLE 전략 특징

Sequence 전략과 유사하다.
키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.

  • TABLE 전략 세팅
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES",
pkColumnValue = “MEMBER_SEQ", allocationSize = 50)
public class Member {
	@Id
	@GeneratedValue(strategy = GenerationType.TABLE,
	generator = "MEMBER_SEQ_GENERATOR")
	private Long id;

참고

김영한님 ORM 표준 JPA프로그래밍 강의를 듣고 공부한 내용을 정리하고자 작성하였습니다. 문제가 될시 삭제하겠습니다. 🙂

profile
차근차근 develog

0개의 댓글