티스토리 뷰

Spring/JPA

JPA - 엔티티 매핑

땅속 디그다 2022. 8. 3. 16:07

🛠 엔티티 매핑


JPA 에서의 중요한 점

  1. 동작 방식
  2. 데이터 베이스와 객체를 어떻게 연관지을 것인가? (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가 사용하는 키생성 전략은 다음과 같다

  1. 직접할당 : 기본 키를 애플리케이션에서 직접 할당
  2. 자동 생성 : 대리 키 사용 방식
    • 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
댓글
04-08 00:51
Total
Today
Yesterday
링크