JPA - Entity

이쒅찬·2023λ…„ 2μ›” 20일
0
post-thumbnail

πŸ“– JPA Entity?

κ΄€κ³„ν˜• λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 데이터λ₯Ό μ €μž₯ν•˜κ³  κ΄€λ¦¬ν•˜κΈ° μœ„ν•΄ μžλ°” 객체λ₯Ό μ‚¬μš©ν•˜λŠ” 방식인 ORMμ—μ„œ μ‚¬μš©λ˜λŠ” 객체λ₯Ό λ§ν•©λ‹ˆλ‹€.

JPA Entity

λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”κ³Ό λ§€ν•‘λ˜λŠ” μžλ°” ν΄λž˜μŠ€μž…λ‹ˆλ‹€. ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ˜ ꡬ쑰와 λ™μΌν•œ ꡬ쑰λ₯Ό κ°€μ Έμ•Όν•˜λ©°, 클래슀 λ‚΄μ˜ 멀버 λ³€μˆ˜λŠ” ν…Œμ΄λΈ”μ˜ 컬럼과 λ§€ν•‘λ©λ‹ˆλ‹€.

create table user_data (
       id integer not null,
        created_at timestamp(6),
        email varchar(255),
        name varchar(255),
        updated_at timestamp(6),
        primary key (id)
)

예λ₯Ό λ“€μ–΄ ν•΄λ‹Ή ν…Œμ΄λΈ”κ³Ό λ§€ν•‘λ˜λŠ” Entity클래슀λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” ν•΄λ‹Ή ν…Œμ΄λΈ”κ³Ό λ™μΌν•œ ꡬ쑰λ₯Ό 가진 ν΄λž˜μŠ€κ°€ ν•„μš”ν•©λ‹ˆλ‹€. 각 컬럼과 λ§€ν•‘λ˜λŠ” 멀버 λ³€μˆ˜λ₯Ό μ„ μ–Έν•˜κ³ , ν•΄λ‹Ή λ³€μˆ˜λ₯Όμ„ getter, setter λ©”μ„œλ“œλ‘œ μ ‘κ·Όν•  수 μžˆλ„λ‘ λ§Œλ“€μ–΄μ•Ό ν•©λ‹ˆλ‹€.

JPA Entity ν΄λž˜μŠ€μ—λŠ” λ°˜λ“œμ‹œ @Entity μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•΄μ•Ό ν•΄λ‹Ή ν΄λž˜μŠ€κ°€ λ°μ΄ν„°λ² μ΄μŠ€μ™€ λ§€ν•‘λœλ‹€λŠ” 것을 인식할 수 μžˆμŠ΅λ‹ˆλ‹€.

Id

@Id둜 PrimaryKey 역할을 ν•˜λŠ” ν•„λ“œλ₯Ό μ§€μ •ν•˜κ³  @GeneratedValue μ–΄λ…Έν…Œμ΄μ…˜μ„ μ‚¬μš©ν•˜μ—¬ PrimaryKey 값을 μžλ™μœΌλ‘œ μƒμ„±ν•˜λŠ” 방법을 지정할 수 μžˆμŠ΅λ‹ˆλ‹€.

@GeneratedValue

@Id μ–΄λ…Έν…Œμ΄μ…˜κ³Ό ν•¨κ»˜ μ‚¬μš©λ˜λ©° μžλ™μœΌλ‘œ κ³ μœ ν•œ 값을 μƒμ„±ν•˜λ©° 고유ID(PK)λ₯Ό μƒμ„±ν•˜λŠ” 방법에 λŒ€ν•œ 정보λ₯Ό μ œκ³΅ν•˜λŠ” μ–΄λ…Έν…Œμ΄μ…˜μž…λ‹ˆλ‹€.

@Target({METHOD, FIELD})
@Retention(RUNTIME)

public @interface GeneratedValue {

    /**
     * (Optional) The primary key generation strategy
     * that the persistence provider must use to
     * generate the annotated entity primary key.
     */
    GenerationType strategy() default AUTO;

    /**
     * (Optional) The name of the primary key generator
     * to use as specified in the {@link SequenceGenerator} 
     * or {@link TableGenerator} annotation.
     * <p> Defaults to the id generator supplied by persistence provider.
     */
    String generator() default "";
}

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
}

ν•΄λ‹Ή μ–΄λ…Έν…Œμ΄μ…˜κ³Ό λ‚΄λΆ€μ˜ GenerationTypeμž…λ‹ˆλ‹€. @GeneratedValueμ—λŠ” 4κ°€μ§€μ˜ μ „λž΅μ΄ μ œκ³΅λ©λ‹ˆλ‹€.

GenerationType

  • AUTO : λ°μ΄ν„°λ² μ΄μŠ€ ν”Œλž«νΌμ„ κΈ°λ°˜μœΌλ‘œν•œ 생성 μ „λž΅μ„ μžλ™μœΌλ‘œ μ„ νƒν•©λ‹ˆλ‹€. (κΈ°λ³Έκ°’)

  • IDENTITY : 엔티티에 λŒ€ν•œ κ³ μœ ν•œ PKλ₯Ό μƒμ„±ν•˜κΈ° μœ„ν•΄ λ°μ΄ν„°λ² μ΄μŠ€μ— μ˜μ‘΄ν•©λ‹ˆλ‹€. 주둜 μžλ™ 증가 숫자 열을 μ§€μ›ν•˜λŠ” λ°μ΄ν„°λ² μ΄μŠ€μ™€ μ‚¬μš©λ˜λ©° μƒˆλ‘œμš΄ μ—”ν‹°ν‹°κ°€ μ˜μ†λ˜λŠ” 경우 λ°μ΄ν„°λ² μ΄μŠ€λŠ” μƒˆλ‘œμš΄ 고유 ID값을 μƒμ„±ν•˜μ—¬ μ—”ν‹°ν‹°μ˜ ID ν•„λ“œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.

  • SEQUENCE : λ°μ΄ν„°λ² μ΄μŠ€ μ‹œν€€μŠ€λ₯Ό μ‚¬μš©ν•˜μ—¬ κ³ μœ ν•œ κΈ°λ³Έ ν‚€ 값을 μƒμ„±ν•©λ‹ˆλ‹€. μ‹œν€€μŠ€λ₯Ό μ§€μ›ν•˜λŠ” λ°μ΄ν„°λ² μ΄μŠ€μ™€ ν•¨κ»˜ μ‚¬μš©λ˜λ©° IDENTITYμ „λž΅λ³΄λ‹€ 더 λ‚˜μ€ μ„±λŠ₯을 λ³΄μ—¬μ€λ‹ˆλ‹€. μƒˆ μ—”ν‹°ν‹°κ°€ μ˜μ†λ˜λ©΄ λ°μ΄ν„°λ² μ΄μŠ€ μ‹œν€€μŠ€μ—μ„œ μƒˆ 값을 μš”μ²­ μ—”ν‹°ν‹°μ˜ IDν•„λ“œμ— ν• λ‹Ήν•©λ‹ˆλ‹€.

@Data
@AllArgsConstructor
@RequiredArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@SequenceGenerator(
        name = "TEST_SEQ",
        sequenceName = "USER_SEQ_GEN",
        initialValue = 1,
        allocationSize = 50
)
public class UserData {
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TEST_SEQ")
    @Id
    private int id;

    @NonNull
    private String name;

    @NonNull
    private String email;

    private LocalDateTime createdAt;

    private LocalDateTime updatedAt;
}

@SequenceGeneratorλ₯Ό μ‚¬μš©ν•˜μ—¬ 지정할 수 있으며 μ•ˆμ— λ“€μ–΄κ°„ λ‚΄μš©μ€ 각각 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

  • name : μ‹œν€€μŠ€ μ œλ„ˆλ ˆμ΄ν„° 이름
  • sequenceName : μ‹œν€€μŠ€ 이름- > PK값을 μƒμ„±ν•˜λŠ”λ° μ‚¬μš©ν•  λ°μ΄ν„°λ² μ΄μŠ€ μ‹œν€€μŠ€μ˜ 이름을 지정
  • initialValue : ν•΄λ‹Ή μ—”ν‹°ν‹°μ˜ PK의 μ΄ˆκΈ°κ°’ default 1
  • allocationSize : λ©”λͺ¨λ¦¬λ₯Ό 톡해 ν• λ‹Ήν•  λ²”μœ„ μ‚¬μ΄μ¦ˆ default 50

쒅합해보면 ν•΄λ‹Ή μ—”ν‹°ν‹°μ—μ„œ Id값을 μžλ™μƒμ„±ν•  λ•Œ μ΄ˆκΈ°κ°’μ€ 1, μ‹λ³„μž 생성기λ₯Ό μ„€μ •ν•΄ 놓은 TEST_SEQ둜 μ„€μ •, 50κΉŒμ§€λŠ” λ©”λͺ¨λ¦¬μ—μ„œ ν˜„μž¬ μ‹œν€€μŠ€μ—μ„œ 값을 μ €μž₯ν•˜λ©° 이후 51이 λ˜λŠ” μ‹œμ μ— DB μ‹œν€€μŠ€λ₯Ό ν•œλ²ˆ 더 ν˜ΈμΆœν•œ 이후 100κΉŒμ§€ κ°€μƒμœΌλ‘œ μ‹œν€€μŠ€ μ‹λ³„μžλ₯Ό κ΄€λ¦¬ν•˜κ² λ‹€λŠ” λ‚΄μš©μž…λ‹ˆλ‹€.

  • TABLE : DBμ’…λ₯˜μ— 상관없이 λ³„λ„μ˜ ν…Œμ΄λΈ”μ„ λ§Œλ“€μ–΄λ‘κ³  ν•΄λ‹Ή ν…Œμ΄λΈ”μ—μ„œ ID값을 계속 μΆ”μΆœν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ„λ‘ μ œκ³΅ν•©λ‹ˆλ‹€. -> Key생성 Table

ν•΄λ‹Ή μ „λž΅μ€ SEQUENCEμ „λž΅κ³Ό λ™μΌν•˜κ²Œ generatorλ₯Ό μ„€μ •ν•˜μ—¬ λ§€ν•‘ν•©λ‹ˆλ‹€. 주둜 λ‹€λ₯Έ μ „λž΅μ„ μ‚¬μš©ν•˜μ§€ μ•Šμ„ λ•Œ μ‚¬μš©ν•©λ‹ˆλ‹€.

@Columnμ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λ©€λ¨Έ λ³€μˆ˜μ™€ λ°μ΄ν„°λ² μ΄μŠ€ columnκ°„μ˜ 맀핑을 μ§€μ •ν•©λ‹ˆλ‹€.

Entity클래슀λ₯Ό μƒμ„±ν–ˆλ‹€λ©΄ ν•΄λ‹Ή ν΄λž˜μŠ€μ™€ κ΄€λ ¨λœ CRUDλ₯Ό μ œκ³΅ν•˜λŠ” μž‘μ—…μ„ μˆ˜ν–‰ν•˜κΈ° μœ„ν•œ RepositoryμΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•˜κ³  λ©”μ„œλ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•©λ‹ˆλ‹€.

@Table

ν•΄λ‹Ή μ–΄λ…Έν…Œμ΄μ…˜μ€ λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ” κ°„μ˜ 맀핑을 μ •μ˜ν•˜λŠ”λ° μ‚¬μš©λ©λ‹ˆλ‹€. μ—”ν‹°ν‹° ν΄λž˜μŠ€μ— 적용되며 ν…Œμ΄λΈ”μ˜ 이름과 ꡬ성해야 ν•˜λŠ” μΆ”κ°€ ν…Œμ΄λΈ” μˆ˜μ€€ 속성을 μ§€μ •ν•©λ‹ˆλ‹€.

  • name : μ—”ν‹°ν‹°κ°€ 맀핑될 λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ˜ 이름을 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. defaultλŠ” μ—”ν‹°ν‹° 클래슀 이름과 λ™μΌν•©λ‹ˆλ‹€.

  • category : λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ˜ μΉ΄ν…Œκ³ λ¦¬ 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. default : ""

  • scherma : λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”μ˜ μŠ€ν‚€λ§ˆλ₯Ό 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. default : ""

  • UniqueConstraint[] : ν…Œμ΄λΈ”μ— λ°°μΉ˜ν•΄μ•Ό ν•˜λŠ” 고유 μ œμ•½ 쑰건을 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. @Column, @JoinColumn μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ λͺ¨λ“  μ œμ•½ 쑰건과 PK맀핑이 μˆ˜λ°˜ν•˜λŠ” μ œμ•½ 쑰건외에도 적용이 κ°€λŠ₯ν•©λ‹ˆλ‹€. default : {}

  • Index[] : ν…Œμ΄λΈ”μ— λŒ€ν•΄ 생성해야 ν•˜λŠ” 인덱슀λ₯Ό 지정할 수 μžˆμŠ΅λ‹ˆλ‹€. deafult : {} -> @NonNull와 같은 μ—­ν• 

@Table μ–΄λ…Έν…Œμ΄μ…˜μ€ ν…Œμ΄λΈ”μ„ λ§€ν•‘ν•˜λŠ”λ° μ‚¬μš©ν•˜λ©° μ—”ν‹°ν‹°, ν…Œμ΄λΈ” λ„€μž„, μŠ€ν‚€λ§ˆ 등을 μ μš©ν•΄μ•Ό ν•˜λŠ” 쑰건을 μ§€μ •ν•˜λŠ”λ° μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ‹€μ œ DB에 index섀정이 λ˜μ–΄μžˆμ§€ μ•Šμ€λ° ν…Œμ΄λΈ” 속성에 index섀정이 λ˜μ–΄μžˆλ‹€κ³  ν•΄μ„œ λ™μž‘ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

μΈλ±μŠ€λ‚˜ μ œμ•½μ‚¬ν•­λ“€μ€ DB섀정에 맑기고 Entity에 ν‘œκΈ°ν•˜μ§€ μ•ŠλŠ” 것이 쑰금 더 μ’‹μ•„λ³΄μž…λ‹ˆλ‹€.

πŸ€” μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” μ΄μœ λŠ”?

JPA Entity 클래슀λ₯Ό μž‘μ„±ν•˜λ©΄, ν•΄λ‹Ή 클래슀λ₯Ό μ‚¬μš©ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€μ™€ μƒν˜Έμž‘μš©ν•˜λŠ”λ° μ‚¬μš©λ  수 μžˆμŠ΅λ‹ˆλ‹€. ν•΄λ‹Ή ν΄λž˜μŠ€λŠ” λ‹€μ–‘ν•œ JPA 쿼리 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ λ°μ΄ν„°λ² μ΄μŠ€μ—μ„œ 데이터λ₯Ό κ²€μƒ‰ν•˜κ³  μ €μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

❌ λ¬Έμ œκ°€ λ˜λŠ” 경우

1. 둜직 뢄리 어렀움

JPA EntityλŠ” λ°μ΄ν„°λ² μ΄μŠ€μ™€ 1:1둜 λ§€ν•‘λ˜λŠ” κ°μ²΄μž…λ‹ˆλ‹€. 객체지ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ ꢌμž₯ν•˜λŠ” 엔티티와 λΉ„μ¦ˆλ‹ˆμŠ€ λ‘œμ§μ„ λΆ„λ¦¬ν•˜λŠ” 방식을 μ‚¬μš©ν•˜κΈ° μ–΄λ €μ›Œ Service 등을 μΆ”κ°€λ‘œ κ΅¬ν˜„ν•΄μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

2. 일뢀 κΈ°λŠ₯ 미지원

JPA EntityλŠ” λ°μ΄ν„°λ² μ΄μŠ€μ˜ κΈ°λ³Έ κΈ°λŠ₯을 μ§€μ›ν•˜λ©°, 일뢀 κΈ°λŠ₯은 μ§€μ›ν•˜μ§€ μ•Šμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ 경우 Native Queryλ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ λ³„λ„μ˜ JDBC μ½”λ“œλ₯Ό μž‘μ„±ν•΄μ•Ό ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

3. μ„±λŠ₯ 이슈

λ°μ΄ν„°λ² μ΄μŠ€μ™€μ˜ 맀핑을 μœ„ν•΄ λ§Žμ€ 메타데이터λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€. JPA λ‚΄λΆ€λ™μž‘μ„ μœ„ν•΄ ν•„μš”ν•˜μ§€λ§Œ, μ‹€ν–‰μ‹œκ°„μ΄ λŠ˜μ–΄λ‚˜λŠ” 원인이 될 수 μžˆμŠ΅λ‹ˆλ‹€. λ˜ν•œ EntityλŠ” 객체 κ·Έλž˜ν”„λ₯Ό 따라 λ‹€λ₯Έ Entity 객체λ₯Ό μžλ™μœΌλ‘œ λ‘œλ“œν•˜λŠ” κΈ°λŠ₯을 μ œκ³΅ν•©λ‹ˆλ‹€ 이 λ•Œ, λΆˆν•„μš”ν•œ Entity 객체λ₯Ό λ‘œλ“œν•˜λŠ” κ²½μš°κ°€ λ°œμƒν•  수 있으며 μ΄λŠ” μ„±λŠ₯ 문제λ₯Ό μ•ΌκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

βœ… μš”μ•½

  • ORMμ—μ„œ μ‚¬μš©λ˜λŠ” 객체이며 λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”κ³Ό λ§€ν•‘λ˜λŠ” μžλ°” 클래슀
  • λ°μ΄ν„°λ² μ΄μŠ€ ν…Œμ΄λΈ”κ³Ό 1:1ꡬ쑰둜 같은 ꡬ성이여야 ν•œλ‹€.
  • λ‹€μ–‘ν•œ 쿼리 λ©”μ„œλ“œμ œκ³΅μœΌλ‘œ κ°œλ°œμžμ—κ²Œ νŽΈλ¦¬ν•¨μ„ κ°€μ Έλ‹€ μ€€λ‹€.
  • λ§Žμ€ 메타데이터 생성, 독립적이지 λͺ»ν•œ 객체 λ‘œλ“œλŠ” μ„±λŠ₯ 이슈λ₯Ό κ°€μ Έμ˜¨λ‹€.
profile
μ™œ? λΌλŠ” 질문이 μ‚¬λΌμ§ˆ λ•ŒκΉŒμ§€

0개의 λŒ“κΈ€