- 객체와 테이블 매핑
- 데이터베이스 스키마 자동 생성
- 필드와 컬럼 매핑
- 기본 키 매핑
- 실전 예제 - 요구사항 분석과 기본 매핑
객체와 테이블 매핑
- @Entity
1. @Entity가 붙은 클래스는 JPA가 관리, 엔티티라 한다.
2. JPA를 사용해서 테이블과 매핑할 클래스는 @Entity가 필수 이다.
3. 주의 사항
- 기본 생성자 필수(파라미터가 없는 public 또는 protected 생성자)
- final클래스, enum, interface, inner 클래스 사용X
4. 속성 정리
- 속성 : name
- JPA에서 사용할 엔티티 이름을 지정합니다.
- 기본값: 클래스 이름을 그대로 사용 합니다.(예: Member)
- 같은 클래스 이름이 없으면 가급적 기본값을 사용 합니다.
- @Table
1. 엔티티와 매핑할 테이블을 지정 합니다.
2. 속성 정리
- name : 매핑할 테이블 이름 (기본값 : 엔티티 이름)
- catalog : 데이터베이스 catalog 매핑
- schema : 데이터베이스 schema 매핑
- uniqueContraints(DDL) : DDL 생성 시에 유니크 제약 조건 생성
데이터베이스 스키마 자동 생성
- DDL을 애플리케이션 실행 시점에 자동 생성
- 테이블 중심에서 객체 중심으로 전환
- 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성
- 이렇게 생성된 DDL은 개발 장비에서만 사용
- 생성된 DDL은 운영서버에서는 사용하지 않거나, 적절히 다듬은 후 사용
- 속성 정리
- hibernate.hbm2ddl.auto
- create : 기존테이블 삭제 후 다시 생성(DROP + CREATE)
- create-drop : create와 같으나 종료시점에 테이블 DROP
- update : 변경분만 반영(운영DB에는 사용하면 안됨)
- vaildate : 엔티티와 테이블이 정상 매핑되었는지만 확인
- none : 사용하지 않음
- hibernate.hbm2ddl.auto
- 주의 사항
- 운영 장비에는 절대 create, create-drop, update 사용하면 안됩니다.
- 개발 초기 단계는 create 또는 update
- 테스트 서버는 update 또든 validate
- 스테이징과 운영 서버는 validate 또는 none
<property name="hibernate.hbm2ddl.auto" value="create" /> ** value 설정 따라 스키마 생성이 다름
DDL 생성 기능
- 제야조건 추가 : 회원 이름은 필수, 10자 초과 X
- @Column(nullable=false, length=10)
- 유니크 제약조건 추가
- @Table(uniqueContraints = {@UniqueConstraint(name= "NAME_AGE_UNIQUE", colNames={"NAME", "AGE"})})
- DDL 생성 기능은 DDL을 자동 생성 할 때만 사용되고 JPA의 실행 로직에는 영향을 주지 않습니다.
필드와 컬럼 매핑
package hellojpa;
import javax.persistence.*;
import java.util.Date;
//jap 사용 인식 및 관리
@Entity
/*@Table(name="USER")*/
public class Member {
@Id
private Long id;
@Column(name = "name", nullable = false)
private String username;
private Integer age;
//private LocalDate testDate;
//private LocalDateTime testDate2;
@Enumerated(EnumType.STRING)
private RoleType roleType;
@Temporal(TemporalType.TIMESTAMP)
private Date createdDate;
@Temporal(TemporalType.TIMESTAMP)
private Date lastModifiedDate;
@Lob
private String description;
public Member(){
}
}
매핑 어노테이션 정리
1. @Column
- 속성 정리
- name : 필드와 매핑할 테이블의 컬럼 이름(기본값 : 객체의 필드 이름)
- insertable, updatable : 등록, 변경 가능 여부 (기본값 : true)
- nullable(DDL) : null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시 에 not null 제약조건이 붙는다.
- unique(DDL) : @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.
- columnDefinition( DDL) : 데이터베이스 컬럼 정보를 직접 줄 수 있다. ex) varchar(100) default 'EMPTY'
- length(DDL) : 문자 길이 제약조건, String 타입에만 사용한다.(기본값 : 255)
- precision, scale(DDL) : BigDecimal 타입에서 사용한다.(BigInteger도 사용할 수 있다.) precision은 소수점을 포함한 전체 자릿수를, scale은 소수의 자릿수다. 참고로 double, float 타입에는 적용되지 않는다. 아주 큰 숫자나 정밀한 소수를 다루어야 할 때만 사용한다.
2. @Enumerated
- 자바 enum 타입을 매핑할 때 사용
- 속성
- value
- EnumType.ORDINAL : enum 순서를 데이터베이스에 저장(기본값)
- EnumType.String : enum 이름을 데이터베이스에 저장
- value
- 주의사항
- ORDINAL 사용 금지 : 추가, 수정, 삭제 시 순서가 변경되면 문제가 생김
3. @Temporal
- 날짜 타입(java.util.Date, java.util.Calender)을 매핑할 때 사용
- 속성
- value
- TemporalType.DATE : 날짜, 데이터베이스 DATE 타입과 매핑(예 : 2013-10-11)
- TemporalType.TIME : 시간, 데이터베이스 time 타입과 매핑 (예: 11:11:11)
- TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑(예: 2013-10-11 11:11:11)
- value
- 참고 : LocalDate, LocalDateTime을 사용할 때는 생략 가능(최신 하이버네이트 지원)
4. @Lob
- 데이터베이스 BLOB, CLOB 타입과 매핑
- @Lob에는 지정할 수 있는 속성이 없다.
- 매핑하는 필드 타입이 문자면 CLOB 매핑, 나머지는 BLOB 매핑
- CLOB : String, char[], java.sql.CLOB
- BLOB: byte[], java.sql.BLOB
5. @Transient
- 필드 매핑X
- 데이터베이스에 저장X, 조회X
- 주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용
@Transient
private Integer temp;
기본키 매핑
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
기본 키 매핑 방법
- 직접 할당 : @Id만 사용
- 자동 생성(@GeneratedValue)
- IDENTITY : 데이터베이스에 위임, MYSQL
- SEQUENCE : 데이터베이스 시퀀스 오브젝트 사용, ORACLE
- @SequenceGenerator 필요
- TABLE : 키 생성용 테이블 사용, 모든 DB에서 사용
- @TableGenerator 필요
- AUTO : 방언에 따라 자동 지정, 기본 값
- IDENTITY
- 기본 키 생성을 데이터베이스에 위임
- 주로 MySQL, PostgreSQL, SQL Server, DB2에서 사용(예: MySQL의 AUTO_INCREMENT)
- JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL 실행
- AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 싱행 한 이후에 ID 값을 알 수 있음
- 1차 캐시에 @id 값을 알 수 없다는 뜻이다.
- persist() 수행 시 바로 insert 쿼리가 수행 된다.
- IDENTITY 전략은 em.persist() 시점에 즉시 INSERT SQL 실행 하고 DB에서 식별자를 조회
- SEQUENCE
- 데이터베이스 시퀀스 오브젝트 사용
- @SequenceGenerator 사용
- 속성
- name : 식별자 생성기 이름
- sequenceName : 데이터베이스에 등록되어 있는 시퀀스 이름
- initialValue : DDL 생성 시 에만 사용됨. 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정한다.
- allocationSize : 시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨, 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다. 기본값 = 50)
- catalog, schema : 데이터베이스 catalog, schema 이름
- persist() 시 시퀀스에서 next value를 가져와서 해당값을 @Id에 가지고 1차 캐싱을 진행
@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;
- TABLE
- 키 생성 전용 테이블을 하나 만들어서 테이터베이스 시퀀스를 흉내내는 전략
- 모든 데이터베이스에 적용 가능
- 성능 문제가 있음
- 속성
- name : 식별자 생성기 이름
- table : 키생성 테이블명
- pkColumnName : 시퀀스 컬럼명
- valueColumnName : 시퀀스 값 컬럼명(기본값 next_val)
- kpColumnValue : 키로 사용할 값 이름
- intialValue : 초기 값, 마지막으로 생성된 값이 기준이다.(기본값 : 0
- allocationSize : 시퀀스 한 번 호출에 증가하는 수 (성능 최적화에 사용됨, 기본값 : 50)
- catalog, schema : 데이터베이스 catalog, schema 이름
- uniqueConstraints(DDL) : 유니크 제약 조건을 지정 할 수 있다.
- @TableGenerator 필요
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형 + 대체키 + 키 생성전략 사용
기본키 생성 전략이 SEQUENCE인 경우
잦은 네트워크 통신이 발생하는데 줄이는 방안은?
-> 미리 인자값 갯수만큼 가져와서 사용한다.
@Entity
@SequenceGenerator(
name = "MEMBER_SEQ_GENERATOR",
sequenceName = "MEMBER_SEQ",
initialValue = 1, allocationSize = 50
)
public class Member2 {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "MEMBER_SEQ_GENERATOR")
@Column(name = "MEMBER_ID")
private Long id;
...
}
- allocationSize를 50으로 지정(기본) - 미리 가져와서 사용
실전 예제 - 1. 요구사항 분석과 기본 매핑
요구사항 분석
- 회원은 상품을 주문할 수 있다.
- 주문 시 여러 종류의 상품을 선택 할 수 있다.
기능목록
- 회원 기능
- 회원등록
- 회원조회
- 상품기능
- 상품등록
- 상품수정
- 상품조회
- 주문기능
- 상품주문
- 주문내역조회
- 주문취소
도메인 모델 분석
- 회원과 주문의 관계 : 회원은 여러 번 주문 할 수 있다(1:N)
- 주문과 상품의 관계 : 주문 할 때 여러 상품을 선택 할 수 있다. 반대로 같은 상품도 여러 번 주문 될 수 있다. 주문상품이라는 모델을 만들어서 N:N 관계를 1:N, N:1 관계로 풀어냈다.
테이블 설계
엔티티 설계와 매핑
데이터 중심 설계 문제점
1. 현재 방식은 객체 설계를 테이블 설계에 맞춘 방식
2. 테이블의 외래키를 객체에 그대로 가져옴
3. 객체 그래프 탐색이 불가능
4. 참조가 없으므로 UML도 잘못됨
'개발 > JPA' 카테고리의 다른 글
고급 매핑 (0) | 2022.06.07 |
---|---|
다양한 연관관계 매핑 (0) | 2022.06.06 |
연관관계 매핑 기초 (0) | 2022.06.05 |
영속성 관리 (0) | 2022.06.02 |
JPA소개 및 시작 (0) | 2022.05.31 |