JPA Entity
객체와 테이블 매핑
@Entity
기본 생성자는 필수
final
클래스,enum
,interface
,inner
클래스에는 사용 불가저장할 필드에
final
사용하면 안됨
@Table
데이터베이스 초기화 전략
none
: 아무것도 실행하지 않음(default)create-drop
: SessionFactory가 시작될 때 drop 후 create를 실행하고, SessionFactory가 종료될 때 drop을 실행(in-memory DB의 경우 기본값)create
: SessionFactory가 시작될 때 데이터베이스 drop을 실행하고 create 실행update
: 변경된 스키마를 적용validate
: 변경된 스키마가 있다면 변경사항을 출력하고 애플리케이션을 종료
제약 조건
두개 이상 컬럼 묶어 Unique 설정
@Table
의 uniqueConstraints
속성을 사용해 지정할 수 있다.
필드와 컬럼 매핑
@Column
DDL과 관련된 속성들은 DDL을 자동으로 생성하는 경우에만 사용되며, JPA 실제 로직에는 영향을 주지 않는다.
@Enumerated
enum class
를 사용하려면 @Enumerated
어노테이션으로 매핑이 필요하다.
EnumType.ORDINAL
: enum 순서를 데이터베이스에 저장 (default)장점 : 데이터베이스에 저장되는 데이터 크기가 작음
단점 : 이미 저장된 enum 순서 변경 불가
EnumType.STRING
: enum 명을 데이터베이스에 저장(권장)장점 : 저장된 enum의 순서가 바뀌거나 추가되어도 안전
단점 : 데이터베이스에 저장되는 데이터 크기가 ORDINAL에 비교해 큼
@Temporal
날짜 타입(java.util.Date
, java.util.Calendar
)을 매핑할 때 사용하며, 아래 TemporalType
은 필수로 지정해야한다.
TemporalType.DATE
TemporalType.TIME
TemporalType.TIMESTAMP
datetime : MySQL
timestamp : H2, Oracle, PostgreSQL
@CreationTimestamp / @UpdateTimestamp
엔티티 객체에 대해 INSERT
, UPDATE
등의 쿼리가 발생할 때, 현재 시간을 자동으로 저장해주는 @CreationTimestamp
와 @UpdateTimestamp
어노테이션을 제공.
@Lob
CLOB
, BLOB
타입 매핑시 @Lob
을 사용하면 된다.
CLOB :
String
,char []
,java.sql.CLOB
BLOB :
byte[]
,java.sql.BLOB
mysql text 타입인 경우에는
@Column(columnDefinition = "TEXT")
사용longtext의 경우
@Lob
사용
@Transient
해당 필드는 매핑하지 않으므로, 데이터베이스에 저장/조회하지 않는다. 즉, 객체에 임시로 어떤 값을 보관하고 싶은 경우에 사용한다.
@Access
JPA가 Entity에 접근하는 방식 지정
AccessType.FIELD
: 필드에 직접 접근.AccessType.PROPERTY
: 접근자(getter)를 사용해 접근
지정하지 않는 경우 @Id
를 지정한 기준으로 설정된다.
기본 키 매핑
JPA Entity를 구현하려면 다음 규칙을 지켜져야한다.
모든 Entity 클래스는
@Id
설정이 필요하다.이때
@Id
로 설정된 값에는null
값이 올 수 없다.
기본키가 복합키인 경우에는
@EmbeddedId
혹은@IdClass
를 사용한다.테이블에 Primary Key가 없는 경우가 있을 수 있다. 이 경우에는 Unique한 컬럼을 기준으로
@Id
annotation을 붙이면된다.
자동 할당(단일키)
기본 키를 애플리케이션에서 직접 할당하는 방법
entityManager.persist()
호출 전 애플리케이션에서 직접 식별자 값을 할당해야하며, 식별자 값 없이 저장하면 예외가 발생한다.
자동 생성(단일키)
대리 키 사용 방식으로 @GeneratedValue
추가 후 원하는 키 생성 전략을 선택하면된다.
IDENTITY
여기서 IDENTITY
전략은 데이터베이스에 insert한 후에 기본 키 값을 조회할 수 있다.(데이터베이스에 Entity를 저장해서 식별자 값을 획득한 후 영속성 컨텍스트에 저장) 하이버네이트의 경우는 JDBC3에서 제공하는 API의 Statement.getGeneratedKeys()
메서드를 사용하여 데이터를 저장함과 동시에 생성된 키값을 얻어온다. 이 경우에는 트랜잭션 쓰기 지연은 동작하지 않는다.
SEQUENCE
여기서 @SequenceGenerator
를 사용해 시퀀스 생성기를 등록했으며, 등록한 시퀀스 생성기를 @GeneratedValue
의 generator로 생성한 시퀀스를 지정했다.
@SequenceGenerator
여기서 매핑할 데이터베이스 시퀀스 명을 지정하지 않으면 hibernate_sequence
를 전역에서 사용한다.
SEQUENCE 전략은 데이터베이스 1. 시퀀스를 사용해 식별자를 조회한 후 2. 조회한 식별자를 Entity에 할당하고, 영속성 컨텍스트에 저장한다.
즉, 데이터베이스와 2번 통신한다.
JPA는 시퀀스에 접근하는 횟수를 줄이기 위해 allocationSize
를 사용한다. allocationSize만큼 한 번에 시퀀스 값을 증가시키고, allocationSize만큼 메모리에 시퀀스 값을 할당한다. 이 최적화 방법은 시퀀스 값을 선점하므로, 여러 JVM이 동시에 동작해도 기본 키 값이 충돌하지 않는다. 단 allocationSize만큼 시퀀스 값이 증가하는 것은 유의해야한다.
TABLE
CUSTOM_SEQUENCES
키 생성용 테이블을 하나 만들어두고 그 테이블을 지정한 후 pkCloumnValue
로 시퀀스 값을 한개 생성하여 사용하는 것이다.
다음과 같이 pkCloumnValue로 지정한 값이 추가된 것을 볼 수 있으며, 키 생성시마다 next_val
이 증가하는 것을 볼 수 있다.
@TableGenerator
이 전략은 데이터베이스 시퀀스 생성용 테이블에서 식별자 값을 획득한 후 영속성 컨텍스트에 저장한다.
AUTO
GenerationType.AUTO
는 선택한 데이터베이스에 따라 위 3개 전략 중 하나를 자동으로 선택한다.
Oracle : SEQUENCE
MySQL : IDENTITY
권장하는 식별자 선택 전략
데이터베이스 기본 키는
null 값은 허용하지 않는다.
유일해야한다.
변해선 안 된다.
테이블의 기본 키를 선택하는 전략은 1. 자연 키 , 2. 대리 키가 있다.
자연 키 : 비즈니스에 의미가 있는 키 (ex) 주민번호, 이메일, 전화번호
대리 키/대체 키 : 비즈니스와 관련 없는 임의로 만들어진 키 (ex) 시퀀스, auto_increment
비즈니스 환경은 언젠가 변하며, 자연 키보다는 대리 키 사용을 권장한다.
복합키(EmbeddedId, @IdClass)
두 어노테이션은 물리적 모델 관점에서 차이점은 없다.
@EmbeddedId는 결합 된 PK가 의미있는 엔티티 자체이거나 코드에서 재사용 될 때 의미가 있다.
객체 지향에 더 가까운 방법
@IdClass는 필드의 일부 조합이 고유하지만 특별한 의미가 없을 경우에 유용하다.
DB에 더 가까운 방법
@IdClass
@IdClass에는 식별자 클래스를 생성해야한다. 예시에서는 PaymentMasterPk 클래스를 생성해주었다. 여기서 식별자 클래스에는 몇가지 규칙이 있다.
Serializable 인터페이스 구현
식별자 클래스의 필드명과 Entity에서 사용하는 식별자의 필드명이 동일해야한다.
equals()
와hashCode()
를 구현해야한다.기본 생성자(args가 없는)를 구현해야한다.
클래스의 접근 제한자는 public이어야한다.
@EmbeddedId
식별자 클래스에 @Embeddable을 사용해야한다.
Serializable 인터페이스를 구현해야한다.
equals()
,hashCode()
를 구현해야한다.기본생성자를 선언해야한다.
클래스의 접근 제한자는 public이어야한다.
참조
Last updated