티스토리 뷰
🛠 엔티티 매핑
JPA 에서의 중요한 점
- 동작 방식
- 데이터 베이스와 객체를 어떻게 연관지을 것인가? (mapping 할 것인가?)
결국 JPA 에서 지원하는 Annotation들을 잘 알고 잘 사용해야 안전하게 매핑이 가능하다
🚀 객체와 테이블 매핑
@Entity
@Entity가 붙은 클래스는 JPA가 관리하고 엔티티라고 부른다.
JPA를 사용하여 테이블과 매핑할 클래스는 @Entity가 필수다.
❌ 조건
- 기본 생성자가 필수(public 또는 protected)
- final 클래스, enum, interface, inner 클래스 사용 불가
- 저장할 필드에 final 사용 불가
🖥 @Entity 의 코드
@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
String name() default "";
}
JPA에서 사용할 Entity 이름을 지정
@Table
@Table은 엔티티와 매핑할 테이블을 지정한다.
예를 들어 Member 클래스와 매핑할 데이터 베이스 테이블이 Mem일 때 @Table을 사용하여 매핑 대상을 정의 할 수 있다.
🖥 @Table 의 코드
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
String name() default "";
String catalog() default "";
String schema() default "";
UniqueConstraint[] uniqueConstraints() default {};
Index[] indexes() default {};
}
@Table을 사용하면 애플리케이션 실행 시점에 auto-ddl 을 해준다.
✅ 데이터베이스 스키마 자동 생성
- ddl을 어플리케이션 실행 시점에 자동 생성 해준다.
- 데이터베이스 방언을 활용해서 데이터베이스에 맞는 적절한 DDL 생성을 도와준다.
- ❗단 운영 단계에서 사용하면 옳지 않다.
- ddl 생성 기능은 DDL 을 자동 생성할 때만 사용되고 JPA의 실행 로직에는 영향 X
제약 조건 같은 것들을 말한다 hibernate 기준 ddl-update 쪽에서는 먹히지 않는다
아무리 봐도 table을 변경 할 때는 직접 ddl 을 db쪽에서 작성하는 것이 중요할 것 같다.
매핑의 주의 사항 (이름 표기법)
단어와 단어를 구분할 때 자바 언어는 관례상 카멜 표기법을 주로 사용하고 데이터베이스는 관례상 언더스코어를 주로 사용한다.
그렇게 될경우 @Colum.name @Table.name 속성 들을 사용하여 하나씩 매핑을 해주는 결과를 낳는다.
hibernate는 해당 상황을 막기위해 hibernate.ejb.naming_strategy를 속성을 사용하여 해결 할 수 있다.
value 값으로 ImprovedNamingStrategy 클래스를 주입하면 카멜 표기법에서 언더스코어 표기법으로 매핑을 고쳐준다.
🚀 필드와 컬럼 매핑
@Column
객체 필드를 테이블 컬럼에 매핑한다.
🖥 코드
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
// 두개 이상의 칼럼에서 사용할 시에 @Table 의 uniqueConstranints를 사용해야 한다.
boolean unique() default false;
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() default "";
int length() default 255;
int precision() default 0;
int scale() default 0;
}
❗ 주의 사항으로는 필드를 java 기본 타입으로 만들경우 nullable = false를 지정하는 것이 안전하다.
@Enumerate
자바의 enum 타입을 매핑할 때 사용한다
🖥 코드
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Enumerated {
EnumType value() default EnumType.ORDINAL;
}
EnumType.STRING 과 ORDINAL 중 하나를 선택하여 사용한다.
안전성과 실용성을 위해 STRING 을 사용하는 것이 정답이다.
@Temporal
날짜 타입을 매핑 할 때 사용한다. 생략할 경우 자바의 Date 와 가장 유사한 timestamp(dateTime) 으로 매핑된다.
🖥 코드
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Temporal {
TemporalType value();
}
- TemporalType.DATE - 날짜에 사용
- TemporalType.TIME - 시간에 사용
- TemporalType.TIMESTAMP - 날짜와 시간에 사용
@Lob
크기가 큰 문자열 속성에 매핑한다.
@Access
JPA가 엔티티 데이터에 접근하는 방식을 지정한다.
🚀 JPA의 기본키 매핑
기본 키를 어플리케이션 레벨에서 직접 할당하는 대신에 데이터베이스가 생성해주는 값을 사용하기 위해 등장
🤔 데이터베이스 마다 기본키 생성 전략이 다른데 이걸 어떻게 처리하지?
JPA가 사용하는 키생성 전략은 다음과 같다
- 직접할당 : 기본 키를 애플리케이션에서 직접 할당
- 자동 생성 : 대리 키 사용 방식
- IDENTITY: 기본 키 생성을 데이터베이스에 위임
- SEQUENCE: 데이터베이스 시퀀스를 사용해서 기본 키를 할당
- TABLE: 키 생성 테이블을 사용
자동 키 생성전략을 사용하려면 @Id 외에도 @GenerateValue 어노테이션을 사용하여야 한다.
IDENTITY 전략
기본 키 생성을 데이터 베이스에 위임한다
예를 들어 MY_SQL의 AUTO_INCREMENT
🤔 영속성 컨텍스트는 id 값으로 엔티티를 관리하게 되는데 persist 시점에 id를 모르는데?
이를 방지하고자 JPA 에서는 IDENTITY 전략을 선택하는 경우 persist 시점에 즉시
insert 쿼리문을 실행하여 DB에서 식별자 조회를 완료한다.
즉 IDENTITY 전략에서는 insert의 버퍼링을 사용하지 못한다.
SEQUENCE 전략
데이터베이스 시퀀스는 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트이다.
(주로 h2, Oracle)
시퀀스 전략을 적절히 사용해서(allocationSize) 성능 최적화 가능하다.
TABLE 전략
키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략
거의 사용하지 않는 전략이다. IDENTITY 단점 줄이려고 TABLE 섞어서 사용하려고 하는데
딱히 성능 최적화의 의미가 없다.
👍 그래서 권장하는 식별자 전략?
데이터 베이스가 사용하는 식별자 전략을 선택하는 편이 좋다.
다만, 사용시에 키 생성 전략에 따른 제약 조건이나, 쿼리 실행 시점을 아는 것이 중요하다.
'Spring > JPA' 카테고리의 다른 글
프록시와 연관관계 관리 (0) | 2022.08.23 |
---|---|
고급 매핑 (0) | 2022.08.23 |
JPA - 연관관계 이해하기 (0) | 2022.08.03 |
JPA - 영속성 컨텍스트 (2) | 2022.08.03 |
JPA 시작 (0) | 2022.08.03 |
- Total
- Today
- Yesterday