@Id
@Entity에 기본키 칼럼을 선언하려면 @Id를 사용합니다.
기본키를 직접 할당하려면 @Id만 적어준 뒤 코드에서 직접 set을 해주면 됩니다. 데이터베이스에서 자동으로 생성하게 하려면 @GeneratedValue를 사용해야 합니다.
@GeneratedValue는 IDENTITY, SEQUENCE, TABLE 3가지 방식이 있습니다. 원하는 방식을 @GenerateValue의 strategy 속성으로 입력해줍니다.
strategy 속성을 적지 않고 @GeneratedValue만 쓰면 GenerationType.AUTO가 적용되고, JPA에서 데이터베이스에 맞는 자동생성 전략을 선택합니다. (MYSQL은 IDENTITY, 오라클은 SEQUENCE)
@Entity
public class Customer{
@Id
@GeneratedValue
private Long id;
private String name;
}
GenerationType.IDENTITY
IDENTITY는 기본키 생성을 데이터베이스에게 모두 맡겨버리는 방식입니다. MySql, PostgreSQL, SQL Server 등에서 사용합니다.
IDENTITY로 설정하면, MYSql은 기본키에 AUTO_INCREMENT 조건을 설정합니다. 그러면 데이터베이스에서 1부터 순차적으로 1씩 증가하는 기본키를 생성해줍니다.
CREATE TABLE CUSTOMER (
ID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
NAME VARCHAR(20)
);
@Entity
public class Customer{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
IDENTITY 전략을 사용하면 객체를 생성, 또는 저장한 뒤 ID값을 가져오기 위해 데이터베이스를 추가로 조회하는 작업을 합니다.
Customer customer = new Customer("manta");
em.persist(customer);
System.out.printIn("customer.getId() = " + customer.getId())
customer.getId() = 1
GenerationType.SEQUENCE
SEQUENCE는 지정한 규칙에 따라 값이 일정하게 증가하는 데이터베이스 오브젝트입니다. 예를 들어 1000부터 3씩 증가한다는 규칙을 시퀀스로 생성할 수 있습니다. 이 전략은 시퀀스를 지원하는 오라클, PostgreSQL등에서 사용합니다.
generator 속성으로 사용할 시퀀스 오브젝트 이름을 기입해주어야 합니다.
CREATE SEQUENCE customers_seq
START WITH 1000
INCREMENT BY 1
NOCACHE
NOCYCLE;
@Entity
@SequenceGenerator(
name="customers_seq", sequenceName="customers_seq", initialValue=100, allocationSize=1
)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "customer_seq")
private Long id;
}
* 시퀀스를 jpa에서 생성해주려면 @SequenceGenerator를 사용합니다.
SEQUENCE 전략은 IDENTITY와 반대로, 데이터베이스에서 식별자를 조회하여 엔티티에 할당합니다. 엔티티는 영속성 컨텍스트에 저장되고, 트랜잭션 커밋이 일어날 때 엔티티가 데이터베이스에 저장됩니다.
GenerationType.TABLE
TABLE은 채번테이블을 사용하는 전략입니다. 모든 데이터베이스에서 사용할 수 있습니다.
@TableGenerator를 사용해 사용할 채번 전략을 조회(설정)합니다.
@Entity
@TableGenerator(name = "customer_seq", table = "seq_table",
pkColumnName = "name",
valueColumnName = "value",
pkColumnValue="task_gen",
initialValue=1000,
allocationSize=10)
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "customer_seq")
private Long id;
}
속성명 | 설명 |
name | 채번 전략 이름, @GeneratedValue의 generator 속성에 name값을 넣어줍니다. |
table | 채번 전략 정보가 저장되어 있는 테이블명 (채번 테이블) |
pkColumnName | 채번 테이블의 pk 칼럼 명 |
valueColumnName | 시퀀스 값 (max, 최종값) 칼럼 명 |
pkColumnValue | 채번 규칙을 조회할 key (채번 전략 ID) |
initialValue | 초기값, 마지막으로 생성된 값이 기준 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수 |
TABLE 전략은 시퀀스 값을 조회하기 위해 SELECT를, 다음 값으로 증가시키기 위해 UPDATE를 발생시킵니다. 때문에 다른 전략에 비해 데이터베이스와의 통신횟수가 많습니다. 또 테이블을 사용하기 때문에, 트랜잭션이 끝날 때까지 테이블에 LOCK이 걸리는 등의 성능이슈가 발생할 수 있습니다.
TABLE 전략에서 성능이슈를 해결하기 위해서 사용하는 설정값이 allocationSize 입니다. 예를들어 allocationSize가 10이라면, 시퀀스가 한번 호출된 후 트랜잭션 내부에서 Entity를 10개를 생성하는 동안 (seq_nbr이 10까지 늘어나는 동안), 채번 테이블을 select하고 update하는 동작이 일어나지 않게 됩니다. 10을 넘어가게 되면, 다시 채번 테이블을 조회합니다.
Customer customerA = new Customer("aaa");
Customer customerB = new Customer("bbb");
Customer customerC = new Customer("ccc");
* allocationSize = 10, 이므로 고객을 3명 생성하지만 채번 테이블은 처음에 1번만 조회하고 update 합니다.
참고자료
- 김영한, 자바 ORM 표준 JPA 프로그래맹, 에이콘
- 김영한, 자바 ORM 표준 JPA 프로그래밍 - 기본편, 인프런
- https://www.baeldung.com/jpa-strategies-when-set-primary-key
'JAVA > JPA' 카테고리의 다른 글
[Querydsl] fetch 결과 조회 (0) | 2022.03.25 |
---|