1. 객체와 테이블 매핑
(1) @Entity
- JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다.
- @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라 부른다.
속성 | 기능 | 기본값 |
name | JPA에서 사용할 엔티티 이름을 지정한다. 보통 기본값인 클래스 이름을 사용한다. | 설정하지 않으면 클래스 이름을 그대로 사용한다. |
* @Entity 적용 시 주의사항
- 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
- 저장할 필드에는 final 사용할 수 없다.
(2) @Table
- @Table은 엔티티와 매핑할 테이블을 지정한다.
- 생략하면 매핑한 엔티티 이름을 테이블 이름으로 사용한다.
속성 | 기능 | 기본값 |
name | 매핑할 테이블 이름 | 엔티티 이름을 사용한다. |
catalog | catalog 기능이 있는 데이터베이스에서 catalog를 매핑한다. | |
schema | schema 기능이 있는 데이터베이스에서 schema를 매핑한다. | |
uniqueConstraints(DDL) | DDL 생성 시에 유니크 제약조건을 만든다. 2개 이상의 복합 유니크 제약조건도 만들 수 있다. 참고로 이 기능은 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용된다. |
2. 데이터베이스 스키마 자동 생성
- JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.
- 클래스의 매핑 정보를 보면 어떤 테이블에 어떤 컬럼을 사용하는지 알 수 있다.
- JPA는 매핑 정보와 데이터베이스 방언을 사용해서 데이터베이스 스키마를 생성한다.
(1) hibernate.hbm2ddl.auto 속성
<property name="hibernate.hbm2ddl.auto" value="create"/>
- persistence.xml에 다음 속성을 추가하면 데이터베이스 스키마가 자동으로 생성된다.
옵션 | 설명 |
create | 기존 테이블을 삭제하고 새로 생성한다. DROP + CREATE |
create-drop | create 속성에 추가로 애플리케이션을 종료할 때 생성한 DDL을 제거한다. DROP + CREATE + DROP |
update | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정한다. |
validate | 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리케이션을 실행하지 않는다. 이 설정은 DDL을 수정하지 않는다. |
none | 자동 생성 기능을 사용하지 않으려면 hibernate.hbm2ddl.auto 속성 자체를 삭제하거나 유효하지 않은 옵션 값을 주면 된다. (none은 유효하지 않은 옵션 값이다.) |
(2) HBM2DDL 주의사항
- 운영 장비에서는 절대 create, create-drop, update 사용하면 안 된다!
- 개발 초기 단계는 create 또는 update
- 테스트 서버는 update 또는 validate
- 스테이징과 운영 서버는 validate 또는 none
(3) DDL 생성 기능
//not null 제약조건과 문자의 크기를 지정할 수 있다.
@Column(name = "name", nullable = false, length = 10)
private String username;
//유니크 제약조건을 추가할 수 있다.
@Table(name = "MEMBER", uniqueConstraints = {@UniqueConstraint(
name = "NAME_AGE_UNIQUE",
columnNames = {"NAME", "AGE"}
)})
public class Member {
@Id
private Long id;
@Column(name = "name")
private String name;
private Integer age;
}
- 이런 기능들은 단지 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
- 스키마 자동 생성 기능을 사용하지 않고 직접 DDL을 만든다면 사용할 이유가 없다.
3. 필드와 컬럼 매핑
분류 | 매핑 어노테이션 | 설명 |
필드와 컬럼 매핑 | @Column | 컬럼을 매핑 |
@Enumerated | 자바의 enum 타입을 매핑 | |
@Temporal | 날자 타입을 매핑 | |
@Lob | BLOB, CLOB 타입을 매핑 | |
@Transient | 특정 필드를 데이터베이스에 매핑하지 않는다. | |
기타 | @Access | JPA가 엔티티에 접근하는 방식을 지정 |
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;
이와 같이 LocalDate를 사용하는 경우 @Temporal 매핑 어노테이션이 필요 없다.
(1) @Column
- @Column은 객체 필드를 테이블 컬럼에 매핑한다.
- name, nullable이 주로 사용되고 나머지는 잘 사용되지 않는다.
속성 | 기능 | 기본값 |
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable (거의 사용하지 않음) | 엔티티 저장시 이 필드도 같이 저장한다 false로 설정하면 이 필드는 데이터베이스에 저장하지 않는다. |
true |
updatable (거의 사용하지 않음) | 엔티티 수정 시 이 필드도 같이 수정 false로 설정하면 데이터베이스에 수정하지 않는다. |
true |
table (거의 사용하지 않음) | 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용. 지정한 필드를 다른 테이블에 매핑할 수 있다. | 현재 클래스가 매핑된 테이블 |
nullable(DDL) | null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다. | true |
unique(DDL) (사용하지않는다. @Table 속성을 사용해서 unique 기능을 사용한다.) |
@Table의 uniqueContraints와 같지만 한 칼럼에 간단히 유니크 제약조건을 걸 때 사용한다. 만약 두 컬럼 이상을 사용해서 유니크 제약조건을 사용하려면 클래스 레벨에서 @Table.uniqueConstraints를 사용해야 한다. | |
columnDefinition(DDL) | 데이터베이스 컬럼 정보를 직접 줄 수 있다. | 필드의 자바 타입과 방언 정보를 사용해서 적절한 컬럼 타입을 생성한다 |
lenght(DDL) | 문자 길이 제약조건, String 타입에만 사용 | 255 |
precision, scale(DDL) | BigDemical 타입에서 사용한다(BigInteger도 사용 할 수 있다). precision은 소수점을 포함한 전체 자릿수를 scale은 소수의 자릿수다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다. |
precision=19, scale=2 |
@Column(nullable = false)
private String data;
// data varchar(255) not null
@Column(columnDefinition = "varchar(100) default 'EMPTY'")
private String data;
// data varchar(100) default 'EMPTY'
@Column(length = 400)
private String data;
// data varchar(400)
@Column 생략
@Column을 생략하게 되면 어떻게 될까?
// 기본 타입에는 null 값을 입력할 수 없다.
int data1;
data1 integer not null //DDL
//객체 타입 일 때는 null 값이 허용된다.
Integer data2;
data2 integer //DDL
//
@Column
int data3
data3 integer //DDL
(2) @Enumerated
- 자바의 enum 타입을 매핑할 때 사용한다.
속성 | 기능 | 기본값 |
value | EnumType.ORDINAL: enum 순서를 데이터베이스에 저장 EnumType.STRING: enum 이름을 데이터베이스에 저장 |
EnumType.ORDINAL |
- EnumType.ORDINAL은 enum에 정의된 순서대로 ADMIN은 0, USER는 1 값이 데이터베이스에 저장된다.
- 장점 : 데이터베이스에 저장되는 데이터 크기가 작다
- 단점 : 이미 저장된 enum의 순서를 변경할 수 없다.
- EnumType.STRING은 enum 이름 그대로 ADMIN은 'ADMIN', USER는 'USER'라는 문자로 데이터베이스에 저장된다.
- 장점 : 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전하다.
- 단점 : 데이터베이스에 저장되는 데이터 크기가 ORDINAL에 비해서 크다.
- OREINAL의 단점의 영향이 크기 때문에 항상 EnumType.STRING을 사용한다.
public enum OrderStatus {
ORDER, CANCEL;
}
@Enumerated(EnumType.STRING)
private OrderStatus status;
(3) @Temporal
- 날짜 타입(java.util.Date, java.util.Calendar)를 매핑할 때 사용한다.
속성 | 기능 | 기본값 |
value | Temporal.DATE : 날짜, 데이터베이스 date 타입과 매핑 TemperalType.TIME : 시간, 데이터베이스 time 타입과 매핑 TemperalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 |
TemporalType은 필수로 지정해야 한다. |
@Temporal(TemporalType.DATE) // (ex : 2013-10-11)
private Date date;
@Temporal(TemporalType.TIME) // (ex : 11:11:11)
private Date time;
@Temporal(TemporalType.TIMESTAMP) // (ex : 2013-10-11 11:11:11)
private Date timestamp;
//==생성된 DDL==/
date date,
time time,
timestamp timestamp
- 자바의 Date 타입에는 년월일 시분초가 있지만 데이터베이스에는 date, time, timestamp(날짜와 시간)라는 세 가지 타입이 별도로 존재한다.
- @Temporal을 생략하면 자바의 Date와 가장 유사한 DDL이 생성된다.
- datetime : MYSQL
- timestamp : H2, 오라클, PostgreSQL
import java.time.LocalDate;
import java.time.LocalDateTime;
java.time 패키지의 LocalDate와 LocalDateTime을 사용할 때는 @Temperal 어노테이션이 필요 없다.
private LocalDate testLocalDate;
private LocalDateTime testLocalDateTime;
(4) @Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑한다.
- @Lob에는 지정할 수 있는 속성이 없다.
- 매핑하는 필드 타입이 문자는 CLOB으로 매핑
- CLOB : String, char[], java.sql.CLOB
- BLOB : byte[], java.sql.BLOB
@Lob
private String lobString;
@Lob
private byte[] lobByte;
//오라클
lobString clob;
lobByte blob;
//MySQL
lobString longtext,
lobByte longblob,
(5) @Transient
- "이 필드는 매핑하지 않는다"를 선언해 준다.
- 데이터베이스에 저장하지 않고 조회하지도 않는다.
@Transient
private int temp;
4. 기본 키 매핑
- 직접 할당 : 기본 키를 애플리케이션에서 직접 할당한다.
- @Id 어노테이션만 사용하고 개발자가 직접 할당한다.
- 자동 생성 : 대리 키 사용 방식 - @GeneratedValue 어노테이션을 추가해야 한다.
- IDENTITY : 기본 키 생성을 데이터베이스에 위임한다.
- SEQUENCE : 데이터베이스 시퀀스를 사용해서 기본 키를 할당한다.
- TABLE : 키 생성 테이블을 사용한다.
(1) 기본 키 직접 할당 전략
- @Id로 매핑한다.
- @Id 적용 가능 자바 타입
- 자바 기본형
- 자바 래퍼형(Wrapper)
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
@Id
private Long id;
Board board = new Board();
board.setId(1L);
em.persist(board);
(2) IDENTITY 전략
- 기본 키 생성을 데이터베이스에 위임하는 전략
- MySQL, PostgreSQL, SQL Server, DB2에서 사용한다.
- MySQL의 AUTO_INCREMENT 기능은 데이터베이스가 기본 키를 자동으로 생성해준다.
- IDENTITY 전략은 AUTO_INCREMENT를 사용하여 데이터베이스에 값을 저장하고 나서야 기본 키 값을 구한다.
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private static void logic(EntityManager em) {
Member member = new Member();
em.persist(member);
System.out.println(member.getId());
}
- 엔티티가 영속 상태가 되려면 식별자가 반드시 필요하다.
- 하지만 IDENTITY 식별자 생성 전략은 엔티티를 데이터베이스에 저장해야 식별자를 구할 수 있으므로 em.persist()를 호출하는 즉시 INSERT SQL이 데이터베이스에 전달된다.
- 이 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
(3) SEQUENCE 전략
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
- SEQUENCE 전략은 이 시퀀스를 사용해서 기본 키를 생성한다.
- 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용할 수 있다.
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1
)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "BOARD_SEQ_GENERATOR")
private Long id;
}
- 데이터베이스 시퀀스를 매핑한다.
- @SequenceGenerator를 사용해서 BOARD_SEQ_GENERATOR라는 시퀀스 생성기를 등록
- sequenceName 속성의 이름으로 BOARD_SEQ를 지정
- JPA는 이 시퀀스 생성기를 데이터베이스의 BOARD_SEQ 시퀀스와 매핑한다.
- SEQUENCE 전략은 em.persist()를 호출할 때 먼저 데이터베이스 시퀀스를 사용해서 식별자를 조회한다.
- em.persist() 호출 시 "call next value for BOARD_SEQ" 쿼리가 나간다.
*SequenceGenerator 속성 정리
속성 | 기능 | 기본값 |
name | 식별자 생성기 이름 | 필수 |
sequenceName | 데이터베이스에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시에만 사용됨. 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정한다. | 1 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용된다.) | 50 |
catalog, schema | 데이터베이스 catalog, schema 이름 |
(4) TABLE 전략
- TABLE 전략은 키 생성 전용 테이블을 하나 만들고 여기에 이름과 값으로 사용할 컬럼을 만들어 데이터베이스 시퀀스를 흉내 내는 전략이다.
- 이 전략은 테이블을 사용하므로 모든 데이터베이스에 적용할 수 있다.
- 실무에서 잘 사용하지 않는다.
(5) AUTO 전략
- GenrerationType.AUTO는 선택한 데이터베이스 방언에 따라 IDENTITY, SEQUENCE, TABLE 전략 중 하나를 자동으로 선택한다.
- 오라클 : SEQUENCE
- MySQL : IDENTITY
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
}
- @GeneratedValue.strategy의 기본값은 AUTO이다.
- strategy = GenerationType.AUTO 생략 가능!
- AUTO를 사용할 때 SEQUENCE 전략이 선택되면 시퀀스나 키 생성용 테이블을 미리 만들어 두어야 한다.
- 만약 스키마 자동 생성 기능을 사용한다면 하이버네이트가 기본값을 사용해서 적절한 시퀀스를 만들어준다.
반응형
'JPA > JPA' 카테고리의 다른 글
[JPA] 상속 관계 매핑 (0) | 2022.01.03 |
---|---|
[JPA] 연관관계 매핑 - 2 (0) | 2022.01.02 |
[JPA] 연관관계 매핑 - 1 (0) | 2022.01.01 |
[JPA] 영속성 컨텍스트 (Persistence context) (0) | 2021.12.29 |
JPA 사용하기 (feat. Maven) (0) | 2021.12.28 |
댓글