코드 저장소.

Jpa [엔티티 매핑] 본문

웹개발/Jpa

Jpa [엔티티 매핑]

slown 2024. 5. 11. 03:00

 

목차

1. 엔티티

2. 엔티티 매핑 관련 어노테이션

 

1. 엔티티 

엔티티는 데이터베이스 테이블에 매핑되는 자바 클래스를 말합니다. 엔티티 ORM(Object-Relational Mapping)에서 중요한 역할을 하며, 개발자가 복잡한 SQL 쿼리를 작성하는 대신 객체를 사용하여 데이터베이스와 상호 작용할 수 있도록 합니다.

 

데이터 베이스의 테이블을 연관시키기 위해서는 Jpa에서 제공하는 어노테이션을 사용해서 테이블을 매핑시킬 수 있습니다. 아래는 Jpa에서 엔티티 클래스에 적용되는 어노테이션들입니다. 

  • 테이블을 매핑하는 어노테이션 : @Table, @Entity
  • 기본키를 설정하는 어노테이션 : @Id
  • 필드와 컬럼에 연관되는 어노테이션: @Column,@Enumerated,@Temporal,@Transient,@Access,@LOB

2. 엔티티 매핑 관련 어노테이션

@Entity  : 해당 클래스가 엔티티임을 나타내기 위해서 필요한 어노테이션입니다. 

@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Entity {
    String name() default "";
}

 

@Entity의 내부를 보면 name 이라는 구현체가 있는데 이것은 엔티티의 이름을 정할 수 있습니다. 어노테이션으로만 특별히 지정을 하지 않는다면 보통은 클래스 이름을 그대로 사용을 합니다.

 

그리고 엔티티를 설정할때 주의할 점이 있다면 다음과 같습니다.

  • 기본 생성자는 필수입니다. (파라미터가 없는 public 또는 protected 생성자)
    • why? 
    • Hibernate는 클래스의 인스턴스를 생성할 때 reflection 기법을 사용하여 객체를 초기화 해야하기 때문에 만약 default 생성자가 존재하지 않으면 어떻게 초기화를 해야할지 모르기 때문에 엔터티 생성 시에는 반드시 기본 생성자가 있어야 됩니다. (기본적으로 별도의 생성자를 정의하지 않으면 자동으로 기본 생성자를 생성합니다.)
  • final 클래스, enum, interface, inner 클래스에는 사용 할 수 없습니다.
  • 저장할 필드에 final을 사용하면 안 됩니다.

@Table : 엔터티와 매핑할 테이블을 지정합니다. 생략하면 매핑한 엔터티 이름을 테이블 이름으로 사용합니다.

@Target(TYPE) 
@Retention(RUNTIME)
public @interface Table {

    String name() default "";

    String catalog() default "";

    String schema() default "";

    UniqueConstraint[] uniqueConstraints() default {};

    Index[] indexes() default {};
}

 

- name : 매핑될 테이블의 이름

- catalog : 매핑될 테이블이 속할 카탈로그의 이름

- schema : 매핑될 테이블이 속할 스키마의 이름

- uniqueConstaraints : 매핑될 테이블에게 적용될 제약조건

- indexes : 매핑될 테이블의 인덱스

 

@Id  :엔티티클래스에서 기본키를 설정할때 필요한 어노테이션입니다. id를 지정할 때에는 직접지정하는 방식과 자동으로 생성을 하는 방식이 있습니다. 

 

직접지정을 하는 방식

  • @Id를 넣으면 된다. 

자동으로 생성하는 방식

  • @Id와 @GeneratedValue를 같이 사용한다.
  • GenerationType 옵션으로 전략을 지정한다.

 @GeneratedValue의 종류

/** 
 * Defines the types of primary key generation strategies. 
 *
 * @see GeneratedValue
 *
 * @since 1.0
 */
public enum GenerationType { 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using an underlying 
     * database table to ensure uniqueness.
     */
    TABLE, 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using a database sequence.
     */
    SEQUENCE, 

    /**
     * Indicates that the persistence provider must assign 
     * primary keys for the entity using a database identity column.
     */
    IDENTITY,

    /**
     * Indicates that the persistence provider must assign
     * primary keys for the entity by generating an RFC 4122
     * Universally Unique IDentifier.
     */
    UUID,

    /**
     * Indicates that the persistence provider should pick an 
     * appropriate strategy for the particular database. The 
     * <code>AUTO</code> generation strategy may expect a database 
     * resource to exist, or it may attempt to create one. A vendor 
     * may provide documentation on how to create such resources 
     * in the event that it does not support schema generation 
     * or cannot create the schema resource at runtime.
     */
    AUTO
}

 

TABLE 

  • 키 생성 전용 테이블을 하나 만들어서 데이터베이스 시퀀스를 흉내내는 전략이다.
  • 엔티티에 적용을 하려면 @TableGenerator를 사용한다. 
  • 이 전략은 시퀀스와 거의 비슷하고 테이블을 사용하기 때문에, 시퀀스를 지원하지 않는 데이터베이스에서도 사용할 수 있다.
  • TABLE의 장점은 기존 시퀀스 전략과 달리 테이블을 만들어 테이블안에서 여러 pk들을 관리할 수가 있다는 장점이 있다.
@Entity
@Getter
@TableGenerator(name = "BOARD_SEQ_GENERATOR",
        table = "tbl_board",
        pkColumnValue = "BOARD_SEQ",
        initialValue = 1,
        allocationSize = 10)
@NoArgsConstructor
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE,generator = "BOARD_SEQ_GENERATOR")
    private Long id;

    @Column(name = "board_title",nullable = false)
    private String title;

    @Column(name = "board_author",nullable = false)
    private String author;

    @Column(name = "board_contents",nullable = false)
    private String contents;

    @CreatedDate
    private LocalDateTime createdTime;
    @LastModifiedDate
    private LocalDateTime updatedTime;
}

 

-name : 테이블명

-table : 시퀸스 생성 테이블 명

-pkColumnName 시퀀스 컬럼명 
-valueColumnName 시퀀스 값 컬럼명 
-pkColumnValue 키로 사용할 값 이름 엔티티 이름
-initialValue 초기 값. 마지막으로 생성된 값이 기준이다. 
-allocationSize 시퀀스를 한 번 호출할 때 증가하는 수 
-catalog, schema 식별자 생성기의 catalog, schema 이름
-uniqueConstraints (DDL) 유니크 제약 조건을 지정할 수 있다.

 

SEQUENCE

  • 유일한 값을 순서대로 생성하는 특별한 데이터베이스 오브젝트로 시퀀스(순서를 정함)를 사용해서 기본키를 생성합니다.
  • 엔티티에 적용을 하려면 @SequenceGenerator를 사용한다.
  • 시퀀스 전략을 사용하기 위해서는 우선 사용할 데이터베이스 시퀀스를 매핑한다.
@Entity
@Getter
@SequenceGenerator(name = "BOARD_SEQ_GENERATOR",
        sequenceName = "BOARD_SEQ",
        initialValue = 1,
        allocationSize = 100)
@NoArgsConstructor
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "BOARD_SEQ_GENERATOR")
    @Column(name = "board_id")
    private Long id;
    .....
}

 

IDENETITY

  • IDENTITY 전략은 기본 키 생성을 데이터베이스에 위임하는 전략으로 DB에서 자동으로 1씩 증가시키는 방식으로 MYSQL에서는 AUTO_INCREMENT를 사용해 기본키를 자동으로 생성합니다. (DB에서 값이 새로 들어 올때마다 자동으로 id값에 +1하여 저장)
    IDENTITY전략은 데이터베이스에 값을 저장하고 나서야 기본키 값을 구할 수 있을때 사용합니다.
  • 사용법은 아래와 같다.

@GeneratedValue(strategy = GenerationType.IDENTITY)

 

UUID

  • UUID를 사용해서 기본키를 만드는 방식입니다.
  • 전통적인 숫자 기반의 기본 키 생성 방법과 달리 문자열 기반으로 생성하기 때문에, 데이터베이스에서 별도의 시퀀스나 테이블을 생성할 필요없습니다.
  • UUID는 128비트의 숫자로 구성되며, 유일성이 보장된다. UUID를 생성하는 방법은 랜덤 값을 사용하는 방법과, 시간 정보와 랜덤 값을 조합하여 생성하는 방법이 있습니다.
  • UUID는 문자열로 구성되므로, 기본 키 값이 숫자일 때와 달리 인덱스를 사용할 때 성능에 영향을 미칠 수 있다. 또한, UUID는 고유성을 보장하지만, 순서를 보장하지 않기 때문에 순서에 의존하는 비지니스 로직에서는 추천하지는 않습니다.

AUTO

  • 말그대로 자동으로 지정을 하는 방식을 말합니다.

@Column : 엔티티 클래스에서 필드를 데이터베이스의 컬럼과 매핑시키는 어노테이션입니다. 

@Target({METHOD, FIELD}) 
@Retention(RUNTIME)
public @interface Column {

    String name() default "";

    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;
}

 

-name : 필드와 매핑할 테이블의 컬럼 이름을 작성합니다.

-unique : @Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제약조건을 걸 때 사용한다.

-insertable / updateable : DB에서 등록, 변경 가능 여부를 설정합니다. / 기본값 : TRUE

-nullable : null 값의 허용 여부를 설정합니다. / 기본값 : TRUE

-columnDefinition : 컬럼정보를 직접 작성합니다.

-length : 문자 길이를 정합니다. / 문자열

-percision / scale : BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다)

-table : 하나의 엔티티를 두 개 이상의 테이블에 매핑할 때 사용합니다.

 

@Enumerated  : Enum 타입을 매핑을 할 때 사용됩니다. 

 

EnumType.ORDINAL : enum 순서를 DB에 저장 (Integer Type으로 저장) :: 기본값

EnumType.STRING : enum 이름을 DB에 저장 (String Type으로 저장)

 

enum Role {
	ADMIN, MEMBER
}

@Enumerated(value = EnumType.STRING)
private Role role;

user.setRole(RoleType.ADMIN);

 

@Temporal :java.util.Date, java.util.Calendar와 같은 날짜 타입을 매핑할 때 사용됩니다.

 

value 속성에는 아래의 타입들이 있어요. (필수로 지정해야 해요.)

  • TemporalType.DATE: 날짜, 데이터베이스 date 타입과 매핑해요. (예: 2023-07-24)
  • TemporalType.TIME: 시간, 데이터베이스 time 타입과 매핑해요. (예: 10:11:11)
  • TemporalType.TIMESTAMP: 날짜와 시간, 데이터베이스 timestamp 타입과 매핑해요. (예: 2023-07-24 10:11:11)

@Temporal을 생략하면 자바의 Date와 가장 유사한 timestamp로 정의됍니다. timestamp 대신에 datetime을 예악어로 사용하는 데이터베이스도 있지만, 데이터베이스 방언 덕분에 애플리케이션 코드는 변경하지 않아도 돼요.

 

@LOB : 데이터베이스의BLOB, CLOB 타입과 매핑합니다.

 

필드 타입이 문자열이면 CLOB, 나머지는 BLOB으로 매핑됍니다.

 

@Transient : 객체에 임시로 어떤 값을 보관하고 싶을 때 사용합니다.

 

@Transient을 사용하면 데이터베이스에 컬럼으로 맵핑을 하지 않습니다.

 

@Access :JPA가 엔티티 데이터에 접근하는 방식을 지정합니다.

사용할 수 있는 속성은 아래와 같습니다.

  • AccessType.FIELD: 필드에 직접 접근
  • AccessType.PROPERTY: Getter를 사용

 

참고

https://ddol.tistory.com/41

 

[JPA] @Temporal / @Lob / @Transient 속성

@Temporal 날짜 타입 (java.util.Date, java.util.Calendar)을 매핑할 때 사용 - DATE : 날짜 2020-07-05 - TIME : 시간 10:50:11 - TIMESTAMP : 날짜,시간 2020-07-05 10:50:11 ** 지금은 사실 @Temporal이 필요 없다.. 자바8이 되면서

ddol.tistory.com

https://velog.io/@hyeok_1212/JPA-%EC%97%94%ED%8B%B0%ED%8B%B0-%EB%A7%A4%ED%95%91#enumerated

'웹개발 > Jpa' 카테고리의 다른 글

Jpa - 프록시 및 로딩전략  (0) 2024.05.29
Jpa - 값타입  (0) 2024.05.28
Jpa - 엔티티 연관관계  (0) 2024.05.25
Jpa - 영속성 컨텍스트  (0) 2024.05.13
Jpa 란 무엇인가??  (0) 2024.05.07