엔티티 매핑

D A S H B O A R D
D E V E L O P
S E C U R I T Y
 엔티티 매핑 소개
 객체와 테이블 매핑
 데이터 베이스 스키마 자동 생성
 필드와 컬럼 매핑
 기본 키 매핑
Reference

 엔티티 매핑 소개

객체와 테이블 매핑 : @Entity, @Table
필드와 컬럼 매핑 : @Column
기기본 키 매핑 : @Id
연관관계 매핑 : @ManyToOne, @JoinColumn

 객체와 테이블 매핑

@Entity

@Entity가 붙은 클래스는 JPA가 관리한다는 것을 명시해준다. ⇒ 이를 Entity라고 함
JPA를 사용해서 테이블과 매핑할 클래스는 @Entity 필수 
주의!!!
기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
final 클래스, enum, interface, inner 클래스 사용 X
저장할 필드에 final 사용 X ⇒ JPA가 객체를 계속 생성해야 하기 때문에 final을 사용하면 안된다.

속성

name
JPA에서 사용할 엔티티 이름을 지정 ⇒ @Entity(name = “Member”)
기본값 : 클래스 이름을 그대로 사용
같은 클래스 이름이 없으면 가급적 기본값 사용을 권장

@Table

@Table은 Entity와 매핑할 테이블 지정

속성

name
매핑할 테이블 이름 ⇒ @Table(name = “MBR”)
기본 값 : 엔티티 이름을 사용
catalog
데이터베이스 catalog 매핑
schema
데이터베이스 schema 매핑
uniqueConstraints(DDL)
DDL 생성 시에 유니크 제약 조건 생성

 데이터 베이스 스키마 자동 생성

DDL을 애플리케이션 실행 시점에 자동 생성해줌
데이터베이스 방언을 활용하여 데이터베이스에 맞는 적절한 DDL 생성
운영 환경에서는 안쓰는것을 권장
hibernate.hbm2ddl.auto를 이용.
아래 코드는 maven의 persistence.xml이니 참고
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"> <!--persistence-unit은 보통 DB의 이름을 설정--> <persistence-unit name="hello"> <properties> <property name="hibernate.hbm2ddl.auto" value="create" /> </properties> </persistence-unit> </persistence>
XML
복사

속성

hibernate.hbm2ddl.auto 에서 옵션에 따라 자동 생성 방식이 달라진다.
create
기존 테이블 삭제 후 다시 생성(DROP + CREATE)
create-drop
CREATE와 같으나 종료 시점에 DROP
update
변경분만 반영
validate
엔티티와 테이블이 정상 매핑되었는지만 확인
none
사용하지 않음
해당 property를 추가하지 않거나 value를 위 4가지 외 다른 것을 사용한 것과 동일
주의!
운영 장비에는 절대로 create, create-drop, update 사용하면 안됨
개발 초기단계에서는 create 또는 update
테스트 서버는 update 또는 validate ⇒ 하지만 웬만하면 쓰지 말자

 필드와 컬럼 매핑

@Column
기본적으로 객체의 변수명을 기본값으로 해서 DB에 쿼리를 날리지만, 원하는 이름으로 바꾸어서 보낼 수 있다. ⇒ @Column(name = “user”)
속성
name : 필드와 매핑할 테이블의 컬럼 이름
insertable, updateable : 등록, 변경 가능 여부
nullable(DDL) : null 값의 허용 여부 설정, false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다.
unique(DDL) : @Table의 uniqueConstraints와 같지만, 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용 → unique 이름설정이 안된다는 점과 복합으로 사용 못한다는 점에서 @ Table 어노테이션에서 사용하는 것을 권장
columnDefinition(DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있다.
length(DDL) : 문자 길이 제약조건, String 타입에서만 사용, 기본 값: 255
percision, scale(DDL) : BigDecimal 타입에서 사용(BigInteger도 사용 가능) → pecision은 소수점을 포함한 전체 자리수를, scalse은 소수의 자리수다. → 참고로 double, float 타입에는 적용 안됨
@Enumerated
enum 타입의 변수를 넣는 어노테이션
이때 default값은 EnumType.ORDINAL이다. 이는 Enum의 숫자형을 넣어주는데, 이는 후에 유지 보수 시에 DB에서 오류가 날 가능성이 매우높다.
그렇기 때문에 @Enumerated(EnumType.STRING)을 사용하는 것을 권장한다.
속성
value : EnumType.ORDINAL : enum 순서를 DB에 저장, EnumType.STRING : enum 이름을 DB에 저장, 기본값 : EnumType.ORDINAL
@Temporal
날짜나 시간의 형태를 지정하는 어노테이션
DB에서는 보통 날짜, 시간, 날짜-시간 이러한 3가지 형태로 되어 있기 때문에 여기서도 옵션으로 지정해주어야 한다.
속성
value : TemporalType.DATE, TemporalType.TIME , TemporalType.TIMESTAMP 이렇게 3가지가 있는데 최근에는 JAVA의 LocalDate를 사용
@Temporal(TemporalType.TIMESTAMP) private Date createDate;
Java
복사
private LocalDate orderDate; private LocalDateTime orderDate;
Java
복사
@Lob
BLOB, CLOB 매핑
DB에 varchar를 넘어서는 굉장히 큰 String 같은 경우 cLob을 이용하는데, 이를 위한 어노테이션
매핑하는 필드 타입이 문자면 CLOB, 나머지는 BLOB 매핑 → CLOB : String, char[], java.sql.CLOB → BLOB : byte[], java.sql.BLOB
@Transient
특정 필드를 매핑하고 싶지 않을 때 사용

 기본 키 매핑

직접 할당 : @Id 만 사용
자동 생성 : @GeneratedValue
IDENTITY : 데이터 베이스에 위임
SEQUENCE : 데이터 베이스 시퀀스 오브젝트 사용 → @SequenceGenerator 필요
TABLE : 키 생성 용 테이블 사용, 모든 DB에서 사용 → @TableGenerator 사용
AUTO : 방언에 따라 자동 지정, 기본값

IDENTITY 전략

기본 키 생성을 DB에 위임
주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용 → ex) MySQL의 AUTO_INCREMENT
JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
영속성 컨텍스트로 인해 늦게 Insert 쿼리가 나갈텐데 키 생성을 DB에서 해준다면 ID는 그때 비어 있나요?
AUTO_INCREMENT는 데이터 베이스에 INSERT SQL을 실행한 이후에 ID 값을 알 수 있음
IDENTITIY 전략은 em .persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회
@Entity public class Member { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; }
Java
복사

SEQUENCE 전략

데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트 → ex) 오라클의 시퀀스
오라클, PostgreSQL, DB2, H2 데이터베이스에서 사용
특징
allocationSize가 기본 값이 50이기 때문에 처음 DB에서 50개의 인덱스를 가지고 오는 것이다.
즉, 1~51까지 서버가 미리 끌어와서 사용하는 것, 이 때 DB에도 sequence가 51로 update되기 때문에 여러 서버에서 동시 접근해도 문제가 되지 않는다. ⇒ Table 전략에서도 마찬가지!!!
@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; }
Java
복사
@SequenceGenerator - 속성
name : 식별자 생성기 이름 ⇒ 필수
sequenceName : 데이터베이스에 등록되어 있는 시퀀스 이름 ⇒ 기본값 : hibernate_sequence
initialValue : DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정 ⇒ 기본값 : 1
allocationSize : 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨) → DB 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 함 ⇒ 기본값 : 50
catalog, schema : 데이터베이스 catalog, schema 이름

TABLE 전략

키 생성 전용 테이블을 하나 만들어서 데이터베이스 스퀀스를 흉내내는 전략
장점 : 모든 데이터베이스에 적용 가능
단점 : 성능
@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; }
Java
복사
호출 시 Query
create table MY_SEQUENCES ( sequence_name varchar(255) not null, next_val bigint, primary key ( sequence_name ) )
SQL
복사
@TableGenerator - 속성
name : 식별자 생성기 이름 ⇒ 필수
table : 키 생성 테이블 명 ⇒ 기본값 : hibernate_sequence
pkColumnName : 시퀀스 컬럼 명 ⇒ 기본값 : sequence_name
valueColumnName : 시퀀스 값 컬럼 명 ⇒ 기본값 : next_val
pkColumnValue :키로 사용할 값 이름 ⇒ 엔티티 이름
initialValue : 초기 값, 마지막으로 생성된 값이 기준 ⇒ 기본값 : 1
allocationSize : 시퀀스 한 번 호출에 증가하는 수(성능 최적화에 사용됨) ⇒ 기본값 : 50
catalog, schema : 데이터베이스 catalog, schema 이름
uniqueConstraints(DDL) : 유니크 제약 조건을 지정 가능
권장하는 식별자 전략
기본 키 제약 조건 : null 아님, 유일, 변하면 안됨
미래까지 이 조건을 만족하는 자연키 찾기 어려움, 대리키(대체키) 사용
예를 들면 주민등록번호는 기본 키로 적절하지 않다.
권장 : Long 형 + 대체키 + 키 생성전략 사용
자연키 vs 대리키
자연키 : 휴대폰 번호, 주민 번호 등
대리키 : 그 외 난수들