JPA - QueryMethods

์ด์ข…์ฐฌยท2023๋…„ 2์›” 21์ผ
0

๐Ÿ“– QueryMethods?

JPA Repository์—์„œ ์ œ๊ณตํ•˜๋Š” Query Methods๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—๊ฒŒ ์งˆ์˜ํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. QueryMethods๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ์ฟผ๋ฆฌ๋ฅผ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์ด ํ–ฅ์ƒ๋˜๋Š” ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

QueryMethods๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„ ๊ทœ์น™์„ ์ด์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด findBy๋’ค์— Id์™€ ๊ฐ™์€ ์†์„ฑ์„ ์ด์šฉํ•˜์—ฌ ํ•ด๋‹น Id๋ฅผ ๊ฐ€์ง„ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์„ฑ ๋ฐฉ๋ฒ•

repository์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜์—ฌ JpaRepository๋ฅผ ์ƒ์†๋ฐ›์Šต๋‹ˆ๋‹ค. Query Methods์ž‘์„ฑ์€ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ํ†ตํ•ด ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. Spring Data JPA์—์„œ๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋”ฐ๋ผ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆํ•œ ์ด๋ฆ„์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

JPA Repository

public interface UserRepository extends JpaRepository<UserData, Long> {
    UserData findByEmail(String email);

    UserData findById(int id);

    List<UserData> findAllByName(String name);
}

Test

    @Test
    void findTest() {
        UserData data1 = repository.findByEmail("dennis@naver.com");
        List<UserData> data2 = repository.findAllByName("martin");
        UserData data3 = repository.findSomethingByEmail("dennis@naver.com");
        System.out.println("data 1 : "+data1);
        System.out.println("data 2 : "+data2);
        System.out.println("data 3 : "+data3);
    }

data 1 : UserData(id=2, name=dennis, email=dennis@naver.com, createdAt=2023-02-21T15:00:13.745773, updatedAt=2023-02-21T15:00:13.745773)

data 2 : [UserData(id=1, name=martin, email=martin@naver.com, createdAt=2023-02-21T15:00:13.744833, updatedAt=2023-02-21T15:00:13.744833), UserData(id=5, name=martin, email=martin@another.com, createdAt=2023-02-21T15:00:13.746473, updatedAt=2023-02-21T15:00:13.746473)]

data 3 : UserData(id=2, name=dennis, email=dennis@naver.com, createdAt=2023-02-21T15:00:13.745773, updatedAt=2023-02-21T15:00:13.745773)

๋งŒ๋“ค์–ด์ง„ ์ฟผ๋ฆฌ๋ฌธ

data1

    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.email=?

data2

    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.name=?

data3

    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.email=?

data2์˜ ๊ฒฝ์šฐ find{All}By{Name} ๋ฉ”์„œ๋“œ ๋„ค์ž„์— ์ฟผ๋ฆฌ๋ฌธ์„ ๋งŒ๋“ค๊ณ  ๊ฒฐ๊ณผ๊ฐ’๋„ ์ž˜ ๋‚˜์™”์Šต๋‹ˆ๋‹ค.

data1, data3์€ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ ๋„ค์ž„์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ๋™์ผํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์™”์Šต๋‹ˆ๋‹ค. find{Something}By{Email}์˜ ๋ฉ”์„œ๋“œ์—์„œ Something์ด ํ•ด์„๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์•Œ ์ˆ˜ ์—†๋Š” ์˜๋ฏธ์˜ ๋‹จ์–ด๋Š” ๋ฌด์‹œํ•˜๊ณ  ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์ ˆํ•˜๊ฒŒ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทœ๊ฒฉ์—๋Š” ๋งž๊ฒŒ ์ž‘์„ฑํ•˜์˜€์œผ๋‚˜ ์˜๋ฏธ๋ฅผ ์•Œ๊ธฐ ํž˜๋“  ๋ฉ”์„œ๋“œ ๋„ค์ž„์€ ์œ„์˜ ์˜ˆ์‹œ ์ฒ˜๋Ÿผ ํ•ด๋‹น ๋‹จ์–ด๋ฅผ ๋นผ๊ณ  ์‹คํ–‰ํ•˜๊ณ  ์—๋Ÿฌ๋ฅผ ์ถœ๋ ฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ Repository์— ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š๋Š”๊ฑธ๊นŒ์š”? ๊ทธ๋ ‡์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ถ€์ ์ ˆํ•œ ๋ฉ”์„œ๋“œ

    @Test
    void runTimeTest() {
        UserData data = repository.findByByName("dennis");
        System.out.println("data : "+data);
    }

์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ์•„๋‹Œ ๋Œ€์ƒ์„ ์ฐพ์ง€ ๋ชปํ•ด ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค์ง€ ๋ชปํ•œ๋‹ค๋Š” ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด์ฒ˜๋Ÿผ ๋ฉ”์„œ๋“œ ์ด๋ฆ„์œผ๋กœ ์ฟผ๋ฆฌ๋ฌธ์ด ์–ด๋–ป๊ฒŒ ์ž‘์„ฑ๋˜๋Š”์ง€ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด์ œ๊นŒ์ง€๋Š” ์กฐ๊ฑด์ด ํ•˜๋‚˜ ํ˜น์€ ํ•˜๋‚˜์˜ ์กฐ๊ฑด์— ๋งŒ์กฑํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์กฐ๊ฑด์ด 2๊ฐœ์ธ ๊ฒฝ์šฐ ์—ญ์‹œ ๋™์ผํ•˜๊ฒŒ ๋ฉ”์„œ๋“œ ๋„ค์ž„์œผ๋กœ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ

    @Test
    void findAndOrTest() {
        UserData data1 = repository.findByNameAndEmail("martin", "martin@another.com");
        List<UserData> data2 = repository.findByNameOrEmail("martin", "dennis@naver.com");
        List<UserData> data3 = repository.findFirstByName("martin");
        System.out.println("data 1 : "+data1);
        System.out.println("data 2 : "+data2);
        System.out.println("data 3 : "+data3);
    }

Query

    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.name=? 
        and u1_0.email=?
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.name=? 
        or u1_0.email=?
    select
        u1_0.id,
        u1_0.created_at,
        u1_0.email,
        u1_0.name,
        u1_0.updated_at 
    from
        user_data u1_0 
    where
        u1_0.name=? fetch first ? rows only

์‹คํ–‰๊ฒฐ๊ณผ

data 1 : UserData(id=5, name=martin, email=martin@another.com, createdAt=2023-02-21T15:42:19.088832, updatedAt=2023-02-21T15:42:19.088832)

data 2 : [UserData(id=1, name=martin, email=martin@naver.com, createdAt=2023-02-21T15:42:19.086632, updatedAt=2023-02-21T15:42:19.086632), UserData(id=2, name=dennis, email=dennis@naver.com, createdAt=2023-02-21T15:42:19.088095, updatedAt=2023-02-21T15:42:19.088095), UserData(id=5, name=martin, email=martin@another.com, createdAt=2023-02-21T15:42:19.088832, updatedAt=2023-02-21T15:42:19.088832)]

data 3 : [UserData(id=1, name=martin, email=martin@naver.com, createdAt=2023-02-21T15:42:19.086632, updatedAt=2023-02-21T15:42:19.086632)]

๋ฉ”์„œ๋“œ ๋„ค์ž„์˜ ์˜๋„๋Œ€๋กœ ์ž‘์„ฑ๋œ ์ฟผ๋ฆฌ๋ฌธ๊ณผ ์‹คํ–‰๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ ๋ฐ–์—๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

return type

JPA Repository์—์„œ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ํ˜•์€ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์œผ๋กœ ์—”ํ‹ฐํ‹ฐ, ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ฐ˜ํ™˜ํ˜•์œผ๋กœ๋Š” ํ”„๋กœ๋•์…˜ ํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ๋•์…˜์€ ์—”ํ‹ฐํ‹ฐ์˜ ์ผ๋ถ€ ์†์„ฑ๋งŒ ์„ ํƒํ•˜์—ฌ ์กฐํšŒํ•˜๊ณ  ์ผ๋ถ€ ์†์„ฑ๋งŒ ๋ฐ˜ํ™˜ํ•˜์—ฌ int,long๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธํ˜• ๋ฐ˜ํ™˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ผ๋ถ€ ์†์„ฑ์ด ๋“ค์–ด์žˆ๋Š” ์ธํ„ฐํŽ˜์ด์Šค, ํด๋ž˜์Šค๋กœ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ํ›„์ž์˜ ๊ฒฝ์šฐ DTO ๊ฐœ๋…์„ ์ด์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๋ณ€ํ™˜ํ•˜์—ฌ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ๋ฉ”์„œ๋“œ๊ฐ€ null ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๋•Œ ๋ช…์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•˜์—ฌ Optional๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ, ํ•ด๋‹นํ•˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ๊ฐ€ null์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ ํ˜ธ์ถœํ•œ ์ฝ”๋“œ์—์„œ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Optional ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๊ฐ€ null๋ฐ˜ํ™˜์‹œ Optional.empty()๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ํ˜ธ์ถœํ•œ ์ฝ”๋“œ์—์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค.

์กฐํšŒ ๊ฒฐ๊ณผ๊ฐ€ null์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์–ด Optional ๊ฐ์ฒด๋กœ ๊ฐ์‹ธ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํ•ด๋‹น ๊ฐ์ฒด๊ฐ€ null์ธ์ง€ ์•„๋‹Œ์ง€ ๋ช…์‹œ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜์—ฌ ์•ˆ์ •์„ฑ๊ณผ ๊ฐ€๋…์„ฑ์ด ๊ฐœ์„ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฉ”์„œ๋“œ๊ฐ€ null์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ชจ๋‘ ์ฒดํฌํ•˜๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Wrapperํด๋ž˜์Šค ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‘๊ฐœ์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๋ฏ€๋กœ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์ฐจ์ง€ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. Optional์ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์—๋งŒ ์‚ฌ์šฉํ•˜๋ฉด ์œ ์—ฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CRUD

๊ธฐ๋ณธ์ ์ธ CRUD์˜ ๊ฒฝ์šฐ JpaRepository๋ฅผ ์ƒ์†๋ฐ›๊ฒŒ ๋˜๋ฉด ๋”ฐ๋กœ ์ ์ง€ ์•Š์•„๋„ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. @Entity๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  JpaRepository๋ฅผ ์ƒ์†๋ฐ›์•˜์œผ๋ฉด Create์—ญํ• ์€ ์ž๋™์œผ๋กœ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ๋ฅผ ๋“ค์–ด๊ฐ€์„œ ๋ณด๋ฉด save,delete,find ์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋งŒ ๋ณด์ด๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. delete๋Š” D, find๋Š” R์— ํ•ด๋‹น๋˜๋Š”๋ฐ save๋Š” insert,update๋ฅผ ๋‹ค ํ•ด์ฃผ๋Š” ๊ฑธ๊นŒ์š”?

save ์˜ˆ์ œ

    @Test
    void saveTest() {
        UserData data = new UserData("name", "mail");
        repository.save(data);
        printList();
        data.setName("Chan");
        repository.save(data);
        printList();
    }

๊ฒฐ๊ณผ

UserData(id=6, name=name, email=mail, createdAt=null, updatedAt=null)
UserData(id=6, name=Chan, email=mail, createdAt=null, updatedAt=null)

์ฒซ๋ฒˆ์งธ๋Š” insert, ๋‘๋ฒˆ์งธ ๊ฒฝ์šฐ์—๋Š” update๊ฐ€ ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. save๋ฉ”์„œ๋“œ์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

	@Transactional
	@Override
	public <S extends T> S save(S entity) {

		Assert.notNull(entity, "Entity must not be null");

		if (entityInformation.isNew(entity)) {
			em.persist(entity);
			return entity;
		} else {
			return em.merge(entity);
		}
	}

JpaRepository์˜ save๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ๋˜๋ฉด CrudRepository์—์„œ save๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ๊ตฌํ˜„๋œ ๋ฉ”์„œ๋“œ๋Š” SimpleJpaRepository์—์„œ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด Entity๊ฐ€ null์ด ์•„๋‹Œ๊ฒฝ์šฐ์— ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ isNew(entity) ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ true์ธ ๊ฒฝ์šฐ insert, false์ธ ๊ฒฝ์šฐ update๋กœ ์ง„ํ–‰๋˜๋Š”๊ฑฐ ๊ฐ™์ด ๋ณด์ž…๋‹ˆ๋‹ค. ์ข€ ๋” ์ƒ์„ธํžˆ ํ™•์ธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

isNew(entity)

	public boolean isNew(T entity) {

		ID id = getId(entity);
		Class<ID> idType = getIdType();

		if (!idType.isPrimitive()) {
			return id == null;
		}

		if (id instanceof Number) {
			return ((Number) id).longValue() == 0L;
		}

		throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType));
	}

ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ id๊ฐ€ null ๋˜๋Š” 0์ธ์ง€ ํŒ๋‹จํ•˜์—ฌ ํ•ด๋‹น๋˜๋Š” ๊ฒฝ์šฐ์— ์ƒˆ๋กœ์šด ์—”ํ‹ฐํ‹ฐ์ž„์„ booleanํƒ€์ž…์œผ๋กœ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.

์ด ๊ณผ์ •์„ ๊ฑฐ์ณ persist() ํ˜ธ์ถœ ํ›„ entity๋ฐ˜ํ™˜ ํ˜น์€ merge()๋ฅผ ํ˜ธ์ถœ ํ›„ entity ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋“ค์€ EntityManager์— ์†ํ•˜์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค. JPA๋Š” EntityManager, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์ง€ํ•˜๊ณ  ํ•„์š”ํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Application์ด ์‹œ์ž‘๋  ๋•Œ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ bean์— ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

EntityManager๋Š” Entity์˜ ์ƒ๋ช… ์ฃผ๊ธฐ์™€ ํŠธ๋žœ์žญ์…˜ ๋“ฑ์„ ๊ด€๋ฆฌํ•˜๋ฉฐ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ(์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜๊ตฌ ์ €์žฅํ•˜๋Š” ํ™˜๊ฒฝ)์— ์ ‘๊ทผํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์ด์— ๊ฐ์ฒด๋ฅผ ๋ณด๊ด€ํ•˜๋Š” ๊ฐ€์ƒ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ™์€ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ง€๋ฉฐ ์—”ํ‹ฐํ‹ฐ ๋งค๋‹ˆ์ €๋ฅผ ํ†ตํ•ด ์ ‘๊ทผ ๋ฐ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ, EntityManager์—์„œ ๊ด€๋ฆฌ๋˜๋ฉด Entity์—๋Š” ์ƒ๋ช… ์ฃผ๊ธฐ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

Entity ์ƒ๋ช…์ฃผ๊ธฐ

  • ๋น„์˜์†(new/transient) : ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ํ˜„์žฌ ๊ด€๊ณ„๊ฐ€ ์—†๋Š” ์ƒํƒœ
  • ์‚ญ์ œ(removed) : ์‚ญ์ œ๋œ ์ƒํƒœ
  • ์˜์†(persisted) : ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋œ ์ƒํƒœ
  • ์ค€์˜์†(detached) : ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ €์žฅ๋˜์—ˆ๋‹ค๊ฐ€ ๋ถ„๋ฆฌ๋œ ์ƒํƒœ -> ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ

๋‹ค์‹œ ๋Œ์•„์™€์„œ persist(), merge()์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. Entity๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ•˜๋ฉด ๋น„์˜์† ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— save -> TRANSIENT ์ƒํƒœ ํ™•์ธ -> persist()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์˜์†์ƒํƒœ๋กœ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

๋™์ผํ•œ Entity๋ฅผ ๊ฐ€์ง€๊ณ  save๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ ์ƒํƒœ๊ฐ€ ๋น„์˜์† ์ƒํƒœ๊ฐ€ ์•„๋‹Œ ๊ฒƒ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ด ๋•Œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์—์„œ ๋‚˜์™”๊ธฐ ๋•Œ๋ฌธ์— Detached์ƒํƒœ ์ž…๋‹ˆ๋‹ค. 1์ฐจ ์บ์‹œ์— ํ•ด๋‹น ์—”ํ‹ฐํ‹ฐ์˜ ์‹๋ณ„์ž๊ฐ€ ์žˆ์œผ๋ฉด db์กฐํšŒ๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ์—†๋Š” ๊ฒฝ์šฐ db์กฐํšŒ๋ฅผ ํ•˜์—ฌ ์ž…๋ ฅ๋ฐ›์€ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋ณต์‚ฌํ•œ ๊ฐ์ฒด๋ฅผ db์— ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, merge() -> select ์ดํ›„ insert๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ˜•์‹์ž…๋‹ˆ๋‹ค.

๐Ÿค” ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ์ด์œ ๋Š”?

QueryMethods๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ๋ณต์žกํ•œ ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐœ๋ฐœ ์ƒ์‚ฐ์„ฑ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. QueryMethods๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์— ๋”ฐ๋ผ ๋‹ค์–‘ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์„ ์ œ๊ณตํ•˜์—ฌ ์ ์ ˆํ•˜๊ฒŒ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์žฅ์ ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—ฐ๋™๋˜๋Š” ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ฐœ๋ฐœํ•˜๋Š”๋ฐ ๋„์›€์„ ์ค๋‹ˆ๋‹ค.

โŒ ๋ฌธ์ œ๊ฐ€ ๋˜๋Š” ๊ฒฝ์šฐ -> ์ œ์•ฝ ์‚ฌํ•ญ

1. ๋ฉ”์„œ๋“œ ๋„ค์ด๋ฐ

QueryMethod๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ”์„œ๋“œ๋ช…์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์ฟผ๋ฆฌ๋ฌธ์˜ ์ œ์•ฝ

JPA Repository์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋Š” ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผํ•˜๋Š” ์ œ์•ฝ์ด ์ƒ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ์œ ์—ฐ์„ฑ ๋ฌธ์ œ

๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ ๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ๋ณ€๊ฒฝ์„ ์œ„ํ•ด์„œ๋Š” ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๋ฉฐ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฌธ์˜ ๊ฒฝ์šฐ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ œ์•ฝ์‚ฌํ•ญ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ORM์— ๋Œ€ํ•œ ์ดํ•ด๋ฅผ ๋†’์ด๊ณ  ์ ์ ˆํ•œ ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ตœ์ ํ™”๋ฅผ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

โœ… ์š”์•ฝ

  • JPA QueryMethods๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผํ•˜๊ธฐ์œ„ํ•œ ์งˆ์˜๋ฌธ์„ SpringFramework์—์„œ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ด์ค€๋‹ค.
  • ๋ฉ”์„œ๋“œ๋ช…์œผ๋กœ ์ฟผ๋ฆฌ๋ฌธ์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ์ฟผ๋ฆฌ๋ฌธ์„ ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
  • ๊ธฐ๋ณธ์ ์ธ CRUD๋Š” ๋ฉ”์„œ๋“œ ์ž‘์„ฑ์—†์ด๋„ ์ œ๊ณตํ•œ๋‹ค.
  • ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฌธ์€ ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜, ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์„์ˆ˜๋„ ์žˆ๋‹ค.
profile
์™œ? ๋ผ๋Š” ์งˆ๋ฌธ์ด ์‚ฌ๋ผ์งˆ ๋•Œ๊นŒ์ง€

0๊ฐœ์˜ ๋Œ“๊ธ€