객체와 테이블 매핑: @Entity, @Table
필드와 컬럼 매핑: @Column
기본 키 매핑: @Id
연관관계 매핑: @ManyToOne,@JoinColumn
-
@Entity가 붙은 클래스는 JPA가 관리
-
JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수
-
기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
-
JPA가 엔터티 객체를 생성할 때 기본생성자를 사용하므로 이 생성자는 반드시 있어야 한다.
-
자바는 생성자가 하나도 없으면 기본 생성자를 자동으로 만든다
public Member(){} //기본 생성자
-
문제는 생성자를 하나 이상 만들면 자바는 기본 생성자를 자동으로 만들지 않기 때문에 기본 생성자를 직접 만들어야 한다.
-
JPA를 구현하는 라이브러리가 reflection 을 써서.. 기본생성자가 필수다.
-
-
final 클래스, enum, interface, inner 클래스 사용X
-
저장할 필드에 final 사용 X
- @Table은 엔티티로 매핑할 테이블 지정
- name : 매핑할 테이블 이름(default : 엔티티 명)
- catablog : 데이터베이스 catalog 매핑
- schema : 데이터베이스 schema 매핑
- uniqueConstrains : DDL생성 시에 유니크 제약 조건 생성
package hellojpa;
import javax.persistence.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
@Entity
public class Member {
@Id
private Long id;
@Column(name = "name")
private String username;
private Integer age;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
}@Column: 컬럼 매핑- name : 필드와 매핑할 테이블의 컬럼 이름
- insertable, updatable : 등록, 변경 가능 여부
- default : TRUE
- 거의 사용하지 않음
- nullable : null값 허용 여부, false로 설정하면 DDL생성 시에 not null 제약 조건이 붙음
- 생성DDL, validate체크로 자주 씀
- unique(DDL) : @Table의 uniqueContraints와 같지만 한 컬럼에 간단히 유니크 제약 조건을 걸 때 사용
- 현업에서 잘 안 씀
- Unique key이름이 복잡하게 생성 됨
- columnDefinition : 필드의 자바 타입과 방언 정보를 사용해 데이터베이스 컬럼 정보를 직접 줄 수 있다 ex) varchar(100) default 'EMPTY'
- length(DDL) : 문자 길이 제약조건, String 타입에만 사용
- default : 255
- precision, scale(DDL) : BigDecimal 타입에서 사용(BigInteger 도)
- precision은 소수점을 포함한 전체 자 릿수를, scale은 소수의 자릿수 다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나 정 밀한 소수를 다루어야 할 때만 사용한다.
- default : precision=19, scale=2
@Column 생략
-
대부분 @Column 속성의 기본값이 적용되는데, 자바 기본 타입일 때는 nullable 속성에 예외가 있음.
-
1 : column 생략, 자바 기본 타입 -> not null 추가 됨
2 : column 생략, 객체 타입 -> null 허용 됨
3 : column 추가, 자바 기본 타입 -> nullable default가 true라 nullable = false로 지정하는 것이 안전 함.
-
참고로 primitive 타입 Int, long, ... 은 null을 입력할 수 없음
1
int data1;
data1 integer not null // DDL
2
Integer data2;
data2 integer // DDL
3
@Column
int data3;
data3 integer // DDL
-
@Temporal: 날짜 타입 매핑-
@Temporal(TemporalType.DATE) // 날짜 @Temporal(TemporalType.DATETIME) // 시간 @Temporal(TemporalType.TIMESTAMP) // 날짜와 시간
-
TemporalType은 필수로 지정해야 함.
-
최근엔 Type으로 LocalDateTime, LocalDate를 쓰기에 필요 없는 매핑
-
-
@Enumerated: enum 타입 매핑-
public enum RoleType{ ADMIN, USER } @Entity public class Member{ // ... 생략 @Enumerated(EnumType.STRING) private RoleType roleType; }
-
EnumType에는 STRING, ORDINAL이 있다
-
ORDINAL
- enum에 정의된 순서대로 ADMIN은 0, USER는 1
- DB에 저장되는 데이터의 크기가 작다는 장점이 있지만, 이미 저장된 enum의 순서를 변경할 수 없다는 단점이 있다.
- 이러한 단점으로, 주의해서 사용해야 함.
-
STRING
- 저장된 enum의 순서가 바뀌거나 enum이 추가되어도 안전하다는 장점이 있지만 DB에 저장되는 데이터 크기가 ORDINAL에 비해 크다
-
-
@Lob: BLOB, CLOB 매핑-
큰 콘텐츠 저장 가능
-
CLOB : String, char[], java.sql.CLOB BLOB : byte[], java.sql.BLOB
-
@Lob private String description; // 회원을 설명하는 필드는 길이 제한이 없다. 따라서 데이터 베이스 VARCHAR 타입 대신에 CLOB 타입으로 저장해야 한다.
-
-
@Transient: 특정 필드를 컬럼에 매핑하지 않음 (매핑 무시)- 객체에 임시로 어떤 값을 보관하고 싶을 때 사용
- DB에 저장하지도 조회하지도 않는다.
- DDL 을 애플리케이션 실행 시점에 자동 생성
- 테이블 중심 → 객체 중심
- 개발 장비에서만 사용할 것
- 생성된 DDL은 운영서버에서는 사용하지 않거나 적절히 다듬은 후 사용
- create : 기존 테이블 삭제 후 다시 생성 (DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블 (DROP)
- update : 변경분만 반영 (운영 DB에는 사용하면 안 됨)
- validate : 엔티티와 테이블이 정상 매핑 되었는지만 확인
- none : 사용하지 않음
- 운영 장비에는 절대 create, create-drop, update 사용하면 안된다.
- 개발 초기 단계는 create 또는 update
- 테스트 서버는 update 또는 validate
- 스테이징과 운영 서버는 validate 또는 none
@Column(nullable = false, length = 10)
DDL을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않는다
이름 매핑 전략
- hibername.ejb.naming_strategy 속성 사용하면 이름 매핑 전략 변경 가능
- table, column 가능
@Column(name="role_type") // 언더스코드(_)
String roleType; // 카멜표기법-
직접할당
@Id-
Board board = new Board(); board.setId("id1"); // 기본 키 직접 할당 em.persiste(board);
-
-
자동 생성 (
@GeneratedValue)- IDENTITY : 데이터베이스에 위임, MYSQL
- SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용, ORACLE
@SequenceGenerator필요
- TABLE : 키 생성용 테이블 사용, 모든 DB에서 사용
@TableGenerator필요
- AUTO : 방언에 따라 자동 지정, Default값
IDENTITY
- 기본키 생성을 데이터베이스에 위임
- 주로 MySQL, PostgreSQL, SQL Server, DB2 에서 사용
- AUTO_INCREMENT는 데이터베이스에 INSERT SQL 실행 후에 식별자 ID를 알 수 있음
- Identity 전략은 em.persist() 시점에 즉시 INSERT SQL을 실행하고 DB에서 식별자를 조회한다.
- 원래 em.persist 에서는 persist context(1차 캐시)에 저장하고 insert는 commit 시점에 한다.
- 해당 전략은 트랜잭션을 지원하는 쓰기 지연이 동작하지 않는다.
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
}SEQUENCE
- 데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트 (ex, Oracle Sequence)
- 주로 오라클, PostgreSQL, DB2, H2 에서 사용
- em.persist(board); 를 할 때 시퀀스를 호출한다
@SequenceGenerator- 속성
- name : 식별자 생성기 이름, 필수
- sequenceName : DB에 등록되어있는 시퀀스 이름, defalut hibernate_sequence
- initialValue : DDL생성 시에만 사용됨, 시퀀스 DDL을 생설할 때 처음 1 시작하는 수를 지정한다, default 1
- allocationSize : 시퀀스 한 번 호출에 증가 하는 수(성능 최적화에 사용됨) 데이터 베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다, default가 50
- 기타
- catalog, schema
- 주의할 점
- allocationSize 기본값이 50이라는 점
- 속성
@Entity
@SequenceGenerator(
name = “MEMBER_SEQ_GENERATOR",
sequenceName = “MEMBER_SEQ", //매핑할 데이터베이스 시퀀스 이름
initialValue = 1, allocationSize = 1)
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
private Long id;
}- Sequence
- persist => 식별자(id) 조회
- entity에 식별자를 할당 후 persist (context에 저장)
- commit -> fulsh -> DB에 저장
- Identity
- persist => insert
- 식별자(id) 조회
- entity에 식별자 할당
TABLE
- 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
- 모든 데이터베이스에 적용 가능하다는 장점이 있지만 성능이 단점이다.
- 키 값을 조회 하면서 select 쿼리를 사용하고 다음 값으로 증가 시키기 위해 Update 쿼리를 사용한다. DB와 한 번 더 통신하는 단점이 있다. 최적화 하는 방법은 SEQUENCE 전략과 같다.(allocationSize사용)
@TableGenerator- 속성
- name, table
- pkColumnName : 시퀀스 컬럼명, default sequence_name
- valueColumnNa : 시퀀스 값 컬럼명, default next_val
- pkColumnValue : 키로 사용할 값 이름, default 엔티티 이름
- initialValue : 초기 값, 마지막으로 생성된 값이 기준이다. default 0
- allocationSize : 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨), default 50
- 기타
- catalog, schema: 데이터베이스 catalog, schema 이름 uniqueConstraints(DDL) : 유니크 제약 조건 지정 가능
- 속성
create table MY_SEQUENCES (
sequence_name varchar(255) not null,
next_val bigint,
primary key ( sequence_name )
)@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 아님, 유일, 변하면 안된다
- 미래까지 이 조건을 만족하는 자연키는 찾기 어렵다. 대리키(대체키)를 사용하자. 예를 들어 주민등록번호도 기본 키로 적절하기 않다.
- 권장: Long형 + 대체키 + 키 생성전략 사용