데이터베이스 테이블의 기본 키(PK)와 객체의 필드를 매핑시켜주는 어노테이션이다.
적용가능한 타입
적용가능한 타입은 아래와 같다.
@Id
만 사용할 경우 기본 키(PK)를 직접 할당해주어야 한다.
기본키를 직접 할당하는 대신 데이터베이스가 생성해주는 값을 사용하려면 @GeneratedValue
를 사용하면 된다.
@Generated
어노테이션이 아님을 주의하자.
만약 @ID
만 사용하면서 PK값을 직접 할당하지 않는 경우 아래의 에러가 발생한다.
[Error] ids for this class must be manually assigned before calling save()
nested exception is org.hibernate.id.IdentifierGenerationException: ids for this class must be manually assigned before calling save(): backend.core.domain.Staff
해당 에러의 발생 원인은 EntityManage.save()
함수를 호출하기 전에 id값이 설정되어 있어야 하는데, 그렇지 않아서이다.
기본 키를 자동으로 생성해주는 어노테이션이다.
속성으로 strategy
가 있으며 이를 통해 자동 생성 전략을 지정해줄 수 있다.
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Facility {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "facility_id")
private Long id;
@OneToMany(mappedBy = "facility")
private List<RoomFacility> roomFacilities;
}
@GeneratedValue(strategy = GenerationType.IDENTITY
IDENTITY
전략은 기본 키 생성을 데이터베이스에 위임하는 전략이다.
주로 MySQL, PostgreSQL, SQL Server에서 사용한다.
데이터베이스의 AUTO_INCREMENT
기능을 통해 데이터베이스가 기본 키를 자동으로 생성해준다.
IDENTITY
전략은 AUTO_INCREMENT
처럼 데이터베이스에 값을 저장하고 나서 기본 키 값을 구할 수 있을 때 사용한다.
주의점
엔티티가 영속 상태가 되기 위해선 식별자가 꼭 필요하다.
IDENTITY
전략을 사용하면 식별자를 데이터베이스에서 지정하기 전까지 알 수 없기에 em.persist()
를 하는 즉시 INSERT SQL이 데이터베이스에 전달된다.
즉 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ",
initialValue = 1,
allocationSize = 1
)
public class Facility {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR")
@Column(name = "facility_id")
private Long id;
@OneToMany(mappedBy = "facility")
private List<RoomFacility> roomFacilities;
}
@GeneratedValue(strategy = GenerationType.SEQUENCE
데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 데이터베이스 오브젝트이다.
SEQUENCE
전략은 이 시퀀스를 사용해서 기본 키를 생성한다.
해당 전략은 오라클, PostgerSQL, H2 데이터베이스에서 사용할 수 있다.
시퀀스 전략을 사용하기 위해서 우선 사용할 데이터베이스 시퀀스를 매핑해야 한다.
@SequenceGenerator
를 사용해 시퀀스 생성기를 등록한 후, @GeneratedValue
의 generator 속성으로 시퀀스 생성기를 선택한다.
@SequenceGenerator
속성은 아래의 표와 같다.
IDENTITY와의 차이점
SEQUENCE
전략은 em.persist()
를 호출할 때 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회한다.
그리고 조회한 식별자를 엔티티에 할당한 후 해당 엔티티를 영속성 컨텍스트에 저장한다.
다음으로 트랜잭션 커밋 시점에 flush
가 발생하면 엔티티를 데이터베이스에 저장한다.
IDENTITY
`전략은 먼저 엔티티를 데이터베이스에 저장한 후에 식별자를 조회하여, 엔티티의 식별자에 할당 한다.
그 후 영속성 컨텍스트에 저장한다.
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
table = "MY_SEQUENCE",
sequenceName = "BOARD_SEQ",
initialValue = 1,
allocationSize = 1
)
public class Facility {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR")
@Column(name = "facility_id")
private Long id;
@OneToMany(mappedBy = "facility")
private List<RoomFacility> roomFacilities;
}
SELECT * FROM MY_SEQUENCE
를 하면 BOARD_SEQ 컬럽과 NEXT_VAL이 나타난다.
TABLE
전략은 시퀀스 대신 테이블을 사용한다는 것 이외에 SEQUENCE
전략과 동작하는 방식이 같다.
@TableGenerator
속성은 아래의 표와 같다.
데이터베이스는 종류도 많고 데이터베이스의 종류에 따라 기본키를 만드는 방법도 다양하다.
AUTO
로 설정하면 데이터베이스 방언에 따라 IDENTITY
, SEQUENCE
, TABLE
전략 중 하나를 자동으로 선택한다.
@GeneratedValue
의 strategy의 기본값은 AUTO
이다.
주의점
AUTO
를 사용할 때 SEQUENCE
, TABLE
전략이 선택되면 시퀀스나 키 생성용 테이블을 미리 만들어야 한다.
만약 ddl-auto
(스키마 자동 생성 기능)를 사용한다면, 하이버네이트가 기본값을 사용해서 적절하게 생성한다.
SEQUENCE
, TABLE
전략의 최적화 방법도 존재한다.