객체와 테이블 매핑
객체는 @Entity, 테이블은 @Table 어노테이션을 사용한다.
Entity는 우리가 관리해야할 객체, 즉 클래스임을 나타낸다.
Table은 지정한 엔티티와 DB에 매핑할 테이블을 지정한다.
Table에 따로 name을 설정해주지 않으면 엔티티 이름을 그대로 사용한다.
예로 Member 클래스를 엔티티로 지정하고, name을 따로 설정하지 않았을 때,
DB에 Member라는 테이블이 만들어지고, Java의 Member 클래스와 매핑한다.
DB 스키마 자동 생성
JPA를 배우면서 처음으로 놀랬던 일이었다.
자바 코드만 작성한다면 JPA가 자체적으로 쿼리를 생성하여 테이블을 만들어주는 것이
매우 신기했다..
하지만 해당 기능은 "운영 서버"에서는 절대 사용하면 안된다고 하셨다.
DDL(Data Definition Language)을 자동 생성해준다고 할 수 있는데
DDL은 "DB 개체의 구조를 만들고 수정하는데 사용하는 언어"라고 한다.
DDL을 생성하는데 5가지 옵션이 있다.
create, create-drop, update, validate, none
create
- 애플리케이션이 시작될 때, 존재하는 테이블을 삭제하고 다시 생성한다.
create-drop
- 종료시점에 drop을 한다. create와 차이점은 애플리케이션이 종료되면 create는 data가 저장되어 있지만, drop은 애플리케이션 종료시점에 drop하기 때문에 data가 존재하지 않게 된다.
update
- 변경된 부분만 반영한다.
validate
- 현재 엔티티와 테이블이 맞게 매핑되었는지 확인한다.
none
- 아무것도 안한다.
이와 같은 옵션을 사용하면
요렇게 DDL을 생성해준다.
이 부분이 정말 신기했다!!
필드와 컬럼 매핑
@Column
- java에서 사용하는 변수를 DB에 사용되는 column에 매핑한다.
- nullable, unique, length 등 다양한 제약조건들을 설정할 수 있다. 만약 nullable에 false를 설정하면 DDL 생성할 때 not null 제약조건이 붙게 된다.
@Enumerated
- DB에는 enum 타입이 없다. 그래서 enum 타입을 매핑한다는 어노테이션 사용해야한다.
- 속성에 ORDINAL, STRING 이 있다. ORDINAL은 enum 순서대로, STRING은 enum 이름을 DB에 저장하게 된다.
- ORDINAL을 사용할 시 GUEST, ADMIN 으로 저장되어 있으면 GUEST는 0, ADMIN은 1로 저장된다. 하지만 USER가 추가 되어 USER, GUEST, ADMIN으로 저장하고 다음에 USER를 추가했을 때, USER는 0으로 저장된다. 이미 DB에는 GUEST가 0으로 저장되어 아주 큰 혼란을 겪게 될 수 있으므로 대부분 STRING을 사용하는 것이 좋다고 한다.
@Temporal
- 날짜 타입에 사용하기 위함이다.
- TemporalType은 DATE/TIME/TIMESTAMP 총 3가지 type이 있다. JAVA의 LocalDate, LocalDateTime을 사용하면 어노테이션 생략이 가능한 것을 볼 수 있다.
@Lob
- varchar를 넘어서는 큰 컨텐츠를 넣고 싶을 때 사용한다.
@Transient
- 자바 메모리에서만 사용하고 DB 컬럼에는 매핑되지 않는다. create 쿼리를 보면 temp라는 변수는 존재하지 않는 것을 알 수 있다.
기본 키 매핑
@Id
- id를 직접 할당할 때 사용
@GeneratedValue
- 오라클은 sequence, mysql은 auto-increment 사용
- id를 DB가 자동 생성해줌
IDENTITY & SEQUENCE 전략
IDENTITY 전략은 기본 키 생성을 DB에 위임하는 것이다.
예로 mysql의 auto_increment가 있다.
하지만 영속화하려면 기본키가 필요한데 해당 전략은
DB에 data를 넣어야 기본 키를 받게 된다.
그래서 identity 전략에서는 특이하게 persist 시점에 쿼리가 나가게 된다. (원래 commit하는 시점에 쿼리가 나간다고 함)
즉, 쓰기 지연 SQL 저장소에 쿼리를 넣지 않고 바로 DB에 쿼리를 날린다.
sequence 전략은 DB에 next value 값을 가져온 뒤,
persist할 때, 값을 넣어준다. 그리고 나서 영속 컨텍스트에 저장한다.
identity와 다르게 버퍼링(쓰기 지연 SQL 사용)이 가능하게 된다.
Sequence 전략에는 최적화 방법으로 allocationSize 옵션이 있다.
해당 옵션은 할당된 숫자만큼 DB에서 미리 땡겨와 메모리에 저장하고,
기본 키를 할당할 때 메모리에서 next value 값을 얻는다.
따라서 DB에 접근하는 횟수를 줄여 최적화할 수 있다.
allcoationSize가 1일 때와 50일 때를 보면 next value의 횟수가 확연히 차이난다.
50일 때는 총 3번의 persist가 일어나도 2번의 next value가 호출된다.
이 때, 2번의 next value가 호출되는 이유는
allcoationSize가 50인데 처음 next value을 호출하면 51값이 나와야하는데 1인 값이 나오게 된다.
그래서 오류로 판단하여 allcoationSize를 한번 더 호출하는 모습이다.
allcoation이 1일 때는 persist 할 때마다 next value가 요청된 것을 알 수 있다.
Reference
https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0_%EC%A0%95%EC%9D%98_%EC%96%B8%EC%96%B4
자바 ORM 표준 JPA 프로그래밍(김영한 지음)
'Spring 강의 > JPA - 기본편' 카테고리의 다른 글
고급 매핑 (0) | 2021.12.07 |
---|---|
다양한 연관관계 매핑 (0) | 2021.12.02 |
연관관계 매핑 기초 (0) | 2021.11.29 |
영속성 관리 - 내부 동작 방식 (0) | 2021.11.19 |
JPA 시작하기 (0) | 2021.11.17 |