entity를 만들때 기본키를 만들어주는데 난 관성적으로 @Id를 이용해 기본키를 만들어주었다. 따라서 왜? 라는 질문을 받으면 단순히 JPA는 영속성 컨텍스트를 사용하고, 영속성 컨텍스트에 데이터를 저장하고 조회하는 데 기준이 식별자값이라서 정해준다 정도로만 말하였다. 이번에 친구와의 대화를 통해 기본키를 할당하는 것이 여러 방법이 있다는 것을 깨달았고, 특히 JPA 내부에서 동작하는 방식이 다르게 된다는 것을 이번에 알게되었다. 이에 대해 정리하였다.
📌기본 키 매핑
영속성 컨텍스트에 데이터를 저장하고 조회하는 모든 기준은 데이터베이스 기본 키(식별자값)이다.
엔티티가 영속 상태가 되려면 식별자가 반드시 필요하다.
1) 직접 할당 : 기본키를 애플리케이션에서 직접 할당한다.
2) 자동 생성 : 대리 키 사용 방식
- IDENTITY : 기본키 생성을 DB에 위임한다.
- SEQUENCE : DB 시퀀스를 사용하여 기본키를 할당한다.
- TABLE : 키 생성 테이블을 사용한다.
cf)
기본키: 실체에서 각 인스턴스를 유일하게 식별하는 데 가장 적합한 키. 테이블 컬럼중에 하나 선택
대리키: 식별자가 너무 길거나 여러 개의 속성으로 구성되어 있는 경우 인위적으로 추가하는 식별자
🌱기본키 직접 할당
- @Id로 매핑한다.
- em.persist()로 엔티티를 저장하기 전에 애플리케이션에서 기본키를 직접 할당하는 방법→ setId()
💡 em.persist()
- 객체를 데이터베이스에 저장
- persist() 메소드 호출시, JPA가 객체와 매핑정보를 보고 적절한 INSERT SQL를 생성해서 DB에 전달
- persist() 메소드는 엔티티 매니저를 사용해서 엔티티를 영속성 컨택스트에 저장한다.(=영속 상태로 만든다)
🌱IDENTITY 전략
- 기본키 생성을 데이터베이스에 위임하는 전략
- em.persist()를 호출해서 엔티티를 저장한 직후에 할당된 식별자 값 출력
- em.persist 즉시 해당 엔티티를 데이터베이스에 플러시 합니다
- 데이터를 데이터베이스에 INSERT한 후에 기본키 값 조회 가능
- 기본 키 값을 얻어오기 위해 데이터베이스를 추가로 조회한다.
- 엔티티를 데이터베이스에 저장한 후에 식별자를 조회해서 엔티티의 식별자에 할당
- 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
→ em.persist()로 객체를 영속화 시키는 시점에 곧바로 insert 쿼리가 DB로 전송
→ entityManager.persist()가 호출되자마자 INSERT SQL을 통해 DB에서 식별자를 조회하여 영속성 컨텍스트의 1차 캐시에 값을 넣는다.
→ 한꺼번에 쿼리를 날리지 않는다. 매번 생성마다 애플리케이션과 DB와의 네트워크가 매번 이루어진다.
- 사용처
MySQL, PostgreSQL, SQL Server, DB2
🌱SEQUENCE 전략
em.persist()를 호출할 때 먼저 데이터베이스 시퀀스를 사용하여 식별자 조회하고 조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 컨텍스트에 저장한다. 이후 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 데이터베이스에 저장한다.
- JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 allocationSize를 사용
- allocationSize: 한 번의 시퀀스 접근을 통해 사용할 수 있는 PK값의 개수
- 네트워크 접근 횟수를 비약적으로 줄일 수 있게 된다.
- 최초에 persist()시 엔티티의 식별자를 구하기 위해 DB의 시퀀스를 두 번 호출 ex) DB의 시퀀스 증가값이 50, allocationSize 가 기본값인 50인 경우
두 번 호출시 1과 51이 각각 리턴되는데, 1을 JPA가 메모리에서 관리할 시작값, 51을 끝(MAX)값 으로 지정. 엔티티에 51의 식별자가 할당되는 때까지는 DB에 시퀀스를 호출하지 않고 JPA가 직접 가상의 시퀀스 값을 할당
- 사용처
오라클, PostgreSQL, DB2, H2 데이터베이스에 사용
→ 즉 MySQL의 경우, Identity 전략을 사용한다.