JPA 는 Entity 인 Java 클래스를 어떻게 변환하여, 관계형 데이터베이스에 테이블을 생성해줄까??
데이터베이스 스키마 및 테이블 자동 생성하기
JPA 의 구현체인 Hibernate 는 Entity 코드를 스캔하여 스키마 와 테이블을 자동으로 생성해주는 기능이 있다.
- 즉, DDL 을 애플리케이션 실행 시점에 자동으로 생성해주는 기능이다.
- 위 기능은 jpa.hibernate.ddl-auto 옵션을 통하여 설정할 수 있다.
jpa.hibernate.ddl-auto
ddl-auto 기능은 각 RDBMS (MySQL, Oracle, MariaDB, 등)의 서로 다른 방언에 맞는 DDL 을 자동 생성 및 실행해준다.
자동 생성에 대한 옵션은 아래와 같다.
create
- 기존 테이블 삭제 후 다시 생성(DROP + CREATE)
- 초기 개발 시 적용
create-drop
- create와 같으나 종료시점에 테이블 DROP
- 초기 개발 또는 테스트 시 적용
update
- 변경된 부분만 반영된다. (ALTER)
- 테스트 시 적용
validate
- 엔티티와 테이블이 정상 매핑되었는지만 확인한다.
(즉, 테이블의 설정을 변경하지 않는다.)
- 테스트 또는 운영 시 적용
none
- DDL 문장을 자동 생성 및 실행 하지 않는다.
- 운영 시 적용
ddl-auto 기능은 개발 및 테스트 시 적용할 수 있지만, 운영 서버에서의 사용은 권장하지 않는다.
(실무에서는 DBA(DB 관리자) 와 상의 후 개발자 또는 DBA 가 직접 쿼리문을 작성 후 실행한다.)
객체와 테이블 매핑
@Entity
- 테이블과의 매핑
- @Entity가 붙은 클래스는 JPA가 관리하는 것으로, 엔티티라고 불린다.
속성
- name
- JPA에서 사용할 엔티티 이름을 지정한다.
- 기본값 : 클래스 이름을 사용한다.
주의사항
- 기본 생성자 (파라미터가 없는 Public 또는 Protected 생성자)는 필수다.
- JPA가 엔티티 객체를 생성할 때 기본 생성자를 사용하기 때문이다.
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
- 저장할 필드에 final 을 사용하면 안된다.
@Table
- 엔티티와 매핑할 테이블을 지정한다.
- 생략한다면, 매핑한 엔티티 이름을 테이블 이름으로 사용한다.
속성
- name
- 매핑할 테이블의 이름을 지정한다.
- 기본값 : 엔티티 이름을 사용한다.
- catalog
- catalog 기능이 있는 데이터베이스에서 catalog를 매핑한다.
catalog
- 데이터베이스의 개체들에 대한 정의를 담고 있는 메타데이터들로 구성된 데이터베이스 내의 인스턴스이다.
- 기본 테이블, 뷰 테이블, 동의어, 값 범위, 인덱스, 사용자, 사용자 그룹 등과 같은 데이너베이스의 개체들이 저장된다.
- schema
- schema 기능이 있는 데이터베이스에서 schema를 매핑한다.
schema
- 데이터베이스에서 자료의 구조, 자료의 표현 방법, 자료 간의 관계를 형식 언어로 정의한 구조이다.
- 데이터베이스의 설계에 대한 계획 (구조와 제약조건)을 정하는 것 이다.
- uniqueConstraints
- DDL 생성 시에 유니크 제약조건을 만든다.
- 2개 이상의 복합 유니크 제약 조건도 만들 수 있다.
- 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용한다.
@Table(uinqueConstraints = {
@UniqueConstraint(name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"})
})
public class Member {
...
}
기본 키 매핑
영속성 컨텍스트는 엔티티를 식별자 값으로 구분하기 때문에, 엔티티를 영속 상태로 만들기 위해서 식별자 값이 반드시 필요하다.
@Id
- 클래스의 필드 위에 선언하여, 해당 필드가 해당 Entity의 기본 키(Primary Key, PK)가 될 것 임을 지정해준다.
적용 가능한 Java 타입
- Java Primitive type (기본형)
- Java Wrapper type
- String
- java.util.Date
- java.sql.Date
- java.math.BigDecimal
- java.math.BigInteger
기본 키 직접 할당 전략
- 엔티티를 영속화(저장)하기 전에 애플리케이션에서 기본 키를 직접 할당하는 방법이다.
- 식별자 값 없이 저장하면 예외가 발생한다.
@GeneratedValue - 기본 키 자동 생성 전략
속성
- strategy
- 기본 키의 생성 전략을 설정해주기 위해 사용한다.
생성 전략 (GenerationType) 종류
- IDENTITY
- 기본 키 생성을 데이터베이스에 위임한다. 즉, 데이터베이스의 기본키 생성(번호 증가) 전략을 따라갑니다.
- SEQUENCE
- 데이터베이스의 특별한 오브젝트 시퀀스를 사용하여 기본키를 생성합니다.
SEQUENCE
- 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트
- @SequenceGenerator 를 통해 생성한다.
- TABLE
- 데이터베이스에 키 생성 전용 테이블을 하나 만들고, 이를 사용하여 기본키를 생성합니다.
- AUTO
- JPA 구현체가 자동으로 생성 전략을 결정합니다.
- Oracle DB 사용시 SEQUENCE, MySQL DB 사용 시 IDENTITY 사용
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
필드와 컬럼 매핑
@Column
- 객체 필드를 테이블 컬럼에 매핑한다.
- 속성 중 name, nullable 이 주로 사용되고, 나머지는 잘 사용되지 ㅏㅇㄴㅎ는 편이다.
속성
- name
- 필드와 매핑할 테이블 컬럼의 이름을 지정한다.
- 기본값 : 객체의 필드 이름
- nullable
- null 값의 허용 여부를 설정한다.
- false 설정 시 DDL 생성 시에 NOT NULL 제약조건이 추가된다.
- 기본값 : true
- unique
- 한 컬럼에 간단히 유니크 제약조건을 만들때 사용한다.
- @Table 의 uniqueConstraints 와 동일하다.
- columnDefinition
- 데이터베이스의 컬럼 정보를 직접 줄 수 있다.
- 기본 값 : 필드의 Java 타입과 방언 정보를 사용하여 적절한 컬럼 타을 생성한다.
- length
- String 타입의 문자 길이에 제약조건을 생성한다.
- 기본 값 : 255
- precision, scale
- BigDecimal, BigInteger 타입에서 사용한다.
- precision 은 소수점을 포함한 전체 자릿수를
scale 은 소수의 자릿수 이다.
- 기본 값 : precision = 19, scale = 2
@Enumerated
- Java의 enum 타입을 매핑할 때 사용한다.
속성
- value
- EnumType.ORDINAL : enum 순서를 데이터베이스에 저장
- EnumType.STRING : enum 이름을 데이터베이스에 저장
- 기본 값 : EnumType.ORDINAL
@Temporal
- 날짜 타입 (java.util.Date, java.util.Calendar)을 매핑할 때 사용한다.
속성
- value
- TemporalType.DATE : 날짜, 데이터베이스 data 타입과 매핑 (2020-12-18)
- TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑 (23:36:33)
- TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑 (2020-12-18 23:36:33)
- 기본 값 : TemporalType은 필수로 지정해야 한다.
- 생략 시, Java 의 Date 와 가장 유사한 timestamp 로 지정해준다.
@Lob (Large Object)
- CLOB (Char LOB)
- 매핑하는 필드 타입이 문자일 경우
- 문자 대형 객체 (String, char[], java.sql.CLOB)
- BLOB (Byte LOB)
- 매핑하는 필드 타입이 문자 이외일 경우
- 이진 대형 객체 (byte[], java.sql.BLOB)
@Transient
@Access
이외에도 @insertable, @updatable, @table 과 같은 거의 사용하지 않는 매핑 속성도 존재한다.