- 객체와 테이블 매핑 : @Entity, @Table
- 기본키 매핑 : @Id
- 필드와 칼럼 매핑 : @Column
- 연관관계 매핑 : @ManyToONe, @JoinColumn
💡 엔티티 클래스 제약 조건
- @Entity 적용해야 한다.
- @Id 적용해야 한다.
- 인자 없는 기본생성자 필요
- 기본 생성자는 public 이나 protected여야 한다
- 최상위 클래스여야 한다
- final이면 안된다.
📙객체와 테이블 매핑
💡@Entity
테이블과 매핑할 클래스는 @Entity 어노테이션을 필수로 붙여야 한다.
- 속성
- name
- 엔티티 이름을 지정한다.
- 기본값은 클래스 이름이다.
- 적용 시 주의사항
- JPA가 엔티티 객체를 생성할 때 기본 생성자를 사용하므로 기본 생성자는 필수이다.
- 자바는 생성자가 하나도 없으면 기본 생성자를 자동으로 만든다.
- 생성자를 하나 이상 만들면 자바는 기본 생성자를 자동으로 만들지 않으므로, 직접 만들어야 한다.
- final 클래스, enum, interface, inner 클래스에는 사용할 수 없다.
- 저장할 필드에 final을 사용하면 안 된다.
💡@Table
- 엔티티와 매핑할 테이블을 지정한다.
- 속성
- name : 테이블 이름(생략하면 클래스 이름과 동일한 이름)
- catalog : 카탈로그 이름 (ex. MySQL DB 이름)
- schema : 스키마 이름(ex. 오라클 스키마 이름)
- 유니크 제약조건
- 스키마 자동 생성 기능을 사용해서 DDL을 만들 때만 사용한다.
- 2개 이상의 복합 유니크 제약조건도 만들 수 있다.
📙데이터베이스 스키마 자동 생성
JPA는 데이터베이스 스키마를 자동으로 생성하는 기능을 지원한다.
💡설정
스키마 자동 생성 기능을 사용하기 위해서 persistence.xml에 설정이 필요하다.
다음 속성을 추가하면, 애플리케이션 실행 시점에 데이터베이스 테이블을 자동으로 생성한다.
<property name="hibernate.hbm2ddl.auto" value="create" />
다음 속성을 추가하면, 콘솔에 실행되는 데이블 생성 DDL을 출력할 수 있다.
<property name="hibernate.show_sql" value="true" />
✔️ 스키마 자동 생성 기능이 만든 DDL은 운영 환경에서 사용할 만큼 완벽하지 않으므로 개발환경에서 사용하거나 매핑을 어떻게 해야하는지 참고 정도로만 사용하는 것이 좋다.
💡hibernate.hbm2ddl.auto 속성
- create
- 기존 테이블을 삭제하고 새로 생성한다 (DROP + CREATE)
- create-drop
- create 속성에 추가로 애플리케이션을 종료할 때 생성한 DDL을 제거한다. (DROP + CREATE + DROP)
- update
- 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 변경 사항만 수정한다.
- validate
- 데이터베이스 테이블과 엔티티 매핑정보를 비교해서 차이가 있으면 경고를 남기고 애플리케이션을 실행하지 않는다.
- DDL을 수정하지 않는다.
- none
✔️ 자동 생성 기능을 사용하지 않으려면 속성 자체를 삭제하거나 유효하지 않은 옵션 값을 주면 된다.
📙DDL 생성 기능
@Column 매핑 정보의 속성 값을 지정하여 제약조건을 추가했을때, 이 제약조건들은 단지 DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다.
📙기본 키 매핑
기본 키를 애플리케이션에서 직접 할당하는 대신에 DB가 생성해주는 값을 사용하려면 어떻게 매핑해야 할까?
-
기본 키 직접 할당 전략
-
자동 생성 전략
- 대리 키 사용 방식
- IDENTITY 전략, SEQUENCE 전략, TABLE 전략
- GenerationType.AUTO
- 다음 속성을 추가해야 한다.
<property name="hibernate.id.new_generator_mappings" value="true" />
- DB를 변경해도 코드를 수정할 필요가 없다.
- SEQUENCE나 TABLE 전략이 선택되면 시퀀스나 키 생성용 테이블을 미리 만들어 두어야 한다.
💡기본 키 직접 할당 전략
기본 키를 애플리케이션에서 직접 할당한다.
💡IDENTITY 전략
기본 키 생성을 DB에 위임한다.
💡SEQUENCE
DB 시퀀스를 사용해서 기본 키를 할당한다.
✔️ DB 시퀀스란❓
유일한 값을 순서대로 생성하는 특별한 DB Object
- @SequenceGenerator를 사용해서 시퀀스 생성기를 등록한다.
-> 시퀀스 생성기를 실제 DB의 시퀀스와 매핑한다.
-> 키 생성 전략을 GenerationType.SEQUENCE로 설정, generator로 방금 등록한 시퀀스 생성기를 선택한다.
=> 식별자 값은 시퀀스 생성기가 할당한다.
- em.persist()를 호출할 때 먼저 DB 시퀀스를 사용해서 식별자를 조회한다.
-> 조회한 식별자를 엔티티에 할당한 후에 엔티티를 영속성 컨텍스트에 저장한다.
-> 트랜잭션을 커밋해서 플러시가 일어나면 엔티티를 DB에 저장한다.
- @SequenceGenerator
- name : 식별자 생성기 이름
- sequenceName : DB에 등록되어 있는 시퀀스 이름
- initialValue : DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 시작하는 수를 지정
- allocationSize : 시퀀스 한 번 호출에 증가하는 수
- catalog, schema : 데이터베이스 catalog, schema 이름
💡TABLE
키 생성 테이블을 사용한다.
- 키 생성 전용 테이블을 하나 만들고 이름과 값으로 사용할 칼럼을 만들어 DB 시퀀스를 흉내내는 전략
- 테이블을 사용하므로 모든 DB에 적용할 수 있다.
- @TableGenerator를 사용해서 케이블 키 생성기를 등록한다.
-> 생성한 테이블을 키 생성용 테이블로 매핑
-> GenerationType.TABLE 선택
-> @GeneratedValue.generator에 만든 테이블 키 생성기를 지정
=> 식별자 값은 해당 테이블 키 생성기가 할당
- @TableGenerator
- name : 식별자 생성기 이름
- table : 키 생성 테이블명
- pkColumnName : 시퀀스 칼럼명
- valueColumnName : 시퀀스 값 칼럼명
- pkColumnValue : 키로 사용할 값 이름
- initialValue : 초기 값, 마지막으로 생성된 값이 기준이다.
- allocationSize : 시퀀스 한 번 호출에 증가하는 수
- catalog, schema
- uniqueConstraints(DDL) : 유니크 제약 조건을 지정할 수 있다.
📙필드와 칼럼 매핑
💡@Column
- 객체 필드를 테이블 칼럼에 매핑
- 속성
- name
- 필드와 매핑할 테이블의 칼럼 이름
- default : 객체의 필드 이름
- nullable(DDL)
- null 값의 허용 여부 설정
- default : true
- false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.
- unique(DDL)
- 한 칼럼에 간단히 유니크 제약조건을 걸 때 사용
- length(DDL)
- 문자 길이 제약조건
- String 타입에만 사용
- precision, scale(DDL)
- BigDecimal 타입에서 사용
- precision : 소수점을 포함한 전체 자릿수
- scale : 소수의 자릿수
- double, float 타입에는 적용하지 않는다.
- 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용
- default : precision=19, scale=2
💡@Enumerated
- 자바의 enum 타입을 매핑할 때 사용
- value
- EnumType.ORDINAL
- enum 순서를 DB에 저장
- 숫자 타입 칼럼에 매핑
- default
- DB에 저장되는 데이터 크기가 작다.
- 이미 저장된 enum의 순서를 변경할 수 없다.
- EnumType.STRING
- enum 이름을 DB에 저장
- 문자열 타입 칼럼에 매핑
- 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전하다.
- DB에 저장되는 데이터 크기가 ORDINAL에 비해서 크다.
💡@Temporal
- 날짜 타입(java.util.Date, java.util.Calender)을 매핑할 때 사용
- value
- TemporalType.DATE : 날짜, 데이터베이스 date 타입과 매핑
- TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑
- TemporalType.TIMESTAMP : 날짜와 시간, 데이터베이스 timestamp 타입과 매핑
- @Temporal을 생략하면 다음과 같이 정의된다.
- timestamp : H2, 오라클, PostgreSQL
💡@Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑
- 속성
- CLOB : String, char[], java.sql.CLOB
- BLOB : byte[], java.sql.BLOB
💡Transient
- 데이터베이스에 저장하지 않고 조회하지도 않는다.
- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용한다.
💡Access
- JPA가 엔티티 데이터에 접근하는 방식을 지정
- 클래스/개별 필드에 적용 가능
-
필드 접근
- AccessType.FIFLD로 지정
- 필드에 직접 접근
- 필드 접근 권한이 private이어도 접근할 수 있다.
- @Id 어노테이션을 필드에 붙인다.
-
프로퍼티 접근
- AccessType.PROPERTY로 지정
- 접근자(Getter)를 사용
- @Id 어노테이션을 getter 메서드에 붙인다.
📙매핑 어노테이션 사용해보기
@Entity
@Table(name = "hotel_info")
public class Hotel {
@Id
@Column(name = "hotel_id")
private String id;
@Column(name = "nm")
private String name;
private int year;
@Enumerated(EnumType.STRING)
private Grade grade;
private LocalDateTIme created;
@Column(name = "modified")
private LocalDateTime lastModified;