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 ์ฟผ๋ฆฌ๋ ์์ฑ๋์ง ์๋๋ค.
์ฝ๊ธฐ๋ง ํ๋ค๊ณ ํด์ ์ ๋ถ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ํ๋๊ฒ์ด ์๋๋ผ ์ฑ๋ฅ ํ ์คํธ ์ดํ์ ํ์ํ ๋ถ๋ถ์๋ง ์ฌ์ฉํ๋๊ฒ ์ข๋ค!
Lock์ ๋ฐ์ดํฐ ์์ ์ ์ํด ์กฐํํ๊ณ ์์ ๋ DB์ ํด๋น ๋ฐ์ดํฐ ์ ๊ทผ์ ๋ง๊ธฐ ์ํด์ ์ฌ์ฉ๋๋ค.
@Lock(LockModeType.PESSIMISTIC_WRITE)
List<Member> findLockByUsername(String username);
LockModeType.PESSIMISTIC_WRITE์ JPA๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๊ณ ์ด๊ฒ์ ํธํ๊ฒ ์ฌ์ฉํ๋๋ก Data JPA์์ @Lock์ ์ง์ํ๋ค.