이 카테고리는 인프런 김영한님의 JPA 강의를 보고 정리하는 공간입니다.
@Entity
- @Entity 어노테이션이 붙은 클래스는 JPA가 관리한다. 이를 엔티티라고 한다.
- 이 엔티티와 데이터베이스의 테이블이 매핑된다.
- 엔티티 클래스에는 기본 생성자가 있어야한다.
- final 클래스, enum, interface, inner 클래스는 안된다.
- 저장할 필드에 final키워드는 안된다.
- name 속성을 사용하여 엔티티 이름을 커스터마이징 할 수 있다. (중복되는 이름의 클래스가 없다면 기본값 권장)
데이터베이스 스키마 자동 생성
- create: 기본 테이블 삭제 후 다시 생성(DROP + CREATE)
- create-drop: create와 같으나 애플리케이션 종료 시점에 DROP
- update: 변경사항만 반영(운영중인 DB에는 사용하면 안됨)
- validate: 엔티티와 테이블이 정상적으로 매핑됐는지만 확인
- none: 사용x
개발 초기에는 create나 update를,
테스트 서버에는 update나 validate를,
운영 서버에는 validate나 none을 권장한다.
필드와 컬럼 매핑
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Entity
public class Member {
@Id
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
}
- @Colunm: 해당 필드와 명시한 컬럼 매핑
- @Temporal: 날짜 타입 매핑
- @Enumerated: enum타입 매핑
- @Lob: 대용량 매핑, CLOB, BLOB이 있다.
- @Transient: 해당 필드는 매핑하지 않겠다.
여기서 Enumerated 매핑 사용시 EnumType.ORDINAL 옵션은 사용하지 않도록하자
이는 enum 순서를 데이터베이스에 저장하는 것으로 의미 자체도 모호하고 나중에 찾기 힘든 버그를 야기한다.
EnumType.STRING으로 하자. 이는 enum의 이름 그 자체를 데이터베이스에 저장한다.
기본키 매핑
직접할당과 자동생성이 있다.
직접 할당시 @Id를 통해 지정할 수 있다.
@Id
private Long id;
자동할당(@GenerateValue)는 4가지 종류가 있다.
- IDENTITY: 데이터베이스에 위임, MYSQL
- SEQUENCE: 데이터베이스 시퀀스 오브젝트 사용, ORACLE
- TABLE: 키 생성용 테이블 사용, 모든 DB에서 사용
- AUTO: 방언에 따라 자동 지정, 기본값
@GeneratedValue(strategy = GenerationType.[여기에전략])
private Long id;
IDENTITY 전략
- 기본키 생성을 DB에 위임 (ex. MySQL의 AUTO_INCREMENT)
영속성 컨텍스트에 persist할때, 우리는 Id와 Value를 알고있어야 한다.
하지만 DB에서 알아서 기본키를 생성하는데 코드를 짜는 우리가 이를 알 수는 없다. 그럼 어떻게 하느냐?
IDENTITY전략을 사용하면 트랜잭션 커밋 시점이 아닌 persist시점에 INSERT SQL이 실행된다.
그렇게해서 DB에서 식별자를 바로 조회할 수 있다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
SEQUENCE 전략
- 데이터베이스의 시퀀스 오브젝트 사용
- 이는 유한한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
- 오라클, PostgreSQL, DB2, H2에서 사용
이 전략 또한 DB에서 기본키 값을 부여해 주는 방식이므로 우리는 다음 기본키로 어떤 값이 올지 모른다.
즉, 이 전략도 영속성 컨텍스트에 영속화 시키기 전에 Id값을 미리 조회하는 추가적인 절차가 필요한 것이다.
SEQUENCE 전략에서는 persist하는 순간
이와 같이 DB로부터 다음 기본키 값을 받아온다.
그런데, 이렇게 INSERT 쿼리를 날리기 위해 추가적인 DB와의 통신이 늘어날수록 성능이 떨어지게 된다. 당연히도.
그렇다면 어떻게 개선할 수 있을까?
SeqenceGenerator의 allocationSize 옵션을 통해 개선이 가능하다.
이 옵션은 DB와 한번 통신 할때마다 시퀀스를 한번에 가져와놓을 수량을 지정할 수 있다. 예를들어 50이라고 해두면 50번에 한번씩만 시퀀스를 호출하는 작업을 해주면 된다.
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 50) //한번에 가져올 시퀀스 값 수량
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
private Long id;
TABLE 전략
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략.
- 장점은 모든 데이터베이스에 적용 가능하다는 점.
- 단점은 성능이 다소 떨어진다는 점.
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MY_SEQUENCE", //직접 만든 시퀀스 테이블을 매핑
pkColunmValue = "MEMBER_SEQ",
allocationSize = 50) //한번에 가져올 시퀀스 값 수량
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "MEMBER_SEQ_GENERATOR")
private Long id;
권장하는 식별자 전략
- 기본키 제약조건: null이 아니며 변하면 안된다.
- 이 조건을 미래까지 쭉 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자.
- 권장 형태: Long형 + 대체키 + 키 생성전략 사용
*대체키란,
후보키가 두개 이상일 경우 그 중에서 어느 하나를 기본키로 지정하고 남은 후보키들을 대체키라한다.
*후보키란,
테이블에서 각 행을 유일하게 식별할 수 있는 최소한의 속성들의 집합이다.
참고:
'JPA' 카테고리의 다른 글
[JPA] 다양한 연관관계 (2) | 2021.07.24 |
---|---|
[JPA] 연관관계 매핑 (0) | 2021.07.21 |
[JPA] 영속성 관리 (0) | 2021.07.17 |
[JPA] JPA란? (0) | 2021.07.15 |