자바 ORM 표준 JPA 프로그래밍 : 교보문고
자바 ORM 표준 JPA 프로그래밍 - 기본편 : 인프런
블로그 참조!
이전에 Pesistence Context 내부에 1 차 Cache 에 대해서 공부했었다. 1차 Cache 에 Entity 를 저장하려면 @Id 값이 필요하다.
@Entity로 선언된 Entity 의 Id 를 할당하는 방법에 대해서 알아보자
Entity 의 Id 값임을 선언하는 Annotation 이며
Table 의 PK 와 객체의 필드를 매핑시켜주는 역할
package org.example.javamain.Entity;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Member2
{
@Id
private String str_id;
private String name;
public String getStr_id() {
return str_id;
}
public void setStr_id(String str_id) {
this.str_id = str_id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity
public class Member2
{
@Id
private String str_id;
Member2 member2 = new Member2();
member2.setStr_id("number1");
member2.setName("a");
em.persist(member2);
Id 값을 직접 입력할 수 있다.
DB에서는 PRIMARY KEY 값을 자동으로 할당해주는 기능을 사용한다.
이러한 기능들을 사용하기 위해서 JPA 에서는 @GeneratedValue 를 사용한다.
영속성 관리 대상의 Entity 의 @Id 로 선언된 필드위에 위치하며
PK 값에 대한 생성 전략을 제공한다.
AUTO, IDENTITY, SEQUENCE, TABLE
strategy 속성값을 사용하며 기본값은 AUTO 이다.@GeneratedValue
@Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface GeneratedValue { GenerationType strategy() default GenerationType.AUTO; String generator() default ""; }
GenerationType
public enum GenerationType { TABLE, SEQUENCE, IDENTITY, AUTO; private GenerationType() { } }
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String str_id;
Dialect
설정 값에 따라
나머지 전략들 중 자동으로 선택한다.
AUTO
사용 시SEQUENCE
,TABLE
전략으로 선택이 되는 것을 고려하여
SEQUENCE 혹은 KEY 생성 TABLE 을 미리 만들어야 할 수 있으니
사용하기전 확인이 필수다
GenerationType.IDENTITY
MySql, PostgreSQL, SQL Server, DB2 에서 사용하며
PK 생성을 DB에 위임하는 전략이다.
DB에서 PK 값 할당을 위임하는 방식이기 때문에 PK 를 DB 에 데이터가
INSERT
되어야 알 수 있다.Persistence Context
에서 Entity 를 영속화 하려면1차 캐시
에
Entity 가 저장이 되어야하고 이때key 값이 @Id 로 선언된 필드
값이기 때문에
1차 캐시에 저장할 수 없고 영속화 시키지 못 한다.
그래서Transaction
이 커밋 되어야 DB 에 Query 를 보내는 것이 아닌 영속화 시킬 때[EntityManager 의 persist()]
Query 가 발생하고 그 결과를 1차 Cache 에 저장한다.
영속화 할때 Query 가 발생함으로 쓰기 지연은 IDENTITY 전략일 때 사용하지 못한다.main
try { Member2 member2 = new Member2(); member2.setName("a"); System.out.println(":::::: BEFORE PERSIST ::::::"); em.persist(member2); System.out.println("member2.getId() : "+member2.getId()); System.out.println(":::::: AFTER PERSIST ::::::"); }
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
DB Sequence 를 사용하여 PK 를 할당하는 방식이다.
이때 Id의 데이터 타입은 는 Long 으로 사용하는 것을 권장한다
ORACLE, PostgreS!L, H2 등에서 사용할 수 있다.
참고로 DB Sequence 는 DB 에서 유일한 값을 순차적으로 생성하는 DB Object 이다.
@Entity
@SequenceGenerator(
name = "TEST_SEQUENCE", // SequenceGenerator 이름
sequenceName = "MEMBER2_SEQ", // Sequence 이름
initialValue = 1, // Table 정의할 때 첫째 값
allocationSize = 1 // 한번 호출 시 증가하는 Sequence
)
public class Member2
{
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TEST_SEQUENCE")
private Long id;
@SequenceGenerator 를 사용하여 Sequence 를 생성하여 사용할 수 있다. Sequence 역시 DB 에서 관리하고
Entity 가 영속화 되기 이전에 sequence 값을 가져온다 ( persist 호출 시 )
sequence object 에서 sequence 를 들고 올 때allocationSize 만큼 sequence 를 들고 오기 때문에 성능 최적화를 할 수 있다.
Member2 member1 = new Member2();
member1.setName("A");
Member2 member2 = new Member2();
member1.setName("B");
Member2 member3 = new Member2();
member1.setName("C");
em.persist(member1);
em.persist(member2);
em.persist(member3);
System.out.println("member1 : "+member1.getId());
System.out.println("member2 : "+member2.getId());
System.out.println("member3 : "+member3.getId());
et.commit();
들고온 sequence 들은 memory 에서 관리
PID 생성을 위한 Table 을 미리 생성하여 DB sequence 처럼 사용한다.
모든 DB 에 적용이 가능
하다는 장점이 있지만
성능 저하
문제를 가지고 있다.@Entity @TableGenerator( name = "Table_SEQ_GEN", table = "SEQ_T", pkColumnValue = "MEMBER2_SEQ", allocationSize = 1 ) public class Member2 { @Id @GeneratedValue( strategy = GenerationType.TABLE, generator = "Table_SEQ_GEN" ) private Long id;