Development/JPA

JPA 기본키 매핑 방식과 키생성 전략은 무엇을 선택해야할까?

DevKTak 2023. 4. 3. 12:34
  • 자연키(natural key)
    • 비즈니스에 의미가 있는 키
    • 예: 주민등록번호, 이메일, 전화번호

 

  • 대리키(surrogate key)
    • 비즈니스와 관련 없는 임의로 만들어진 키, 대체키로도 불린다.
    • 예: 오라클 시퀀스, auto_increment, 키생성 테이블 사용

 

* 자연키 보다는 대리키를 권장

 

기본키(Primary key) 매핑 방식

  • 직접 할당: @Id 어노테이션만 사용해서 회원의 기본키를 직접 할당
  • 자동 생성: 대리키 사용 방식, 기본키 생성을 데이터베이스에 위임한다.
    • IDENTITY: 자동 증가 컬럼(auto_increment)을 이용한 전략
      • 데이터베이스에 INSERT 쿼리를 실행한 후에 생성된 키를 가져와서 엔티티의 식별자로 사용
      • MySQL, SQL Server 등에서 사용
      • 단점은 주로 대량의 데이터를 다루는 경우, 새로운 엔티티를 저장하기 전에 식별자 값을 가져와야 하므로 성능이 다소 저하될 수 있다.
      • 객체를 저장할 때 auto_increment의 경우 애플리케이션에서는 그 값이 얼마임을 알지 못하기에 DB에 insert문을 날려야 id값을 알 수 있다.
        save() 호출 시 원래는 트랜잭션이 끝나는 commit 시점 전에 flush가 이루어지지만, 해당 경우는 DB에서 id 값을 받아와야 하니 save() 메서드를 호출하는 시점에 insert 쿼리가 나간다. (flush가 이루어진다.)
        이렇게 id 값을 할당한 객체는 영속성 컨텍스트 1차 캐시에 값을 넣게 된다.
    • SEQUENCE: 데이터베이스 시퀀스 객체를 사용해서 기본키를 할당한다.
      • 시퀀스 테이블을 만들어서 데이터베이스 시퀀스를 흉내낼 Id를 할당한다. 
      • Oracle, PostgreSQL 등에서 사용
      • JPA는 시퀀스 값을 캐시하는 방법을 제공하여 시퀀스 값을 가져올 때마다 데이터베이스에 접근하지 않고, 캐시에서 값을 가져와서 TABLE 방식보다 데드락에 걸릴 확률은 적다.
      • sequence 값만 시퀀스 객체에서 조회해오면 되기때문에 insert 할 필요가 없다.
        save() 호출 시 id 값을 채우기 위해 select 문이 실행되고, 트랜잭션이 끝나는 commit 시점에 insert 문이 실행된다.
    • TABLE: 데이터베이스에 전용 테이블을 만들어서 그 안에 필요한 컬럼을 생성하여 기본키 값을 관리한다.
      • 특정 벤더에 의존적이지 않다.
      • 엔티티를 저장하기 전에 전용 테이블에서 식별자 값을 가져와서 엔티티의 식별자로 사용
      • 주로 데이터베이스에서 SEQUENCE를 지원하지 않는 경우에 사용
      • SEQUENCE 보다 여러 트랜잭션이 동시에 셀렉트를 하려할 때 데드락에 걸릴 확률이 더 크다.
    • AUTO: dialect 값에 따라서 기본키 자동 생성 전략이 지정된다.
      • 기본값으로, 데이터베이스에 따라 GenerationType.SEQUENCE 또는 GenerationType.IDENTITY 중 하나를 선택

 

결론: 자신이 사용하는 데이터베이스의 특성과 요구 사항을 고려하여 적절한 키 생성 전략을 선택할 것!

 

추가!

Hibernate 5 부터 MySQL 기본 전략이 IDENTITY => TABLE로 변경되었기 때문에

IDENTITY를 기본 전략으로 사용하려면 strategy = GenerationType.IDENTITY를 명시해주자!



'Development > JPA' 카테고리의 다른 글

그놈의 N + 1 문제  (0) 2023.04.10