JPA (4) 엔티티 매핑
02 Mar 2022김영한님의 자바 ORM 표준 JPA 프로그래밍 강의 정리
객체와 테이블 매핑
@Entity
- @Entity가 붙은 클래스는 JPA가 관리하며 entity라 함
- JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수
- 기본 생성자 필수
- final 클래스, enum, interface, inner class 사용할 수 없음
- 저장할 필드에
final
사용할 수 없음
속성 | 설명 | 기본값 |
---|---|---|
name | JPA에서 사용할 엔티티 이름 지정 같은 클래스 이름이 없으면 가급적 기본값 사용 |
클래스 이름 |
@Table
- @Table은 엔티티와 매핑할 테이블 지정
속성 | 설명 | 기본값 |
---|---|---|
name | 매핑할 테이블 이름 | 엔티티 이름을 기본값으로 사용 |
catalog | DB catalog 매핑 | |
schema | DB schema 매핑 | |
uniqueConstraints | DDL 생성시에 unique 제약 조건 생성 |
DB schema 자동 생성
- DDL을 애플리케이션 실행 시점에 자동 생성
- 테이블 중심 → 객체 중심
- DB 방언을 활용해서 적절한 DDL 생성
- 이렇게 생성된 DDL은 개발 환경에서만 사용해야 함
- 생성된 DDL은 운영 서버에서 사용하지 않거나 수정 후 사용
hibernate.hbm2ddl.auto
속성- DB 방언마다 DDL이 달라짐
- 운영 환경에서는 create, create-drop, update 사용 X
- 개발 초기 단계: create 또는 update
- 테스트 서버: update 또는 validate
- 스테이징, 운영 서버: validate 또는 none
옵션 | 설명 |
---|---|
create | 기존테이블 삭제 후 다시 생성 (DROP + CREATE) |
create-drop | create와 같지만 종료 시점에 테이블 DROP |
update | 변경 부분만 반영 (운영DB에는 사용하면 안됨) |
validate | 엔티티와 테이블이 정상 매핑되었는지만 확인 |
none | 사용하지 않음 |
DDL 생성 기능
- 제약조건 추가
// 필수 값 & 10자 초과 X @Column(nullable = false, length = 10)
- 유니크 제약 조건 추가
@Table(uniqueConstraints = {@UniqueConstraint(name = "NAME_AGE_UNIQUE",
columnName = {"NAME", "AGE"})})
@Column(unique = true)
- DDL 생성 기능은 JPA 실행 로직에는 영향 X
필드와 컬럼 매핑
- @Column: 컬럼 매핑
- @Temporal: 날짜 타입 매핑
- @Enumerated: enum 타입 매핑
- @Lob: BLOB, CLOB 매핑
- @Transient: 특정 필드를 컬럼에 매핑하지 않음 (매핑 무시)
@Column
속성 | 설명 | 기본값 |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable, updatable | 등록, 변경 가능 여부 | True |
nullabe(DDL) | null 값의 허용 여부 설정 false로 설정하면 DDL 생성시에 not null 제약 조건이 붙음 |
|
unique(DDL) | @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 unique 제약 조건을 걸 때 사용 | |
columnDefinition(DDL) | DB 컬럼 정보를 직접 줄 수 있음 예) varchar(100) default ‘EMPTY’ |
필드의 자바 타입과 방언 정보 사용 |
length(DDL) | 문자 길이 제약 조건, String 에만 사용 | 255 |
precision, scale(DDL) | BigDecimal 타입에서 사용 (BigInteger도 가능) precision은 소수점을 포함한 전체 자릿수 scale은 소수의 자릿수 double, float에는 적용되지 않고 아주 큰 숫자나 정밀한 소수를 다룰 때만 사용 |
precision=19 scale=2 |
@Enumerated
- Java enum 타입 매핑할 때 사용
ORDINAL
을 사용하지 않도록 주의(새로운 데이터를 추가할 때 순서에 의한 문제가 발생할 수 있음)
속성 | 설명 | 기본값 |
---|---|---|
value | EnumType.ORDINAL : enum 순서를 DB에 저장EnumType.STRING : enum 이름을 DB에 저장 |
EnumType.ORDINAL |
@Temporal
- 날짜 타입(java.util.Date, java.util.Calendar) 매핑할 때 사용
- LocalDate, LocalDateTime 사용할 때는 생략 가능
속성 | 설명 | 기본값 |
---|---|---|
value | TemporalType.DATE : 날짜, DB date 타입과 매핑TemporalType.TIME : 시간, DB time 타입과 매핑TemporalType.TIMESTAMP : 날짜와 시간, DB timestamp 타입과 매핑 |
@Lob
- DB의 BLOB, CLOB 타입과 매핑
- 지정할 수 있는 속성 X
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte[], java.sql.BLOB
@Transient
- 필드 매핑 X
- DB에 저장하거나 조회하지 않음
- 주로 메모리상에서 어떤 값을 보관하고 싶을 때 사용
기본 키 매핑
- 직접 할당:
@Id
만 사용 - 자동 생성:
@GeneratedValue
속성 | 설명 |
---|---|
GeneratedType.IDENTITY | DB에 위임 (MySQL) |
GeneratedType.SEQUENCE | DB 시퀀스 오브젝트 사용 (Oracle) @SequenceGenerator 필요 |
GeneratedType.TABLE | key 생성용 테이블 사용 모든 DB에서 사용 @TableGenerator 필요 |
GeneratedType.AUTO | 방언에 따라 자동 지정 기본값 |
IDENTITY
- 기본키 생성을 DB에 위임
- 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용
- JPA는 보통 트랜잭션 커밋 시점에 INSERT 쿼리 실행
- AUTO_INCREMENT는 DB에 INSERT 쿼리를 실행한 이후에 ID 확인 가능
- IDENTITY 전략은 em.peresist() 시점에 즉시 INSERT 쿼리를 실행 후, DB에서 식별자 조회
SEQUENCE
- 시퀀스는 유일한 값을 순서대로 생성하는 특별한 DB 오브젝트
- Oracle, PostgreSQL, DB2, H2에서 사용
- @SequenceGenerator
속성 | 설명 | 기본값 |
---|---|---|
name | 식별자 생성기 이름 | 필수 |
sequenceName | DB에 등록되어 있는 시퀀스 이름 | hibernate_sequence |
initialValue | DDL 생성 시에만 사용 시퀀스 DDL을 생성할 때는 처음 1 시작하는 수를 지정 |
|
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) DB 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 함 |
50 |
catalog, schema | DB의 catalog, schema 이름 |
@Entity
@SequenceGenerator(name = "MEMBER_SEQ_GENERATOR", sequenceName = "MEMBER_SEQ",
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
}
TABLE
- 키 생성 전용 테이블을 만들어 DB 시퀀스를 흉내내는 전략
- 모든 DB에 적용 가능하지만 성능 이슈가 있을 수 있음
- @TableGenerator
속성 | 설명 | 기본값 |
---|---|---|
name | 식별자 생성기 이름 | 필수 |
table | 키 생성 테이블 이름 | hibernate_sequences |
pkColumnName | 시퀀스 컬럼 이름 | sequence_name |
valueColumnName | 시퀀스 값 컬럼 이름 | next_val |
pkColumnValue | 키로 사용할 값 이름 | entity 이름 |
initialValue | 초기값 마지막으로 생성된 값이 기준 |
0 |
allocationSize | 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용) | 50 |
catalog, schema | DB의 catalog, schema 이름 | |
uniqueConstraints(DDL) | unique 제약 조건 지정 가능 |
@Entity
@TableGenerator(
name = "MEMBER_SEQ_GENERATOR",
table = "MY_SEQUENCES", pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "MEMBER_SEQ_GENERATOR")
private Long id;
권장하는 식별자 전략
- 기본 키 제약 조건
- null이 아님
- 유일한 값
- 변하면 안됨
- 3가지 조건을 다 만족하는 자연키를 찾기 어려움
- 대리키(대체키)를 사용하는 것 권장
- Long + 대체키 + 키 생성전략 사용