1. 개요
김영한 님의 '자바 ORM 표준 JPA 프로그래밍 - 기본편' 을 들으면서 정리하는 포스팅입니다.
https://www.inflearn.com/course/ORM-JPA-Basic
자바 ORM 표준 JPA 프로그래밍 - 기본편 강의 | 김영한 - 인프런
김영한 | JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., 실무에서도
www.inflearn.com
2. 기본키 매핑 @Id
- Entity에는 반드시 PK가 필요하다.
- PK를 매핑할 때 Entity 필드에 @Id를 붙혀주면 된다.
@Entity
public class Member {
@Id private String userId; // 기본키 정의
// 필드 정의 ...
}
3. 기본키 할당 전략
기본키를 할당 전략은 '직접할당방식', '자동생성방식' 두 가지 전략이 있다.
a. 직접 할당 방식
직접할당 방식은 애플리케이션 내에서 PK에 해당하는 필드를 Setter, 생성자 등을 통해 직접 할당하는 방식이다.
@Entity
public class Member {
@Id @Setter private String userId; // 기본키 정의
// 기타 필드 정의..
}
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Member member = new Member();
member.setUserId("member1"); // 기본키 직접 할당
em.persist(member);
b. 자동 생성 방식 @GeneratedValue
자동생성방식은 대리키를 사용하는 방식으로 IDENTITY, SEQUENCE, TABLE, AUTO 4가지 방식이 있다.
자동생성방식은 MySQL에서 AUTO_INCREMENT 를 떠올리면 이해하기 쉽다.
4. PK 자동 생성 방식 4가지
a. IDENTITY 전략
기본키 생성 방식을 DB에 위임하는 방식이다.
MySQL, PostgreSQL, SQL Server 등에서 사용할 수 있다.(예: MySQL에서 AUTO_INCREMENT)
작동 방식
- PK는 데이터베이스가 자동으로 생성한다.(쿼리만 날리면 DB에서 알아서 PK를 할당한다)
- Entity는 반드시 PK를 알아야 하기 때문에 em.persist(o) 호출 시 즉시, SQL Insert 쿼리를 실행하여 DB로부터 생성된 PK를 가져오는 방식으로 동작한다. => 쓰기 지연이 동작하지 않으므로 배치 처리 불가능하다.
사용 예시
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
// 생성자, Setter 등
}
DDL 자동 생성 결과(MySQL)
b. SEQUENCE 전략
- DB Sequence를 사용해 기본키를 할당하는 방식이다.
- Sequence는 유일한 값을 순서대로 생성하는 DB 오브젝트이다.(기본키를 관리하는 테이블이라고 생각하자.)
- IDENTITY 방식과 다르게 Insert 하기 전에 시퀀스를 조회해서 PK 값을 알 수 있기 때문에 쓰기 지연이 가능하다.
- 시퀀스를 미리 선점하여 여러 JVM에서 동작해도 기본키가 충돌하지 않는다.
- Oracle, PostgreSQL, DB2, H2 데이터베이스에서 사용할 수 있다.
작동 방식
- JPA가 Entity의 PK가 필요할 때, DB 시퀀스 오브젝트에서 현재 값을 가져온다.
- 예: 현재 시퀀스 값이 1 이라고 가정
- allocationSize 만큼 DB 시퀀스 오브젝트의 현재 값을 증가시켜 업데이트 한다.
- 예: allocationSize가 50이면 시퀀스의 현재값을 50만큼 증가시켜 51 로 업데이트
- JPA는 할당된 범위(1~50) 의 값을 메모리에 보관해두고, 필요할 때 꺼내서 사용한다.
- DB 호출 횟수를 줄일 수 있어 성능 최적화 가능
3번의 Insert 쿼리를 진행할 때 JPA 쿼리 결과
- allocationSize가 1일 경우 메모리에 할당된 PK 값이 하나뿐이므로 Insert를 진행할 때 마다 시퀀스를 조회하여 PK를 할당해준다.
- allocationSize가 50일 경우 할당된(1~50)까지 시퀀스를 메모리에 꺼내서 PK에 할당한다.
@SequenceGenerator 속성
속성 | 설명 | 기본값 |
name | 식별자 생성기 이름 | 필수 |
sequenceName | DB에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시 초기값 지정 | 1 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) | 50 |
catalog, schema | DB 스키마, 카탈로그 이름 |
사용 예시
@SequenceGenerator(
name = "member_seq_generator",
sequenceName = "member_seq",
initialValue = 1,
allocationSize = 50
)
@Entity
public class Member {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "member_seq_generator"
)
private Long id;
private String username;
// 생성자 및 Setter 등
}
DDL 자동 생성 결과(H2 Database)
c. TABLE 전략
- 키 생성 전용 테이블을 하나 만들어서 DB 시퀀스를 흉내내는 전략
- 테이블을 이용하는 방식이기 때문에 모든 DB에 적용 가능한 방법이다.
- 테이블로부터 시퀀스를 할당받기 때문에 추가적으로 Update 쿼리가 발생한다는 점에서 시퀀스 전략보다 성능은 좋지 않다. (시퀀스를 지원하지 않는 DB에서 사용하는게 좋을 것 같다.)
작동 방식
- 시퀀스 전략과 동작방식은 유사하다.
- 시퀀스를 할당 받을 때 추가적으로 Update 쿼리가 실행된다는 점에서 차이가 있다.
TABLE 전략과 SEQUENCEPA 전략 쿼리 결과 차이
- TABLE 전략은 현재 시퀀스 값을 조회한 다음 allocationSize만큼 증가한 값만큼 UPDATE 쿼리를 실행한다.
- SEQUENCE 전략은 단순 시퀀스만 조회를 하기 때문에 UPDATE 쿼리를 실행하지 않는다.
@TableGenerator 속성
속성 | 설명 | 기본값 |
name | 식별자 생성기 이름 | 필수 |
table | 키생성 테이블 명 | hibernate_sequences |
pkColumnName | 시퀀스 컬럼명 | sequence_name |
valueColumnNa | 시퀀스 값 컬럼명 | next_val |
pkColumnValue | 키로 사용할 값 이름 | 엔티티 이름 |
initialValue | 초기값, 마지막으로 생성된 값이 기준 | 0 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) | 50 |
catalog, schema | DB 카탈로그, 스키마 이름 | |
uniqueConstraint | 유니크 제약 조건 |
사용 예시
@TableGenerator(
name = "member_seq_generator",
table = "sequence_table",
pkColumnName = "member_seq",
valueColumnName = "member_next_val",
allocationSize = 50
)
@Entity
public class Member {
@Id
@GeneratedValue(
strategy = GenerationType.TABLE,
generator = "member_seq_generator"
)
private Long id;
private String username;
// 생성자 및 Setter 등 ..
}
DDL 자동 생성(H2 Database)
d. AUTO 전략
- DB 방언에 따라 자동으로 IDENTITY, SEQUENCE, TABLE 전략을 선택한다.
- DB를 변경해도 코드를 따로 수정할 필요가 없다.
- 키 생성 전략이 정해지지 않은 개발 초기 단계에 사용하면 편리하다.
- 실제 운영 환경에서는 권장하지 않는다.
'Programming > Java' 카테고리의 다른 글
[JPA] JPA에서 DB 슈퍼-서브 타입 구현하는 방법 (0) | 2024.12.20 |
---|---|
[JPA] Entity 연관 관계 매핑(단방향/양방향, 연관관계주인, 다중성) (0) | 2024.12.13 |
[JPA] Entity 매핑과 DDL 자동 생성 옵션 정리 (0) | 2024.12.12 |
[JPA] JPA 영속성 컨텍스트와 Entity 상태(비영속, 영속, 준영속, 삭제) (1) | 2024.12.06 |
[Java] ProcessBuilder로 시스템 명령어 수행하기 (0) | 2024.10.08 |