Spring Data Jpa๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ฉด ํด๋น ์กฐ๊ฑด์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋์ง ํ์ธ ํ๊ธฐ ์ํด exists ์ฟผ๋ฆฌ๊ฐ ํ์ํ ๋๊ฐ ๋ง์ต๋๋ค.
๊ฐ๋จํ ์ฟผ๋ฆฌ์ ๊ฒฝ์ฐ์ ์๋์ ๊ฐ์ด ๋ฉ์๋๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ๋๋ฐ์.
boolean existsByName(String name);
์กฐ๊ธ์ด๋ผ๋ ๋ณต์กํ๊ฒ ๋๋ฉด ๋ฉ์๋๋ช ์ผ๋ก๋ง ์ฟผ๋ฆฌ๋ฅผ ํํํ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
์กฐ๊ฑด๋ฌธ์ด 3๊ฐ ์ด์์ด๊ฑฐ๋, ํ๋๋ช ์ด ๋๋ฌด ๊ธธ๊ฑฐ๋ ์กฐ๊ฑด๋ฌธ ์์ฒด๊ฐ ๋ณต์กํ๋ ๋ฑ๋ฑ
๊ทธ๋์ ์ด๋ฐ ๊ฒฝ์ฐ์ ๋ณดํต @Query ๋ฅผ ์ฌ์ฉํ๋๋ฐ์.
๋ค๋ง ์ด๋ด ๊ฒฝ์ฐ JPQL์์ select์ exists ๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. (select exists ๋ฌธ๋ฒ)
๋จ, where์ exists๋ ์ง์ํฉ๋๋ค.
๊ทธ๋์ exists ๋ฅผ ์ฐํํ๊ธฐ ์ํด ์๋์ ๊ฐ์ด count ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
@Query("SELECT COUNT(o.id) > 0 " +
"FROM Order o " +
"WHERE o.txDate =:txDate")
boolean exists(@Param("txDate") LocalDate txDate);
์ด ๋ฐฉ์์ ์ฑ๋ฅ์ ์ด์๊ฐ ์๋๋ฐ์.
ํ๋์ฉ ์ด๋ค ์ด์๊ฐ ์๋์ง ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
1. count vs exists
SQL๋ก ์ง์ count ์ exists๋ก ์ฑ๋ฅ ๋น๊ต๋ฅผ ํด๋ณด์๋ฉด ํฐ ์ฐจ์ด๋ฅผ ๋๋ผ์ค ์ ์๋๋ฐ์.
5600๋ง๊ฑด ์ ๋ ์์ฌ์๋ ํ ์ด๋ธ์ ๊ธฐ์ค์ผ๋ก count์ exists๋ฅผ ์ํํด๋ณด๋ฉด ๋ค์์ ์ฑ๋ฅ ์ฐจ์ด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
count
- 9.079์ด
exists
- 5.278์ด
๊ฑฐ์ 2๋ฐฐ์ ๊ฐ๊น์ด ์ฑ๋ฅ ์ฐจ์ด๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
๋ฐ์ดํฐ๊ฐ ๋ ๋์ด์ 1์ต๊ฑด์ด ๋๋๋ค๋ฉด ์ฐจ์ด๋ ๋ ๋ฒ์ด์ง๊ฒ ์ฃ ?
์ ์ด๋ ๊ฒ ์ฑ๋ฅ ์ฐจ์ด๊ฐ ๋ ๊น์?
์ด๋ exists๋ ์ฒซ๋ฒ์งธ ๊ฒฐ๊ณผ์์ ๋ฐ๋ก true ๋ฅผ ๋ฆฌํดํ๋ฉด ๋์ง๋ง, count์ ๊ฒฝ์ฐ์ ๊ฒฐ๊ตญ ์ด ๋ช๊ฑด์ธ์ง ํ์ธํ๊ธฐ ์ํด ์ ์ฒด๋ฅผ ํ์ธํด๋ด์ผํ๊ธฐ ๋๋ฌธ์ ์ฑ๋ฅ ์ฐจ์ด๋ ๋น์ฐํ ์ ๋ฐ์ ์์ต๋๋ค.
์ฐธ๊ณ : JOOQ ๋ธ๋ก๊ทธ - Avoid Using COUNT() in SQL When You Could Use EXISTS()
์ ๊ฒฐ๊ณผ๋ก count ์ ์ฑ๋ฅ ์ด์๋ฅผ ํ์ธ ํ์์ต๋๋ค.
์ฌ๊ธฐ์ @Query์์ exists๋ฅผ ์ฌ์ฉํ ์ ์์ผ๋ Querydsl๋ก ๋์ฒดํ ์ ์๋์ง ํ์ธํด๋ณด๊ฒ ์ต๋๋ค.
Querydsl์์ exists?
Querydsl์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๋ exists ๋ฅผ ๋ณด๋ฉด ์ฑ๋ฅ์ ์ด์๊ฐ ์๋ count ์ฟผ๋ฆฌ ๋ฐฉ์์ ์ฌ์ฉํ์์ ์ ์ ์์ต๋๋ค.
(QuerydslJpaPredicateExecutor.exists)
๊ทธ๋์ exists ์ฟผ๋ฆฌ๋ฅผ ์ง์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
์๋ ์ฟผ๋ฆฌ๋ฅผ
select exists (select 1
from book
where id = :id
)
Querydsl๋ก ํํํด๋ณด๊ฒ ์ต๋๋ค.
public Boolean exist(Long bookId) {
return queryFactory.select(queryFactory
.selectOne()
.from(book)
.where(book.id.eq(bookId))
.fetchAll().exists())
.fetchOne();
}
์ปดํ์ผ ์๋ฌ๋ ์๋์ง๋ง ์ค์ ๋ก ์ํ ํด๋ณด์๋ฉด Querydsl์์๋ from์ ์์ด๋ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
from ์ ์ ๋ถ์ด๊ฒ ๋๋ฉด ๊ธฐ์กด์ exists ๋ก ๊ฐ์ ํจ๊ณผ๋ฅผ ์ ํ ๋ณผ ์ ์์ผ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ผ๋ก ์ฐํ๊ฐ ํ์ํฉ๋๋ค.
2. limit 1 ๋ก ๊ฐ์ ํ๊ธฐ
exists๊ฐ count๋ณด๋ค ์ฑ๋ฅ์ด ์ข์ ์ด์ ๊ฐ ๊ฒฐ๊ตญ ์ ์ฒด๋ฅผ ์กฐํํ์ง ์๊ณ ์ฒซ๋ฒ์งธ ๊ฒฐ๊ณผ๋ง ํ์ธํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
๊ทธ๋์ ์ด๊ฑธ ์ง์ ๊ตฌํํด์ ํด๊ฒฐํ๊ฒ ์ต๋๋ค.
์ฆ, limit 1๋ก 1๊ฐ๋ง ์กฐํํ๊ณ ์ด๊ฒ ์๋์ง ์๋์ง๋ก ํ๋จํ๋ ๊ฒ์
๋๋ค.
Querydsl๋ก ํํํ๋ฉด ์๋์ฒ๋ผ ๋ฉ๋๋ค.
public Boolean exist(Long bookId) {
Integer fetchOne = queryFactory
.selectOne()
.from(book)
.where(book.id.eq(bookId))
.fetchFirst(); // limit 1
return fetchOne != null; // 1๊ฐ๊ฐ ์๋์ง ์๋์ง ํ๋จ (์์ผ๋ฉด null์ด๋ผ null์ฒดํฌ)
}
fetchFirst() ๋ ๋ด๋ถ์ ์ผ๋ก limit(1).fetchOne() ๋ก ๋์ด์์ต๋๋ค.
์ฒ์ ์ฑ๋ฅ ํ ์คํธํ๋ ํ ์ด๋ธ์ ๊ทธ๋๋ก ์ ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํด๋ณด๋ฉด?
exists์ ๋์ผํ ์ฑ๋ฅ ํจ๊ณผ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ฆ, exists ๊ฐ ํ์ํ ๊ฒฝ์ฐ์ limit 1๋ก ๋์ฒด๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ถ๊ฐ
๋ฉ์๋ ์ฟผ๋ฆฌ์ exists๋ ์์ ๊ฐ์ด limit์ผ๋ก ์ฟผ๋ฆฌ ์ต์ ํ๋ฅผ ๋ด๋ถ์ ์ผ๋ก ํ๊ณ ์์ต๋๋ค.
๊ฐ๋จํ ์กฐ๊ฑด์ exists๊ฐ ํ์ํ๋ฉด ๋ฉ์๋ ์ฟผ๋ฆฌ๋ก ๊ตฌํํด๋ ๋๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
3. ์ ๋ฆฌ
- count๋ exists์ ๋นํด ์ฑ๋ฅ์ ์ด์๊ฐ ์๋ค.
- ๊ทธ๋ฌ๋ @Query์ Querydsl์์๋ select exists๋ฅผ ์ฌ์ฉํ ์๊ฐ ์๋ค.
- ๊ทธ๋์ select exists๋ฅผ limit 1 ๋ก ๋์ฒดํด์ ์ฌ์ฉํ๋ค.
- ๋จ, JpaRepository์ ๋ฉ์๋ ์ฟผ๋ฆฌ์์ ๋ด๋ถ์ ์ผ๋ก limit 1๋ฅผ ์ฌ์ฉํ๊ณ ์์ด์ ์ฑ๋ฅ์ ์ด์๊ฐ ์๋ค.
ref : https://jojoldu.tistory.com/516
JPA exists ์ฟผ๋ฆฌ ์ฑ๋ฅ ๊ฐ์
Spring Data Jpa๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ฉด ํด๋น ์กฐ๊ฑด์ ๋ฐ์ดํฐ๊ฐ ์กด์ฌํ๋์ง ํ์ธ ํ๊ธฐ ์ํด exists ์ฟผ๋ฆฌ๊ฐ ํ์ํ ๋๊ฐ ๋ง์ต๋๋ค. ๊ฐ๋จํ ์ฟผ๋ฆฌ์ ๊ฒฝ์ฐ์ ์๋์ ๊ฐ์ด ๋ฉ์๋๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ ์ฌ์ฉํ๋๋ฐ์. b
jojoldu.tistory.com
'Backend๐ฑ > Spring JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA์ Spring Data JPA์ ์ฐจ์ด (feat. Hibernate) (0) | 2023.04.23 |
---|---|
JPA ์ฌ์ฉ๋ฒ (JpaRepository) (0) | 2023.04.23 |
JPA ๊ธฐ๋ณธ์์ฑ findBy (0) | 2023.04.21 |
[JPA] ์ฟผ๋ฆฌ ๋ฉ์๋ ์ฌ์ฉ (1) | 2023.04.20 |
Spring Data JPA 1. ์์๊ตฌ์กฐ์ ์ฃผ์ ์ธํฐํ์ด์ค (0) | 2023.04.19 |