[java] JPA 식별자 생성 방식 By starseat 2022-10-26 08:43:08 java/spring Post Tags # JPA 식별자 생성 방식 - 직접 할당 - 식별 컬럼 방식 - 시퀀스 사용 방식 - 테이블 사용 방식 ## 직접 생성 방식 - @Id 설정 대상에 직접 값 설정 - 사용자가 입력한 값, 규칙에 따라 생성한 값 등 - 예) 이메일, 주문 번호 - 저장하기 전에 생성자 할당 (보통 생성 시점에 전달) ### 사용 예 ```java @Entity @Table(name = "hotel") public class Hotel { @Id @Column(name = "hotel_id") private String id; ... } ``` ```java Hotel hotel = new Hotel("H-001", ...); entityManager.persist(hotel); ``` ## 식별 컬럼 방식 - DB의 식별 컬럼에 매핑(예, MySQL 자동 증가 컬럼) - DB가 식별자를 생성하므로 객체 생성시에 식별값을 설정하지 않음 - 설정 방식 - @GeneratedValue(strategy = GenerationType.IDENTITY) - INSERT 쿼리를 실행해야 식별자를 알 수 있음. - EntityManager.persist() 호출 시점에 INSERT 쿼리 실행 - persist() 실행할 떄 객체에 식별자 값 할당됨. ### 사용 예 ```java @Entity public class Review { @Id @Column(name = "review_id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "hotel_id") private String hotelId; ... } ``` ```java // 생성 시점에 식별자 지정하지 않음 Review review = new Review(4, "H-01", ...); // 저장 시점에 INSERT 쿼리 바로 실행 entityManager.persist(review); // persist() 이후 식별자 사용 가능 Long newReviewId = review.getId(); ``` ## 시퀀스 사용 방식 - 시퀀스를 사용해서 식별자 생성 (Oracle 시퀀스 등) - JPA가 식별자 생성 처리 -> 객체 생성시에 식별값을 설정하지 않음 - 설정 방식 - @SequenceGenerator 로 시퀀스 생성기 설정 - @GeneratedValue 의 generator 로 시퀀스 생성기 지정 - EntityManager.persist() 호출 시점에 시퀀스 사용 - persist() 실행시 객체에 식별자 값 할당됨 - INSERT 쿼리는 실행하지 않음 ### 사용 예 - `name` 은 `GeneratedValue` 에서 사용할 이름 - `sequenceName` 이 실제 시퀀스 이름 - `allocationSize` 는 `1` 로 지정 권고 - `5` 나 `10` 등 다른 값으로 지정하면 중복되서 사용됨. - **seq 가 중복되서 pk 값이 중복될 수도 있음.** ```java @Entity @Table(schema = "crm", name = "activity_log") public class ActivityLog { @Id @SequenceGenerator( name = "log_seq_gen", sequenceName = "activity_seq", schema = "crm", allocationSize = 1 ) @GeneratedValue(generator = "log_seq_gen") private Long id; @Column(name = "user_id") private String userId; ... public ActivityLog(String userId, String activityType, ...) { this.userId = userId; this.activityType = activityType; this.created = LocalDateTime.now(); ... } } ``` ```java EMFOracle.init(); EntityManager em = EMFOracle.createEntityManager(); EntityTransaction tx = em.getTransaction(); ... tx.begin(); // 생성 시점에 식별자 지정하지 않음. ActivityLog log new ActivityLog("U01", "VISIT", ...); // persist() 시점에 시퀀스로 식별자 구함 em.persist(log); // 커밋 시점에 INSERT 쿼리 실행 tx.commit(); ``` ## 테이블 사용 방식 - 테이블을 시퀀스처럼 사용 - 테이블에 Entity 를 위한 키 보관 - 해당 테이블을 이용해서 다음 식별자 생성 - 설정 방식 - @TableGenerator 로 테이블 생성기 설정 - @GeneratedValue 의 generator 로 테이블 생성기 지정 - EntityManager.persist() 호출 시점에 테이블 사용 - persist() 할 때 테이블을 이용해서 식별자를 구하고 이를 Entity 에 할당 - INSERT 쿼리는 실행하지 않음 ### 사용 예 - 식별자를 생서할 때 사용할 테이블 구조 - Entity 이름 컬럼 - 식별자 보관 컬럼 - DB ```sql create table id_seq ( entity varchar(100) not null primary key, nextval bigint ) engine innodb character set utf8mb4; ``` - java ```java @Entity @Table(name = "access_log") public class AccessLog { @Id @TableGenerator( name = "accessIdGen", table = "id_seq", pkColumnName = "entity", pkColumnValue = "accessLog", valueColumnName = "nextval", initialValue = 0, allocationSize = 1 ) @GeneratedValue(generator = "accessIdGen") private Long id; ... } ``` # 출처 - [최범균님의 JPA 기초 05 엔티티 식별자 생성 방식](https://www.youtube.com/watch?v=Xw9uTs72SVo) Previous Post [jpa] JPA annotation Next Post [java] JPA Embeddable