[Spring] JPA Hint & Lock

๋ฐ•์ค€ํ˜•ยท2023๋…„ 11์›” 18์ผ
0

Spring

๋ชฉ๋ก ๋ณด๊ธฐ
8/17
post-thumbnail

๐Ÿ“ŒJPA Hint

JPA ์ฟผ๋ฆฌ ํžŒํŠธ(SQL ํžŒํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ JPA ๊ตฌํ˜„์ฒด(ํ•˜์ด๋ฒ„๋„ค์ดํŠธ)์—๊ฒŒ ์ œ๊ณตํ•˜๋Š” ํžŒํŠธ)

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

@Test
    public void queryHint() {
        //given
        Member member1 = new Member("member1", 10);
        memberRepository.save(member1);
        em.flush(); // ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด์šฉ์„ DB์— ๋™๊ธฐํ™”
        em.clear(); // ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋น„์šฐ๊ธฐ

        //when
        // ๋ณ€๊ฒฝ๊ฐ์ง€๋ฅผ ์œ„ํ•ด ์Šค๋ƒ…์ƒท๊ณผ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ €์žฅํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์ฐจ์ง€ํ•œ๋‹ค.
        Member findMember = memberRepository.findById(member1.getId()).get();

        // ์›๋ณธ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ๋ณ€๊ฒฝ๊ฐ์ง€๊ฐ€ ์ž‘๋™ํ•˜์—ฌ update ์ฟผ๋ฆฌ ์ƒ์„ฑ
        findMember.setUsername("member2");

        em.flush();
    }

flush ๋  ๋•Œ ์›๋ณธ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ตํ•ด์„œ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ์ž๋™์œผ๋กœ update ์ฟผ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๋งŒ์•ฝ์— ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒ๋งŒ ํ•  ๊ฒฝ์šฐ์—” ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด์„œ @QueryHints๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์กฐํšŒํ•˜๋ฉด ๋œ๋‹ค.

// ๋ณ€๊ฒฝ๊ฐ์ง€๋ฅผ ์œ„ํ•œ ์Šค๋ƒ…์ƒท์„ ๋‚จ๊ธฐ์ง€ ์•Š๋Š”๋‹ค.
@QueryHints(value = @QueryHint(name = "org.hibernate.readOnly", value = "true"))
Member findReadOnlyByUsername(String username);

์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ๋ถˆ๋Ÿฌ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด?

ํ…Œ์ŠคํŠธ ์ฝ”๋“œ

@Test
    public void queryHint() {
        //given
        Member member1 = new Member("member1", 10);
        memberRepository.save(member1);
        em.flush(); // ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋‚ด์šฉ์„ DB์— ๋™๊ธฐํ™”
        em.clear(); // ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ๋น„์šฐ๊ธฐ

        //when
        // ๋ณ€๊ฒฝ๊ฐ์ง€๋ฅผ ์œ„ํ•ด ์Šค๋ƒ…์ƒท๊ณผ ์›๋ณธ ๋ฐ์ดํ„ฐ๋ฅผ ๋ชจ๋‘ ์ €์žฅํ•˜๋ฏ€๋กœ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋” ์ฐจ์ง€ํ•œ๋‹ค.
        Member findMember = memberRepository.findReadOnlyByUsername("member1");
        findMember.setUsername("member2");

        // ์›๋ณธ ๋ฐ์ดํ„ฐ์™€ ๋น„๊ตํ•˜์—ฌ ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์ด ์žˆ์œผ๋ฉด ๋ณ€๊ฒฝ๊ฐ์ง€๊ฐ€ ์ž‘๋™ํ•˜์—ฌ update ์ฟผ๋ฆฌ ์ƒ์„ฑ
        em.flush();
    }

setUsername์œผ๋กœ ์กฐํšŒํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์˜€์ง€๋งŒ ๋น„๊ตํ•  ์Šค๋ƒ…์ƒท์ด ์—†์–ด์„œ update ์ฟผ๋ฆฌ๋Š” ์ƒ์„ฑ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ฃผ์˜์ โ—

์ฝ๊ธฐ๋งŒ ํ•œ๋‹ค๊ณ  ํ•ด์„œ ์ „๋ถ€ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ํ•˜๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ์ดํ›„์— ํ•„์š”ํ•œ ๋ถ€๋ถ„์—๋งŒ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค!

๐Ÿ“ŒJPA Lock

Lock์€ ๋ฐ์ดํ„ฐ ์ˆ˜์ •์„ ์œ„ํ•ด ์กฐํšŒํ•˜๊ณ  ์žˆ์„ ๋•Œ DB์— ํ•ด๋‹น ๋ฐ์ดํ„ฐ ์ ‘๊ทผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ๋œ๋‹ค.

@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findLockByUsername(String username);

LockModeType.PESSIMISTIC_WRITE์€ JPA๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๊ณ  ์ด๊ฒƒ์„ ํŽธํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก Data JPA์—์„œ @Lock์„ ์ง€์›ํ•œ๋‹ค.

profile
์œผ์Œฐ ์œผ์Œฐ

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

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด