์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- ์ผ์
- ์งํ
- ์๋ฆฌ์ดํธํ๋
- ๋ฐ์ด๋ธ์ค
- ๋ถ๋์ฐ
- ๋งค๋งค์ ๋ต
- ํฌ์
- ์ฌํ
- ํธ๋ ์ด๋
- ์ด๋๋ฆฌ์
- ๊ตญ๋ด์ฌํ
- ํธ๋ ์ด๋ฉ
- ๋ง์ง
- ์ธ๊ณ๊ฒฝ์
- ์ฃผ์
- ์ํธํํ
- ๊ฒฝ์
- ํ๋ก๊ทธ๋๋ฐ
- ๋ฐ์ดํฐ๋ถ์
- Python
- ํด์ธ์ฌํ
- ๊ธ๋ฆฌ
- C++
- ์ฐจํธ๋ถ์
- ๋นํธ์ฝ์ธ
- ๊ฒฝ์ ์งํ
- ํ์ด์ฌ
- ํ์จ
- ๋ฏธ๊ตญ์ฌํ
- cpp
- Today
- Total
์ถ์ ๊ณต์
[Spring] ์ฟผ๋ฆฌ ๋ฉ์๋! — JPA์์ SQL ์์ด ์กฐํํ๊ธฐ ๋ณธ๋ฌธ
[Spring] ์ฟผ๋ฆฌ ๋ฉ์๋! — JPA์์ SQL ์์ด ์กฐํํ๊ธฐ
dkrehd 2025. 5. 9. 03:50
๐งโ๏ธ ๋ง๋ฒ์ฒ๋ผ ์๋ํ๋ ์ฟผ๋ฆฌ ๋ฉ์๋! — JPA์์ SQL ์์ด ์กฐํํ๊ธฐ
์๋
ํ์ธ์! ์ค๋์ SQL ํ ์ค๋ ์ ์ฐ๊ณ ๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์์ฃผ๋, ์ ๋ง ์ ๊ธฐํ ๊ธฐ๋ฅ
**Spring Data JPA์ ์ฟผ๋ฆฌ ๋ฉ์๋(Query Method)**์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค ๐
๐ง ๋จผ์ , JPA๊ฐ ์ง์ํ๋ ์ฌ๋ฌ ์ฟผ๋ฆฌ ๋ฐฉ์!
JPA์์๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ์ํด ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ด์. ์๋์ฒ๋ผ์:
JPQL | JPA ์ ์ฉ SQL (Entity ๊ธฐ์ค์ผ๋ก ์์ฑ, SQL๊ณผ ์ ์ฌ) |
Query Method | ๋ฉ์๋ ์ด๋ฆ๋ง ์ ์ง์ผ๋ฉด ์๋์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ฃผ๋ ๋ง๋ฒ ๊ฐ์ ๊ธฐ๋ฅ |
Criteria | ์ฝ๋ ์กฐํฉ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ง๋๋ JPA ํ์ค ๋ฐฉ์ (ํ์ง๋ง ๋ถํธํด์!) |
Querydsl | Criteria๋ณด๋ค ์ฝ๊ณ ๊ฐ๋ ฅํ ์ฟผ๋ฆฌ ์์ฑ ๋๊ตฌ (์คํ์์ค) |
Native SQL | ์ฐ๋ฆฌ๊ฐ ์ง์ SQL์ ์์ฑํ๋ ๋ฐฉ์ (๋ณต์กํ ์ฟผ๋ฆฌ์ ์ฌ์ฉ) |
๐งโ๏ธ ๊ทธ์ค์์๋ ์ค๋์ ์ฃผ์ธ๊ณต! — ์ฟผ๋ฆฌ ๋ฉ์๋(Query Method)
Spring Data JPA์์๋ ๋ฉ์๋ ์ด๋ฆ๋ง ์ ์ง์ผ๋ฉด,
์๋์ผ๋ก SELECT, DELETE, COUNT ๊ฐ์ SQL์ ๋ง๋ค์ด์ค์!
์์:
List<Board> list = boardRepository.findByTitleAndWriter("์ ๋ชฉ", "๊ธ์ด์ด");
์ด ํ ์ค์ด ์ฌ์ค์ SQL์ ๋์ ํ๊ณ ์์ด์!
SELECT * FROM board WHERE title = '์ ๋ชฉ' AND writer = '๊ธ์ด์ด';
์ฟผ๋ฆฌ ๋ฉ์๋๊ฐ ์ ์ข์๊น?
- ์์ฐ์ฑ ํฅ์: ๋ณต์กํ SQL/JPQL์ ์ง์ ์์ฑํ ํ์ ์์ด ๋ฉ์๋ ์ด๋ฆ๋ง์ผ๋ก ๊ธฐ๋ณธ์ ์ธ ์กฐํ๊ฐ ๊ฐ๋ฅํด ๊ฐ๋ฐ ์๋๊ฐ ๋นจ๋ผ์ง๋๋ค.
- ์ฝ๋์ ๊ฐ๋ ์ฑ: ๋ฉ์๋ ์ด๋ฆ ์์ฒด๊ฐ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ์ด๋ค ์กฐ๊ฑด์ผ๋ก ์ฐพ๋์ง ๋ช ํํ๊ฒ ๋ณด์ฌ์ฃผ๋ฏ๋ก, ์ฝ๋๋ฅผ ์ฝ๋ ์ฌ๋์ด ์ฝ๊ฒ ์ดํดํ ์ ์์ต๋๋ค.
- ์ ์ง๋ณด์ ์ฉ์ด: ์กฐํ ์กฐ๊ฑด์ด ๋ณ๊ฒฝ๋ ๋, ๋ฉ์๋ ์ด๋ฆ๋ง ๊ท์น์ ๋ง๊ฒ ์์ ํ๊ฑฐ๋ ์๋ก์ด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ๋ฉด ๋๋ฏ๋ก ์ ์ง๋ณด์๊ฐ ํธ๋ฆฌํฉ๋๋ค.
- ํ์ ์์ ์ฑ: ์ปดํ์ผ ์์ ์ ๋ฉ์๋ ์ด๋ฆ๊ณผ ๋งค๊ฐ๋ณ์์ ํ์ ์ค๋ฅ๋ฅผ ์ก์ ์ ์์ด ๋ฐํ์ ์ค๋ฅ ๊ฐ๋ฅ์ฑ์ ์ค์ฌ์ค๋๋ค.
- ํ๋ ์์ํฌ ํ์ฉ: Spring Data JPA์ ๊ฐ์ ํ๋ ์์ํฌ์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๋ณ๋์ ์ค์ ์์ด ํ์ฉํ ์ ์์ต๋๋ค.
๐งฑ BoardRepository ํด๋์ค ์ดํด๋ณด๊ธฐ
์๋ ์ฝ๋๋ ์ฟผ๋ฆฌ ๋ฉ์๋๊ฐ ์ด๋ป๊ฒ Repository์ ์ ์๋๋์ง ๋ณด์ฌ์ค๋๋ค!
public interface BoardRepository extends CrudRepository<Board, Long> {
// 1. "์์ฑ์ ์ด๋ฆ์ด [writer]์ธ ๊ธ์ด ์ด ๋ช ๊ฐ์ธ์ง ์ธ์ด์ฃผ์ธ์!"
int countAllByWriter(String writer);
// 2. "์์ฑ์ ์ด๋ฆ์ด [writer]์ธ ๊ธ๋ค์ ๋ชจ๋ ์ฐพ์์ฃผ์ธ์!"
List<Board> findByWriter(String writer);
// 3. "์ ๋ชฉ์ด [title]์ด๊ณ , ์์ฑ์ ์ด๋ฆ์ด [writer]์ธ ๊ธ๋ค์ ๋ชจ๋ ์ฐพ์์ฃผ์ธ์!"
List<Board> findByTitleAndWriter(String title, String writer);
// 4. "์์ฑ์ ์ด๋ฆ์ด [writer]์ธ ๊ธ๋ค์ ์ด์ ๋ชจ๋ ์ง์์ฃผ์ธ์!"
@Transactional // ์ฌ๋ฌ ๊ฐ๋ฅผ ์ง์ธ ๋ ์์ ํ๊ฒ! ํน๋ณํ ์ฒ๋ฆฌ๊ฐ ํ์ํด์.
int deleteByWriter(String writer);
}
๐ ๊ท์น์ ์์ฃผ ๊ฐ๋จํด์:
๋์ + By + ํ๋๋ช (๊ทธ๋ฆฌ๊ณ ํ์ํ๋ฉด And, Or๋ก ์กฐํฉ)
- countAllByWriter: '์ ๋ถ ์ธ์ด์ค' (countAll) + '์์ฑ์ ๊ธฐ์ค์ผ๋ก' (ByWriter)
- findByWriter: '์ฐพ์์ค' (find) + '์์ฑ์ ๊ธฐ์ค์ผ๋ก' (ByWriter)
- findByTitleAndWriter: '์ฐพ์์ค' (find) + '์ ๋ชฉ ๊ธฐ์ค์ผ๋ก' (ByTitle) + '๊ทธ๋ฆฌ๊ณ ' (And) + '์์ฑ์ ๊ธฐ์ค์ผ๋ก' (Writer)
- deleteByWriter: '์ง์์ค' (delete) + '์์ฑ์ ๊ธฐ์ค์ผ๋ก' (ByWriter)
์ด๋ ๊ฒ ์ฐ๋ฆฌ๊ฐ ์ํ๋ '์์ฒญ'์ ์ด๋ฆ์ผ๋ก ์ ์ง์ด์ ์ ์ด ๋์ผ๋ฉด, ์ปดํจํฐ(์ ํํ๋ ์คํ๋ง ๋ฐ์ดํฐ JPA๋ผ๋ ๋๋ํ ์น๊ตฌ)๋ ์ ์ด๋ฆ๋ง ๋ณด๊ณ ๋ ์์์ ๋ณต์กํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํธ(JPQL)๋ฅผ ๋ง๋ค์ด์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์์ค๊ฑฐ๋, ์ธ๊ฑฐ๋, ์ง์์ฃผ๋ ๊ฑฐ์์.
@Transactional ๊ฐ์ ๊ฑด "์ฌ๋ฌ ๊ฐ์ ๊ธ์ ํ ๋ฒ์ ์ง์ฐ๋ ๊ฒ์ฒ๋ผ ์ค์ํ ์์ ์ ์ค๊ฐ์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋ฉด ์ ๋๋๊น, ์ปดํจํฐ๊ฐ ํน๋ณํ ๋ ์ ๊ฒฝ ์จ์ ์์ ํ๊ฒ ์ฒ๋ฆฌํด์ค!" ๋ผ๊ณ ์๋ ค์ฃผ๋ ๊ฑฐ๋ผ๊ณ ์๊ฐํ๋ฉด ์ฌ์์.
๐งช ํ ์คํธ ์ฝ๋๋ก ํ๋์ฉ ์ดํดํด๋ณด๊ธฐ
๐ฏ 1. ํ ์คํธ์ฉ ๋ฐ์ดํฐ ๋ง๋ค๊ธฐ (@BeforeEach)
for (int i = 0; i < 100; i++) {
Board board = new Board();
board.setBno((long)i);
board.setTitle("title" + i);
board.setContent("content" + i);
board.setWriter("writer" + (i % 5)); // writer0 ~ writer4 (5๋ช
)
...
boardRepository.save(board);
}
๐ ์ด 100๊ฐ์ ๊ฒ์๋ฌผ ์์ฑ!
๐ ๊ธ์ด์ด๋ writer0๋ถํฐ writer4๊น์ง, ๊ฐ 20๊ฐ์ฉ ์์ด์.
๐ 2. findByWriter() ํ ์คํธ
List<Board> list = boardRepository.findByWriter("writer1");
assertTrue(list.size() == 20);
writer1์ด ์์ฑํ ๊ธ๋ง 20๊ฐ ์ฐพ๊ธฐ!
SQL๋ก ์ฐ๋ฉด SELECT * FROM board WHERE writer = 'writer1'
๐ 3. countAllByWriter() ํ ์คํธ
int count = boardRepository.countAllByWriter("writer1");
assertTrue(count == 20);
writer1์ ๊ฒ์๊ธ ๊ฐ์ ์ธ๊ธฐ!
SQL: SELECT COUNT(*) FROM board WHERE writer = 'writer1'
๐งจ 4. deleteByWriter() ํ ์คํธ
int deletedCount = boardRepository.deleteByWriter("writer1");
assertTrue(deletedCount == 20);
List<Board> list = boardRepository.findByWriter("writer1");
assertTrue(list.size() == 0);
writer1์ด ์ด ๊ธ์ ๋ชฝ๋ ์ญ์ !
SQL: DELETE FROM board WHERE writer = 'writer1'
๐ง ์ฟผ๋ฆฌ ๋ฉ์๋ ํค์๋ ์์ฝํ
findBy | ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํ | findByTitle(String title) |
countBy | ๊ฐ์ ์ธ๊ธฐ | countByWriter(String writer) |
deleteBy | ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ ์ญ์ | deleteByWriter(String writer) |
And, Or | ์กฐ๊ฑด ์ฌ๋ฌ ๊ฐ ์กฐํฉ | findByTitleAndWriter(String t, String w) |
โ ์ ๋ฆฌํ๋ฉด!
JPQL | Entity ๊ธฐ๋ฐ SQL ๋ฌธ๋ฒ (์กฐ๊ธ ๋ณต์กํ์ง๋ง ์ ์ฐํจ) |
์ฟผ๋ฆฌ ๋ฉ์๋ | ๋ฉ์๋ ์ด๋ฆ๋ง์ผ๋ก SQL์ ์๋ ์์ฑํด์ฃผ๋ ๊ธฐ๋ฅ |
์ฌ์ฉ ์์ | findBy, countBy, deleteBy ๋ฑ๋ฑ |
์ฅ์ | SQL ๋ชฐ๋ผ๋ ์ฝ๊ฒ ๋ฐ์ดํฐ ์กฐํ/์ญ์ ๊ฐ๋ฅ |
๐ ๋ง๋ฌด๋ฆฌ
์ฟผ๋ฆฌ ๋ฉ์๋๋ Spring Data JPA๊ฐ ์ ๊ณตํ๋ ์ต๊ณ ์ ์ ๋ฌผ์
๋๋ค.
๋ณต์กํ SQL ์์ด๋, ์ด๋ฆ๋ง ์ ์ง์ผ๋ฉด JPA๊ฐ ์์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ๋ค ์ค์!
'Web Dev > BackEnd' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring]JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ ์ฝ๊ฒ ๋ฐฐ์ฐ๊ธฐ โ SQL ์์ด JPA๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ! (1) | 2025.05.10 |
---|---|
[Spring] Spring Data JPA โ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์ ์ ๊ฐํธํ๊ฒ ๋ง๋๋ ๊ธฐ์ (0) | 2025.05.09 |
[Spring] JPA, Entity, EntityManager ์ ๋๋ก ์ดํดํ๊ธฐ (1) | 2025.05.06 |
[Spring] ๋ฐ์ดํฐ ๋ชจ๋ธ๋ง ์๋ฒฝ ๊ฐ์ด๋ (0) | 2025.05.02 |
[Spring] AOP ์๋ฒฝ ๊ฐ์ด๋ (0) | 2025.04.30 |