프로젝트를 진행하다가 @GenerateValue 관련으로 문제를 겪어서
제대로 이해할겸 공부를 해봤습니다.
데이터베이스에서 PK 설정 중에 auto_increment 라고
레코드가 추가될 때 마다 자동으로 pk 값을 증가시켜주는 옵션이 있는데
JPA에서는 기본키를 자동으로 생성해주는 @GeneratedValue
가 있습니다.
@Id
와 @GeneratedValue
를 같이 사용을 해야 합니다.
@GeneratedValue
에는 4가지 종류가 있는 한번 알아봅시다.
@GeneratedValue(strategy = GenerationType.IDENTITY)
기본키 생성을 데이터베이스에게 위임하는 방식으로 id값을 따로 할당하지 않아도
데이터베이스가 자동으로 AUTO_INCREMENT를 하여 기본키를 생성해줍니다.
시점
em.persist() 시점에 쓰기 지연을 하지않고 바로 쿼리를 DB에 날려 데이터를 등록하고 식별자를 리턴받습니다.
주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다고 하더라고요. (예: MySQL의 AUTO_ INCREMENT)
보통은 이걸로 많이 사용하시더라고요
@GeneratedValue(strategy = GenerationType.SEQUNCE)
데이터 베이스의 Sequence Object를 사용하여 데이터베이스가 자동으로 기본키를 생성해준다.
@SequenceGenerator
어노테이션이 필요합니다.
@Entity
@SequenceGenerator(
name = "USER_PK_SEQUENCE",
sequenceName = "USER_PK_SEQ",
initailValue = 1,
allocationSize = 50
)
public class UserEntity() {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USER_PK_SEQUENCE")
private Long id;
private String name;
}
제가 시퀀스 규칙을 직접 정의하여 해당 규칙대로 PK값이 증가합니다.
시점
em.persist() 시점에 시퀀스를 조회하는 쿼리를 DB에 날려 시퀀스의 nextValue를 받고 영속성 컨텍스트에 등록합니다.
오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용한다고 합니다.
@GeneratedValue(strategy = GenerationType.TABLE)
키를 생성하는 테이블을 사용하는 방법으로 SEQUENCE 방법과 매우 유사합니다.
@TableGenerator 어노테이션이 필요합니다.
@Entity
@TableGenerator(
name = "USER_PK_TABLE",
table = "USER_PK_SEQ",
pkColumnValue = "USER_SEQ",
allocationSize = 1
)
public class PkEx() {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="USER_PK_TABLE")
private Long id;
private String name;
}
키 생성 전용 테이블을 만들어서 데이터베이스 시퀀스 전략을 따라합니다.
장점은 모든 데이터베이스에 적용은 되는데
성능이 영...
성능떄문에 별로 안쓴다고 합니다. ㅋㅋㅋ
@GeneratedValue(strategy = GenerationType.AUTO)
기본 설정 값으로 각 데이터베이스에 따라 기본키를 자동으로 생성합니다.
(JPA 구현체가 자동으로 생성 전략을 고름)
프로젝트를 진행하다가 복합키가 설정된 Entity에서 GeneratedValue IDENTITY 방식을 사용했더니 아래와 같은 에러가 발생했다...
org.springframework.orm.jpa.JpaSystemException: Could not set field
value [POST_INSERT_INDICATOR] value by reflection
먼저 해결방법 부터 쉽게 말하자면
복합키와 @EmbeddedId
에서는 @GeneratedValue
를 못 쓴다고 합니다.
호호호호...
근데 아무것도 몰랐을 떄는
@GeneratedValue(strategy = GenerationType.AUTO)
해서 돌아가서 돌아가는 줄 알았는데
실제로 id값을 확인 해보면 id값이 null로 표시된다.
(근데 대체 왜 DB에 저장이 되는거지???)
최대한 안전하게 데이터베이스를 설계하려면 복합키보다는
대표ID(PK) 값을 설정해주는 것이 낫다고 하더라고요
복합키를 구성할 떄는
특정 데이터를 식별하는 게 의미가 없는 도메인 일때 구성해준다고 하더라고요.
예) 걸음거리 기록 저장.
복합키는 대표ID 에 비해서는 자원적인 성능도 그렇고
Unique 하게 이루어지게 만들어야 하기때문에
생각할 거리가 많아지는 것 같습니다.
진짜 공부할수록 그리고 프로젝트 할 수록
JPA 랑 DB에 대해서 1도 모르는거 같습니다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
DB 설계 쉬운놈이 아니였습니다.
정복할때까지 공부 가즈아!!
흑흑 파면팔수록 계속나오는 JPA, DBㅠㅠ 정복공부 가즈아,,,!!!