객체와 테이블 매핑
@Entity
- JPA가 관리하는 크래스를 Entity라고 하고, 이를 등록하는 에너테이션이다.
- 기본 생성자(파라미터가 없는 public 또는 protected)가 필수다.
final class
,enum
,interface
,inner class
에 사용 불가능하다.
- 저장할 filed에 final 사용이 불가능하다.
@Table
- 엔티티와 매핑할 테이블을 지정한다.
속성 | 기능 | 기본값 |
---|---|---|
name | 매핑한 테이블 이름 | 엔티티 이름 사용 |
catalog | DB catalog 매핑 | |
schema | DB schema 매핑 | |
uniqueConstrains(DDL) | DDL 생성 시에 유니크 제약 조건 생성 |
데이터 베이스 스키마(DDL) 자동 생성
- 애플리케이션 실행 시점에 DB TABLE을 자동으로 생성시켜준다.
- 이로써 SQL을 독립적으로 개발할 수 있다.
- 다만, 절대 운영서버에서 DDL을 그대로 사용하지말고, DDL을 다듬어서 사용해야한다.
옵션(hibernate.hbm2ddl.auto)
옵션 | 설명 |
---|---|
create | 기존 테이블 삭제 후 다시 생성(DROP + CREATE) |
create-drop | create와 같으나, 종료시점에 DROP |
update | 변경분만 반영(운영 DB에서 사용시 큰일남) → attribute 추가 시 DROP + CREATE 대신 ALTER TABLE, attribute 삭제 시 아무 일도 안 일어남. |
validate | 엔티티와 테이블이 정상 매핑되었는지만 확인 |
none | 사용하지 않음. |
주의사항
- 운영 장비에는 절대 create, create-drop, update를 사용하면 안 된다.
- 개발 초기 단계에는 create, update를 사용.
- 테스트 서버에는 update, validate를 사용.
- 스테이징과 운영 서버는 validate, none을 사용.
DDL 생성 제약 조건(Constraints)
- Column에 제약조건을 추가할 수 있다.
@Column(nullable=false, length = 10)
- Table에도 제약조건을 추가할 수 있다.
@Table(uniqueConstraints = {@UniqueConstraint( name = "NAME_AGE_UNIQUE", columnNames = {"NAME", "AGE"} )})
- DDL 생성시에만 영향을 주고, JPA의 실행 로직에는 전혀 영향을 주지 않는다.
필드와 컬럼 매핑
public class Member {
@Id
private Long id;
@Column(name = "name") // DB의 column명은 name
private String username;
private Integer age;
@Enumerated(EnumType.STRING) // enum의 value를 String으로 넣음. ORDINAL으로 넣으면 index
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP) // DATE: 날짜, TIME: 시간, TIMESTAMP: 날짜+시간
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob // unlimited string
private String description;
@Transient // DB와 매핑시키지 않음
int temp;
}
create table Member (
id bigint not null,
age integer,
createdDate timestamp,
description clob,
lastModifiedDate timestamp,
roleType varchar(255),
name varchar(255),
primary key (id)
)
@Column
속성 | 설명 | 기본값 |
---|---|---|
name | 필드와 매핑할 테이블의 컬럼 이름 | 객체의 필드 이름 |
insertable, updatable | 등록, 변경 가능 여부 | TRUE |
nullable(DDL) | null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다 | TRUE |
unique(DDL) | @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다 | |
columnDefinition (DDL) | 데이터베이스 컬럼 정보를 직접 줄 수 있다. ex) varchar(100) default ‘EMPTY’ | 필드의 자바 타입과 방언 정보를 사용해 |
length(DDL) | 문자 길이 제약조건, String 타입에만 사용한다. | 255 |
precision, scale(DDL) | BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다). precision은 소수점을 포함한 전체 자 릿수를, scale은 소수의 자릿수다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다. | precision=19, scale=2 |
@Enumerated
- 자바 enum 타입을 매핑할 때 사용.
속성 | 설명 | 기본값 |
---|---|---|
value | EnumType.ORDINAL : enum 순서를 DB에 저장 EnumType.STRING : enum 이름을 DB에 저장 | EnumType.ORDINAL |
- 주의! ORDINAL 절대 사용 X!
@Temporal
- 날짜 차입을 매핑할 때 사용.
- 최신 하이버네이트에서는
LocalDate
,LocalDateTime
사용 시 자동으로 삽입해주기 때문에 더 이상 사용할 필요가 없다.
@Lob
- 데이터베이스 BLOB, CLOB타입과 매핑할 때 사용.
- CLOB: String, char[], java.sql.CLOB
- BLOB: byte[], java.sql.BLOB
- 지정할 수 있는 속성이 하나도 없다.
@Transient
- 필드를 매핑시키지 않고 무시할 때 사용.
- 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용.
기본 키 매핑
@Id
- Primary Key임을 알릴 때 사용.
@GeneratedValue
- 자동으로 DB에서 값을 생성해올 때 사용한다. 만약 설정하지 않으면 수동으로 Id를 직접 넣어주어야 한다.
- 총 4가지 전략이 있다.
전략 | 의미 |
---|---|
IDENTITY | DB에 위임. MYSQL |
SEQUENCE | Sequnce 오브젝트 사용. ORACLE |
TABLE | 키 생성용 테이블 사용. 모든 DB |
AUTO | DB에 따라 자동.(위 3개 중 하나로 선택) |
IDENTITY 전략
- 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용한다.
- JPA에서 트랜잭션 커밋시점에 INSERT SQL을 실행하는데, AUTO_INCREMENT는 테이버에스에 INSERT SQL을 실행한 후에 ID를 알 수 있다. 이 때문에 SQL이 날라가기 전 까지 ID를 알 수가 없다.
SEQUENCE 전략
@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;
...
}
- 오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용한다.
- 특별한 데이터베이스 Sequence 오브젝트를 사용하여 ID를 계산한다.
- IDENTITY전략과 달리 SQL이 날라가기 전에 ID를 알 수 있다.
- DB의 SEQUENCE TABLE에서 값을 미리 가져올 수 있다.
- 트랜잭션이 commit되기 전에도 가져올 수 있다.
@SequenceGenerator
속성 | 설명 | 기본값 |
---|---|---|
name | 생성기 이름 | 필수 |
sequenceName | DB에 등록된 sequnce 이름 | hibernate_sequence |
initialValue | DDL생성시에만 사용 됨. 시퀀스 DDL생성 시 처음 시작하는 수 지정 | 1 |
allocationSize | 시퀀스 한 번 호출 시 증가하는 수. 성능 최적화의 핵심. | 50 |
catalog, schema | DB catalog, schema 이름 |
- 트랜잭션 commit전에 SEQUENCE TABLE에 SQL을 날려서 미리 ID를 가져오므로 네트워크를 2번타게 된다.
- 따라서, IDENTITY보다 더 느린 경우가 자주 발생하는데, 이 때문에
allocationSize
옵션을 통해서 미리 ID를 여러개 증가시켜 애플리케이션에서 사용할 수 있도록 하는 것이다.
allocationSize
옵션이 기본 50이기 때문에 1개를 넣을 때 마다 DB의 SEQUENCE는 50이 증가할 것이고, 애플리케이션에서는 1씩 증가하고 50개가 다 채워질 경우, 다시 DB에 요청하여 50개를더 증가시켜서 가져온다.
em.persist(member1); // DB SEQ = 1 | 1 => DB 호출
em.persist(member2); // DB SEQ = 51 | 2 => MEM에서 처리
em.persist(member3); // DB SEQ = 51 | 3 => MEM에서 처리
TABLE 전략
- 키 생성 전용 테이블을 하나 만들어 SEQUENCE전략을 흉내낸 것이다. 사용방법도 동일하다.
@TableGenerator
속성 | 설명 | 기본값 |
---|---|---|
name | 생성기 이름 | 필수 |
table | 키생성 테이블명 | hibernate_sequences |
pkColumnName | 시퀀스 칼럼명 | sequence_name |
valueColumnNa | 시퀀스 값 칼럼명 | nex_val |
pkColumnValue | 키로 사용할 값 이름 | 엔티티 이름 |
initialValue | 초기 값, 마지막으로 생성된 값이 기준이다. | 0 |
allocationSize | 시퀀스 한 번 호출 시 증가하는 수. 성능 최적화의 핵심. | 50 |
catalog, schema | DB catalog, schema 이름 | |
uniqueConstraints(DDL) | 유니크 제약조건을 지정할 수 있다. |
권장하는 식별자 전략
- 기본 키 제약 조건: null이 아니어야하며, 절대 변하지 않아야 한다.
- 먼 미래까지 이 조건을 만족하는 자연키를 찾는 것이 쉽지 않다(주민등록번호도 기본 키로 적절하지 않을 정도이다.)
- 따라서, 자연키가 아닌 대체키(자연적으로 존재하지 않고, DB상에 독립적인)를 사용하자.
- 권장: Long형 + 대체키 + 키 생성전략 이용
Uploaded by N2T
(23.06.11 16:46)에 작성된 글 입니다.