Dev/JPA

JPA Entity์˜ ๊ธฐ๋ณธ์†์„ฑ

OK-๊ฐ€์ž 2022. 3. 2. 17:23

๐Ÿค”Entity

๋„๋งค์ธ ๊ฐ์ฒด์ธ Entity๋Š” ์‹ค์Šต์„ ํ†ตํ•ด ๊ณต๋ถ€ํ•ด๋ณด์ž.

โœ… GenerationType ์ด ๋ญ˜๊นŒ?

@Entity // ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ JPA์—์„œ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๋Š” ๊ฐ์ฒด์ธ๊ฒƒ์„ ์ •์˜.
public class User {

    @Id // ์—”ํ‹ฐํ‹ฐ์—๋Š” ์‹๋ณ„์ž๊ฐ€ ํ•„์š”ํ•œ๋ฐ @ID๋กœ ํ‘œํ˜„.
    @GeneratedValue // GenerationType (IDENTITY, SEQUENCE, TABLE, AUTO)
    private long id;
    /*IDENTITY
    * DB์—์„œ AUTOINCREMENT๋ฅผ ์ด์šฉํ•ด ์ž๋™์œผ๋กœ ID๊ฐ’์ด ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ id๊ฐ’์„ ๋จผ์ € insert ์‹œํ‚จ๋‹ค.
    * ๊ทธ๋ž˜์„œ ํŠธ๋žœ์ ์…˜์ด ๋๋‚˜๊ธฐ ์ „์— , ์ฆ‰ ๋กค๋ฐฑ ๋œ๋‹คํ•˜๋”๋ผ๋„ ์ด๋ฏธ insert ๋˜์–ด ์žˆ์–ด์„œ ๋งˆ์น˜ ์ด๋นจ๋น ์ง„๊ฒƒ ์ฒ˜๋Ÿผ ์ค‘๊ฐ„์— ๋น„๋Š” ํ˜„์ƒ์ด ์ผ์–ด๋‚œ๋‹ค.

    /*SEQUENCE
    * Sequence๋Š” ์˜ค๋ผํด, postqre์—์„œ ์“ฐ๋Š”๋ฐ ์ธ์„œํŠธ๋ฅผ ํ•  ๋•Œ ์‹œ์ฟผ์Šค๋กœ๋ถ€ํ„ฐ ์ฆ๊ฐ€๋œ id ๊ฐ’์„ ๋ฐ›์•„์„œ ์‹ค์ œ id๊ฐ’์— ๋„ฃ๋Š” ๋ฐฉ์‹์ด๋‹ค.
    */

    /*TABLE
    * DB์ข…๋ฅ˜์— ์ƒ๊ด€์—†์ด Table์— id๊ฐ’์„ ์ €์žฅํ•ด ๋‘๊ณ  ์ถ”์ถœํ•˜์—ฌ ์ด์šฉํ•œ๋‹ค.
    */

    /*AUTO
    * ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด AUTO๋ฅผ ์“ด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๊ฐ DB ์ ํ•ฉํ•œ ๊ฐ’์„ ์ž๋™์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋Š”๋ฐ, DB ์˜์กด์„ฑ์ด ์—†์ด ์ฝ”๋”ฉํ• ์ˆ˜ ์žˆ๋‹ค.
    * ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ DB๋Š” ๊ณ ์ •ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์„œ ๊ตฌ์ฒด์ ์ธ ๊ฐ’์„ ์ง€์ •ํ•ด ์‚ฌ์šฉํ•˜๋Š”๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.
    */

    ...
    ...
}
GenerationType์„ ์„ค์ •ํ•ด๋ณด์ž.

โœ… GenerationType (Table)

@Table(name = "user_legacy")
public class User {
    ...
    ...
    ...
}

๐Ÿ‘‰ Test๋ฅผ ํ•ด๋ณด๋ฉด

    create table user_legacy (
       id bigint not null,
        created_at timestamp,
        email varchar(255),
        name varchar(255),
        updated_at timestamp,
        primary key (id)
    )

๐Ÿ‘‰ Test๊ฐ€ ์ˆ˜ํ–‰๋ ๋•Œ table์„ ๋งŒ๋“œ๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

โœ… @indexes(์ธ๋ฑ์Šค) ์™€ @uniqueConstraints(์ œ์•ฝ์กฐ๊ฑด)

@Table(name = "user" ,indexes = {@Index(columnList = "name")}, uniqueConstraints = {@UniqueConstraint(columnNames = {"email"})})
public class User {

๐Ÿ‘‰ ์œ„์™€ ๊ฐ™์ด indexes์™€ uniqueConstraints ์„ค์ •ํ•ด ์ฃผ๋ฉด ddl์ด ์ƒ์„ฑ๋ ๋•Œ index๊ฐ€ ์ƒ์„ฑ์ด ๋˜๊ณ , ์ œ์•ฝ์กฐ๊ฑด์ด ์ƒ์„ฑ๋œ๋‹ค.

Hibernate: create index IDXgj2fy3dcix7ph7k8684gka40c on user (name)
Hibernate: 

    alter table user 
       add constraint UKob8kqyqqgmefl0aco34akdtpe unique (email)

๐Ÿคš ํ•˜์ง€๋งŒ ์œ„์™€๊ฐ™์ด ํ‘œ์‹œํ•œ๋‹ค๊ณ  ํ•ด์„œ ์‹ค์ œ DB์™€ ๋˜‘๊ฐ™์•„ ์ง€๋Š”๊ฑด ์•„๋‹ˆ๋‹ค. JPA๋ฅผ ์ด์šฉํ•ด์„œ DB DDL์„ ์ƒ์„ฑํ• ๋•Œ๋Š” ์ ์šฉ๋˜์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” select delete update ๊ฐ™์€ ์ฟผ๋ฆฌ์— ์•„๋ฌด๋Ÿฐ ์ ์šฉ์ด ์•ˆ๋œ๋‹ค. ์ฆ‰, ์‹ค์ œ DB์— index๊ฐ€ ์—†๋Š”๋ฐ JPA์—์„œ ์„ค์ •ํ•ด์ค€๋‹ค๊ณ  ํ•ด์„œ ์‹คํ–‰์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฑฐ๋‹ค.

โœ… @Colume

    @Id // ์—”ํ‹ฐํ‹ฐ์—๋Š” ์‹๋ณ„์ž๊ฐ€ ํ•„์š”ํ•œ๋ฐ @ID๋กœ ํ‘œํ˜„.
    @GeneratedValue // GenerationType (IDENTITY, SEQUENCE, TABLE, AUTO)
    private long id;

    @NonNull
    private String name;

    @NonNull
    @Column(updatable = false, insertable = false)
    private String email;

    @Column(name ="crtd_at", nullable = false,unique = true)
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;

๐Ÿ‘‰ Column์˜ name์„ ์ง€์ •ํ•˜๋Š”๊ฑด ์š”์ฆ˜์—๋Š” ์•ˆํ•œ๋‹ค. ์™œ๋ƒ๋ฉด ์™ ๋งŒํ•˜๋ฉด ๋ช…์‹œ์ ์œผ๋กœ DB์˜์ปด๋Ÿผ์ด๋ฆ„๊ณผ ์—”ํ‹ฐํ‹ฐ์˜ ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ๊ฐ™๊ฒŒ ํ•˜๊ธฐ๋•Œ๋ฌธ์ด๋‹ค. ํ•˜์ง€๋งŒ DB์ปฌ๋Ÿผ์ด๋ฆ„๊ณผ ์—”ํ‹ฐํ‹ฐ์˜ ๋ณ€์ˆ˜ ์ด๋ฆ„์ด ๋‹ค๋ฅด๋ฉด name์„ ์ด์šฉํ•ด์—ฌ mappingํ•ด์ค€๋‹ค.

๐Ÿ‘‰ nullable ์€ ๋ง ๊ทธ๋Œ€๋กœ notNull์ œ์•ฝ์„ DDL์— ์ถ”๊ฐ€ํ•ด ์ฃผ๋Š” ๊ฒƒ ์ด๋‹ค. ์œ„์— @indexes @uniqueConstraints์™€ ๊ฐ™์ด ์‹ค์ œ DB์— ์ ์šฉ ๋˜๋Š”๊ฑด ์•„๋‹ˆ์ง€๋งŒ, ์‹ค์ œ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๋•Œ notnullํ‘œ์‹œ๋Š” ์ •๋ง ์œ ์šฉํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋ช…์‹œ์ ์œผ๋กœ ์ ์–ด์ฃผ๋Š”๊ฒƒ์ด ์ข‹๋‹ค.

๐Ÿ‘‰ unique๋Š” ์ค‘๋ณต ๋ถˆ๊ฐ€์ธ๊ฑฐ ๋‹ค ์•Œ์ง€? ๊ทธ๋Ÿผ @Table์— ์žˆ๋Š” ์ œ์•ฝ์‚ฌํ•ญ uniqueConstraints์™€ ๋‹ค๋ฅธ์ ์€ ๋ญ˜๊นŒ?
๐Ÿค” uniqueConstraints ๋Š” ํ…Œ์ด๋ธ”์˜ ๋ณตํ•ฉ ์ปฌ๋Ÿผ, ์ฆ‰ 2 ์†์„ฑ์„ ๋ฌถ์–ด์„œ unique๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๊ณ , ์ปฌ๋Ÿผํ•˜๋‚˜๋งŒ ์ง€์ •ํ•˜๊ณ  ์‹ถ์„๋•Œ๋Š” ๊ทธ ๋ณ€์ˆ˜ ์œ„์— unique = true ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์‰ฝ๊ฒŒ ๋งํ•˜๋ฉด ์ด๋Ÿฐ๊ฑฐ ์•„๋‹Œ๊ฐ€?
๐Ÿ‘‡๋ณตํ•ฉ ์œ ๋‹ˆํฌ ex          ๐Ÿ‘‡ ๊ทธ๋ƒฅ ์œ ๋‹ˆํฌ ex
๋ฐ˜ | ๋ฒˆํ˜ธ                     ์ „ํ™”๋ฒˆํ˜ธ                
1  |  3                     01012341234
1  |  2                     01012341235
1  |  3                     01012341236
1  |  4                     01012341237

โœ… @Column์˜ insertable ๊ณผ updatable

๐Ÿ˜ฎ insertable,updatable ์ด ๋‘๋†ˆ์€ ๋‹ค๋ฅธ ์„ค์ •๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ DML์—๋„ ์˜ํ–ฅ์„ ๋ผ์นœ๋‹ค.

    @Column(insertable = false)
    private LocalDateTime createdAt;
    @Column(updatable = false)
    private LocalDateTime updatedAt;
@Test
    void insertAndUpdateTest(){
        /*insert*/
        User user =new User();
        user.setName("martin");
        user.setEmail("martin2@fast.com");

        userRepository.save(user);

        /*update*/
        User user2 = userRepository.findById(1L).orElseThrow(RuntimeException::new);
        user2.setName("marrrrrtin");

        userRepository.save(user2);

    }

๐Ÿ‘‰ ์œ„์™€ ๊ฐ™์ด createdAt ์—๋Š” (insertable = false)๋ฅผ updatable์—๋Š” (updatable = false)๋ฅผ ์ง€์ •ํ•ด ์คฌ๋‹ค. ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ž.

    insert 
    into
        user
        (email, name, updated_at, id) 
    values
        (?, ?, ?, ?)


    update
        user 
    set
        created_at=?,
        email=?,
        name=? 
    where
        id=?

์œ„์˜ ๋กœ๊ทธ์ฒ˜๋Ÿผ insert๋ฌธ์—๋Š” createdAt ์• ํŠธ๋ฆฌ๋ทฐํŠธ๊ฐ€ ๋น ์กŒ๊ณ  update๋ฌธ์—๋Š” updated_at๊ฐ€ ๋น ์ง„๊ฑธ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

โœ… @Transient
Entity๋Š” Data๊ฐ์ฒด๊ธฐ ๋•Œ๋ฌธ์— DB๋ ˆ์ฝ”๋“œ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜์˜ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ์ฒด๋กœ์จ์˜ ์—ญํ• ๋„ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— DB๋ ˆ์ฝ”๋“œ์™€ ๋ณ„๊ฐœ์˜ Data๋ฅผ ๊ฐ€์ง€๊ณ  ์‹ถ์€ Needs๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ๊ทธ๋•Œ ํŠธ๋žœ์ง€์–ธํŠธ๋ฅผ ์“ด๋‹ค.

    @Transient
    private String testData;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ddl์—๋„ ์•ˆ๋“ค์–ด๊ฐ€๊ณ  dml์—๋„ ์•ˆ๋“ค์–ด๊ฐ„๋‹ค. ์˜์†์„ฑ์ฒ˜๋ฆฌ์— ์ œ์™ธ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.์ฆ‰ DB๋ ˆ์ฝ”๋“œ์— ์ฒ˜๋ฆฌ๊ฐ€ ์•ˆ๋œ๋‹ค.

๐Ÿค”๐Ÿค”ENUM Type?

Enum ํƒ€์ž…์€ DB์—๋Š” 0,1, ์ˆœ์„œ๋Œ€๋กœ ๋“ค์–ด๊ฐ„๋‹ค. ์ฆ‰, ๋‚จ์ž,์—ฌ์ž ๊ฐ์ฒด๊ฐ€ ์ฐจ๋ก€๋กœ ์žˆ์–ด๋„ DB์—์„  0,1์œผ๋กœ ๋งตํ•‘๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ํ•ญ์ƒ Enum์„ ์“ฐ๊ธฐ ๋ณด๋‹จ ๊ทธ๋ƒฅ String ํƒ€์ž…์„ ์ป๋‹ค. Jpa์—์„œ๋„ ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผํ• ๊นŒ?
์‹ค์Šตํ•ด๋ณด์ž.
โœ… enum type ํด๋ž˜์Šค์ƒ์„ฑ

public enum Gender {
    MALE,
    FEMALE
}

โœ… User ์—”ํ‹ฐํ‹ฐ์— ์ด๋„˜ํƒ€์ž… gender ์‚ฌ์šฉ.

private Gender gender;

โœ… nativeQuery ์ฟผ๋ฆฌ๋ฅผ ์•„์ง ์•ˆ๋ฐฐ์› ์ง€๋งŒ, ์ผ๋‹จ UserRepository์— ์—ฐ์Šต์šฉ์œผ๋กœ ์จ๋ณด์ž.

    @Query(value = "select * from user limit 1;", nativeQuery = true)
    Map<String, Object> findRawRecord();

โœ… ๊ทธ๋ฆฌ๊ณ  Test

 @Test
    void enumTest() {
        User user = userRepository.findById(1L).orElseThrow(RuntimeException::new);
        user.setGender(Gender.MALE);

        userRepository.save(user);

        userRepository.findAll().forEach(System.out::println);

        System.out.println(userRepository.findRawRecord().get("gender"));
    }


์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋‹ค ์‹ถ์ด MALE์˜ ์  ๋”๋ฅผ ๋ณด๋‹ˆ 0์ด๋ผ๋Š” ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค. ์ž ์ด์ œ Enum Data์œ„์—

    @Enumerated(value = EnumType.STRING)
    private Gender gender;

@Enumerated(value = EnumType.STRING)
๋‹ค์‹œ Testํ•˜๋ฉด


์ด์ œ ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅ๋œ๋‹ค.
์ด๊ฑฐ ์ •๋ง ์ค‘์š”ํ•˜๋‹ค. ๐Ÿ˜ก

'Dev > JPA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

JPA ์—ฐ๊ด€๊ด€๊ณ„ (1:N)  (0) 2022.03.02
JPA EntityListener  (0) 2022.03.02
JPA ์ฟผ๋ฆฌ๋ฉ”์†Œ๋“œ ์ •๋ ฌ  (0) 2022.03.02
JPA ์ฟผ๋ฆฌ๋ฉ”์†Œ๋“œ(QueryMethod)  (0) 2022.03.02
JPA Repository Interface ์ƒ์„ธ 2  (0) 2022.03.02