엔티티 매핑 소개
•
객체와 테이블 매핑 : @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 대리키
•
자연키 : 휴대폰 번호, 주민 번호 등
•
대리키 : 그 외 난수들