์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 |
- ๋งค๋งค์ ๋ต
- ํ์จ
- ์ฐจํธ๋ถ์
- ๊ตญ๋ด์ฌํ
- ์ธ๊ณ๊ฒฝ์
- ํด์ธ์ฌํ
- ๊ธ๋ฆฌ
- C++
- ๊ฒฝ์
- ๊ฒฝ์ ์งํ
- ์ฃผ์
- ์๋ฆฌ์ดํธํ๋
- ์งํ
- ํธ๋ ์ด๋
- ์ํธํํ
- ์ฌํ
- ๋ฐ์ดํฐ๋ถ์
- ๋นํธ์ฝ์ธ
- ๋ง์ง
- ๋ฏธ๊ตญ์ฌํ
- ๋ถ๋์ฐ
- ๋ฐ์ด๋ธ์ค
- ํ์ด์ฌ
- cpp
- Python
- ์ผ์
- ํฌ์
- ์ด๋๋ฆฌ์
- ํ๋ก๊ทธ๋๋ฐ
- ํธ๋ ์ด๋ฉ
- Today
- Total
์ถ์ ๊ณต์
[Spring]JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ ์ฝ๊ฒ ๋ฐฐ์ฐ๊ธฐ – SQL ์์ด JPA๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ! ๋ณธ๋ฌธ
[Spring]JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ ์ฝ๊ฒ ๋ฐฐ์ฐ๊ธฐ – SQL ์์ด JPA๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ!
dkrehd 2025. 5. 10. 06:31๐ง JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ ์ฝ๊ฒ ๋ฐฐ์ฐ๊ธฐ – SQL ์์ด JPA๋ก ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ!
์๋
ํ์ธ์!
์ค๋์ Spring Data JPA์์ SQL ์์ด๋ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ,
๋ฐ๋ก JPQL๊ณผ **๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(Native Query)**์ ๋ํด ์์๋ณผ ๊ฑฐ์์.
์ด๋ฑํ์๋ ์ดํดํ ์ ์๋๋ก ์ฝ๊ณ ์ฌ๋ฏธ์๊ฒ ํ์ด๋ณผ๊ฒ์!
๐ 1. JPQL์ด๋?
๐ฃ JPQL = Java Persistence Query Language
JPQL์ ํ ์ด๋ธ์ด ์๋๋ผ "๊ฐ์ฒด(Entity)"๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ์์ฑํด์.
๋ง์น “ํ์(Student) ์ค์์ ์ด๋ฆ์ด ๋ฏผ์์ธ ์ ๋ฅผ ์ฐพ์์ค”๋ผ๊ณ ๋งํ๋ ๋๋์ด์ฃ !
์:
-- SQL
SELECT * FROM board WHERE title = '์ ๋ชฉ1';
-- JPQL
SELECT b FROM Board b WHERE b.title = '์ ๋ชฉ1';
- Board๋ ํ ์ด๋ธ์ด ์๋๋ผ ์๋ฐ ํด๋์ค
- b๋ ๋ณ๋ช (alias)
์ ๊น! ์ฟผ๋ฆฌ๋ฅผ ๋ง๋๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ๋ค๋ ์๋์?
๋ค! Spring Data JPA๋ ์ฌ์ค ์ฌ๋ฌ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค ์ ์๊ฒ ๋์์ค์.
- ์๋ ์์ฑ:
- ์ฟผ๋ฆฌ ๋ฉ์๋ (Query Methods): ๋ฉ์๋ ์ด๋ฆ์ ํน์ ๊ท์น์ ๋ง๊ฒ ๋ง๋ค๋ฉด (์: findByTitle(String title)), Spring Data JPA๊ฐ ์์์ ์ฟผ๋ฆฌ๋ฅผ ๋๋ฑ ๋ง๋ค์ด์ค์! (๊ฐ์ฅ ๊ฐํธํ ๋ฐฉ๋ฒ ์ค ํ๋์ฃ !)
- JPA Criteria (JPA ํ์ค): ์๋ฐ ์ฝ๋๋ก ์ฟผ๋ฆฌ๋ฅผ ์กฐ๋ฆฝํ๋ ๋ฐฉ์์ด์์. (์ข ๋ ๋ณต์กํ ์ ์์ด์)
- Querydsl (์คํ ์์ค): ์ญ์ ์๋ฐ ์ฝ๋๋ก ์์ ํ๊ณ ์ฝ๊ฒ ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค๊ฒ ๋์์ฃผ๋ ์ธ๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์.
- ์๋ ์์ฑ (์ค๋์ ์ฃผ์ธ๊ณต!):
- EntityManager์ createQuery() ์ฌ์ฉ: JPA ํ์ค ๋ฐฉ๋ฒ์ผ๋ก, ์ง์ JPQL ๋ฌธ์์ด์ ์ ๋ฌํด์ ์ ๋ฆฌ๋ฅผ ๋ง๋ค์ด์.
- @Query ์ด๋ ธํ ์ด์ ์ฌ์ฉ: Spring Data JPA์ ํธ๋ฆฌํ ๊ธฐ๋ฅ! ์ธํฐํ์ด์ค ๋ฉ์๋ ์์ @Query๋ฅผ ๋ถ์ด๊ณ JPQL์ด๋ SQL์ ์ง์ ์จ๋ฃ์ ์ ์์ด์.
์ค๋์ ์ด ์ค์์ ์๋์ผ๋ก ์ฐ๋ฆฌ๋ง์ JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ์ง์คํด ๋ณผ๊ฒ์!
๐ 2. JPQL ์์ฑํ๋ ๋ฐฉ๋ฒ
JPQL์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง๊ฐ ์์ด์!
โ ๋ฐฉ๋ฒ 1: @Query ์ ๋ํ ์ด์ ์ฌ์ฉ
์ฐ๋ฆฌ๊ฐ ๋ง๋ Repository ์ธํฐํ์ด์ค์ ๋ฉ์๋ ์์ @Query ๋ผ๋ ๋ง๋ฒ ๋ฑ์ง๋ฅผ ๋ถ์ด๊ณ , ๊ทธ ์์ JPQL ๋ ์ํผ๋ฅผ ์ ์ด ๋ฃ๋ ๊ฑฐ์์. ๋ง์น ๋ ์ํผ๋ถ์ ํน์ ์๋ฆฌ๋ฒ ์์ "ํน๋ณ ์ง์์ฌํญ: ์ด๋๋ก ์๋ฆฌํ ๊ฒ!" ์ด๋ผ๊ณ ๋ฉ๋ชจ๋ฅผ ๋ถ์ด๋ ๊ฒ๊ณผ ๊ฐ์ฃ .
// BoardRepository.java ์์
public interface BoardRepository extends CrudRepository<Board, Long> {
@Query("SELECT b FROM Board b") // <<-- ๋ฐ๋ก ์ด ๋ถ๋ถ!
List<Board> findAllBoard(); // ๋ฉ์๋ ์ด๋ฆ์ ์์ ๋กญ๊ฒ ์ง์ด๋ ๊ด์ฐฎ์์!
}
- @Query("์ฌ๊ธฐ์_JPQL_๋ ์ํผ_์์ฑ") ํํ๋ก ์ฌ์ฉํด์.
- ์ค์! @Query๋ฅผ ์ฌ์ฉํ๋ฉด, Spring Data JPA๊ฐ ์ด JPQL์ ์คํํด์ฃผ๊ธฐ ๋๋ฌธ์ ๋ฉ์๋ ์ด๋ฆ(findAllBoard())์ ๊ตณ์ด JPA์ ์ฟผ๋ฆฌ ๋ฉ์๋ ์์ฑ ๊ท์น(์: findBy...)์ ๋ฐ๋ฅด์ง ์์๋ ๊ด์ฐฎ์์! ๊ทธ๋ฅ ์ฐ๋ฆฌ๊ฐ ์์๋ณด๊ธฐ ์ฌ์ด ์ด๋ฆ์ผ๋ก ์ง์ผ๋ฉด ๋๋ต๋๋ค.
- ์ฌ๊ธฐ์ Board๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ์ด๋ฆ์ด ์๋๋ผ, ์ฐ๋ฆฌ๊ฐ ๋ง๋ Board ์ํฐํฐ ํด๋์ค ์ด๋ฆ์ด๊ณ , b๋ Board ์ํฐํฐ๋ฅผ ๊ฐ๋ฆฌํค๋ ๋ณ๋ช (alias) ๊ฐ์ ๊ฑฐ์์. JPQL์ ๋์๋ฌธ์๋ฅผ ๊ตฌ๋ถํ๋ ๋ถ๋ถ(์ํฐํฐ ์ด๋ฆ, ํ๋ ์ด๋ฆ ๋ฑ)์ด ์์ผ๋ ์ฃผ์ํด์ผ ํด์!
โ ๋ฐฉ๋ฒ 2: EntityManager.createQuery() ์ฌ์ฉ
๋ง์น ๋ฐ์ดํฐ ๊ด๋ฆฌ์(EntityManager)์๊ฒ ์ ์์ผ๋ก "์ด๋ฐ์ด๋ฐ ์กฐ๊ฑด์ ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์์ฃผ์ธ์" ๋ผ๊ณ ์์ธํ ์์ฒญ์๋ฅผ ์์ฑํด์ ๋ณด๋ด๋ ๊ฒ๊ณผ ๊ฐ์์.
// BoardRepositoryTest3.java ์์ ์ค
// ...
String query = "SELECT b FROM Board b"; // Board ์ํฐํฐ์์ ๋ชจ๋ b๋ฅผ ์ ํํ๋ค!
TypedQuery<Board> tQuery = em.createQuery(query, Board.class); // EntityManager(em)์๊ฒ ์์ฒญ์ ์ ๋ฌ!
List<Board> list = tQuery.getResultList(); // ๊ฒฐ๊ณผ ๋ชฉ๋ก ๋ฐ๊ธฐ!
// ...
- em.createQuery(JPQL๋ฌธ์์ด, ๋ฐํ๋ _์ํฐํฐ_ํ์ .class) ํํ๋ก ์ฌ์ฉํด์.
- JPA์ ํ์ค ๋ฐฉ๋ฒ์ด๋ผ ์ด๋ค JPA ๊ตฌํ์ฒด(์: Hibernate)๋ฅผ ์ฐ๋ ๋์ผํ๊ฒ ๋์ํ์ง๋ง, Spring Data JPA Repository ์ธํฐํ์ด์ค์์๋ ๋ณดํต ์๋ ๋ฐฉ๋ฒ์ ๋ ๋ง์ด ์จ์.
๐ฏ 3. JPQL ๋งค๊ฐ๋ณ์ ์ง์ ํ๊ธฐ
์ฟผ๋ฆฌ์ ๊ฐ์ ๋ฃ๋ ๋ฐฉ๋ฒ์ 2๊ฐ์ง์์!
์์๋๋ก ?1 | b.title = ?1 AND b.writer = ?2 |
์ด๋ฆ์ผ๋ก :๋ณ์๋ช | b.title = :title AND b.writer = :writer |
@Query("SELECT b FROM Board b WHERE b.title=?1 AND b.writer=?2")
List<Board> findByTitleAndWriter2(String title, String writer);
@Query("SELECT b FROM Board b WHERE b.title=:title AND b.writer=:writer")
List<Board> findByTitleAndWriter3(String title, String writer);
๐ 4. ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(Native Query)๋?
JPQL์ด ์๋, ์ง์ง SQL์ ๊ทธ๋๋ก ์ฐ๊ณ ์ถ์ ๋๋ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์จ์!
- ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ข ๋ฅ์ ๋ฐ๋ผ ์กฐ๊ธ์ฉ ๋ค๋ฅผ ์ ์๋, ๊ทธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง์ ์์ํ SQL์ ์ง์ ์ฌ์ฉํ๋ ๊ฑฐ์์.
- ์ธ์ ์ฌ์ฉํ ๊น์?
- JPQL๋ก ํํํ๊ธฐ ์ด๋ ค์ด ๋งค์ฐ ๋ณต์กํ ์ฟผ๋ฆฌ
- ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ง์ ๊ณ ์ ๊ธฐ๋ฅ ์ฌ์ฉ ์
- ํต๊ณ ์ฟผ๋ฆฌ๋ ๋๋ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๋ฑ์์ SQL ์ง์ ํ๋์ด ํ์ํ ๋
- ์ด๋ป๊ฒ ์ฌ์ฉํ ๊น์? @Query ์ด๋ ธํ ์ด์ ์ nativeQuery = true ์ต์ ์ ์ถ๊ฐํ๋ฉด ๋ผ์!
// BoardRepository.java ์์
@Query(value = "SELECT * FROM BOARD", nativeQuery = true) // nativeQuery = true ํ์!
List<Board> findAllBoardSQL();โ
- value ์์ฑ์๋ ์ค์ SQL ๋ฌธ์ฅ์ ์จ์ฃผ๊ณ , nativeQuery = true๋ฅผ ๊ผญ ๋ถ์ฌ์ค์ผ "์ด๊ฑด JPQL ์๋๊ณ ์ง์ง SQL์ด์ผ!" ๋ผ๊ณ Spring Data JPA์๊ฒ ์๋ ค์ค ์ ์์ด์.
- ์ฃผ์! ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ ์ด๋ฆ๊ณผ ์ปฌ๋ผ ์ด๋ฆ์ ์ฌ์ฉํด์ผ ํด์. (์: Board ์ํฐํฐ๊ฐ BOARD_TABLE ํ ์ด๋ธ์ ์ ์ฅ๋๋ค๋ฉด, SQL์ SELECT * FROM BOARD_TABLE์ด ๋์ด์ผ๊ฒ ์ฃ . ์์ ์์๋ ์ํฐํฐ ์ด๋ฆ๊ณผ ํ ์ด๋ธ ์ด๋ฆ์ด Board๋ก ๊ฐ์ ๊ฒฝ์ฐ์์.)
โ ์ผ๋ถ ์ปฌ๋ผ๋ง ์กฐํํ ๋?
@Query(value = "SELECT TITLE, WRITER FROM BOARD", nativeQuery = true)
List<Object[]> findAllBoardSQL2();
- Board ์ ์ฒด๊ฐ ์๋๋ผ ์ ๋ชฉ๊ณผ ๊ธ์ด์ด๋ง ์กฐํํด์
- ๋ฐํ ํ์ ์ List<Object[]> (๋ฐฐ์ด ํํ)
โ ๊ทธ๋ฐ๋ฐ ์ Object[]๋ก ๋ฐ์์ผ ํ ๊น์?
- SQL๋ก SELECT TITLE, WRITER์ฒ๋ผ ์ฌ๋ฌ ์ปฌ๋ผ์ ๊ณจ๋ผ์ ์กฐํํ๋ฉด,
- JPA๋ ์ด ๊ฒฐ๊ณผ๋ฅผ ํ๋์ ํด๋์ค(Board)๋ก ๋ง๋ค ์ ์์ด์. ์๋ํ๋ฉด content, viewCnt ๊ฐ์ ๋ค๋ฅธ ์ ๋ณด๊ฐ ์๊ธฐ ๋๋ฌธ์ด์ฃ !
๊ทธ๋์ JPA๋ ์ด๋ ๊ฒ ์ฒ๋ฆฌํด์:
์ ์ฒด ์ํฐํฐ | List<Board> |
์ผ๋ถ ์ปฌ๋ผ | List<Object[]> |
์๋ฅผ ๋ค์ด,
["title1", "writer1"] ์ด๋ฐ ์์ผ๋ก ๋ฐฐ์ด(Object[])์ ๋ด์์ ๋ฐํํด์.
๐ ๋ง์ฝ ์ปฌ๋ผ์ด 1๊ฐ๋ฟ์ด๋ผ๋ฉด?
@Query(value = "SELECT WRITER FROM BOARD", nativeQuery = true) List<Object> findAllWriters();
- ์ด์ฒ๋ผ ํ๋์ ์ปฌ๋ผ๋ง ์กฐํํ๋ฉด Object[] ๋์ **๊ทธ๋ฅ Object**๋ก ๋ฐ์๋ ๋ผ์!
- ์ด์ ๋ ๊ฐ๋จํด์: ๋ฐฐ์ด์ด ํ์ ์์ผ๋๊น์!
๐ฆ ์ ๋ฆฌ ์์ฝ
SELECT * | List<Board> | ๋ชจ๋ ์์ฑ์ ๊ฐ์ ธ์ค๋ฏ๋ก Board์ ์๋ ๋งคํ ๊ฐ๋ฅ |
SELECT TITLE, WRITER | List<Object[]> | ์ผ๋ถ ์ปฌ๋ผ๋ง ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์ ๋ฐฐ์ด ํํ๋ก ๋ฐ์ |
SELECT WRITER | List<Object> | ์ปฌ๋ผ์ด ํ๋์ผ ๊ฒฝ์ฐ ๋ฐฐ์ด์ด ํ์ ์์ |
์ด์ฒ๋ผ ๋ฐํ ํ์
์ JPQL ๋๋ SQL์์ ์ด๋ค ์ปฌ๋ผ์ ์กฐํํ๋๋์ ๋ฐ๋ผ ๊ฒฐ์ ๋ผ์.
ํผ๋์ ํผํ๋ ค๋ฉด ์ฟผ๋ฆฌ๋ฅผ ์์ฑํ ๋ ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ผ ํ๋์ง๋ ํจ๊ป ์๊ฐํด์ผ ํ๋ต๋๋ค ๐
๐ 5. ํ์ด์ง๊ณผ ์ ๋ ฌ๋ ๊ฐ๋ฅํด์!
โ ํ์ด์ง (Pageable)
@Query("SELECT b FROM Board b")
Page<Board> findAllWithPaging(Pageable pageable);
โ ์ ๋ ฌ (Sort)
Sort sort = Sort.by(Sort.Direction.DESC, "inDate");
List<Board> list = boardRepository.findAll(sort);
- DESC = ๋ด๋ฆผ์ฐจ์
- ASC = ์ค๋ฆ์ฐจ์
์ค์ ์ฝ๋ ์ฟ๋ณด๊ธฐ (ํ ์คํธ ์ฝ๋ ์ค๋ช ) ๐งช
์ด์ ์ค๋ ๋ฐฐ์ด ๋ด์ฉ๋ค์ด ์ค์ ํ ์คํธ ์ฝ๋(BoardRepositoryTest3.java)์์ ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง ์ดํด๋ณผ๊ฒ์!
// BoardRepositoryTest3.java
@SpringBootTest // ์คํ๋ง ๋ถํธ ํ๊ฒฝ์์ ํ
์คํธ!
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) // @Order ์์๋๋ก ํ
์คํธ ์คํ!
class BoardRepositoryTest3 {
@Autowired // EntityManager ์ BoardRepository ๋ฅผ ์คํ๋ง์ด ์ค๋นํด์ค!
public EntityManager em;
@Autowired
private BoardRepository boardRepository;
@BeforeEach // ๊ฐ ํ
์คํธ(@Test) ์คํ ์ ์ ํญ์ ๋จผ์ ์คํ๋๋ ๋ถ๋ถ!
public void testData() {
// ํ
์คํธ๋ฅผ ์ํด 100๊ฐ์ ๊ฒ์๊ธ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๋ง๋ค์ด๋ฌ์.
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)); // ์์ฑ์๋ 0~4๋ฒ์ด ๋ฐ๋ณต๋ผ์.
board.setViewCnt((long)(Math.random()*100));
board.setInDate(new Date());
board.setUpDate(new Date());
boardRepository.save(board); // CrudRepository์ save๋ก ์ ์ฅ!
}
}
// 1. @Query๋ก JPQL ์์ฑ ํ
์คํธ (๋ชจ๋ ๊ฒ์๊ธ ์กฐํ)
@Test
@DisplayName("@Query๋ก JPQL์์ฑ ํ
์คํธ")
public void queryAnnoTest() {
List<Board> list = boardRepository.findAllBoard(); // ์ฐ๋ฆฌ๊ฐ @Query๋ก ๋ง๋ ๋ฉ์๋ ํธ์ถ!
assertTrue(list.size() == 100); // 100๊ฐ ์ ์ฐพ์์๋์ง ํ์ธ!
}
// 2. @Query๋ก JPQL ์์ฑ ํ
์คํธ - ๋งค๊ฐ๋ณ์ ์์ ๊ธฐ๋ฐ
@Test
@DisplayName("@Query๋ก JPQL์์ฑ ํ
์คํธ - ๋งค๊ฐ๋ณ์ ์์")
public void queryAnnoTest2() {
// ์ ๋ชฉ์ด "title1"์ด๊ณ ์์ฑ์๊ฐ "writer1"์ธ ๊ฒ์๊ธ ์ฐพ๊ธฐ! (?1, ?2 ๋ฐฉ์)
List<Board> list = boardRepository.findByTitleAndWriter2("title1", "writer1");
assertTrue(list.size() == 1); // 1๊ฐ ์ฐพ์์ ธ์ผ ํด์!
}
// 3. @Query๋ก JPQL ์์ฑ ํ
์คํธ - ๋งค๊ฐ๋ณ์ ์ด๋ฆ ๊ธฐ๋ฐ
@Test
@DisplayName("@Query๋ก JPQL์์ฑ ํ
์คํธ - ๋งค๊ฐ๋ณ์ ์ด๋ฆ")
public void queryAnnoTest3() {
// ์ ๋ชฉ์ด "title1"์ด๊ณ ์์ฑ์๊ฐ "writer1"์ธ ๊ฒ์๊ธ ์ฐพ๊ธฐ! (:title, :writer ๋ฐฉ์)
List<Board> list = boardRepository.findByTitleAndWriter3("title1", "writer1");
assertTrue(list.size() == 1); // ์ญ์ 1๊ฐ!
}
// 4. @Query๋ก ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(SQL) ์์ฑ ํ
์คํธ (๋ชจ๋ ์ปฌ๋ผ ์กฐํ)
@Test
@DisplayName("@Query๋ก ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(SQL) ์์ฑ ํ
์คํธ")
public void queryAnnoTest4() {
List<Board> list = boardRepository.findAllBoardSQL(); // ๋ค์ดํฐ๋ธ SQL ํธ์ถ!
assertTrue(list.size() == 100); // 100๊ฐ ์ ์ฐพ์์๋์ง ํ์ธ!
}
// 5. @Query๋ก ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(SQL) ์์ฑ ํ
์คํธ (์ผ๋ถ ์ปฌ๋ผ๋ง ์กฐํ)
@Test
@DisplayName("@Query๋ก ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ(SQL) ์์ฑ ํ
์คํธ2")
public void queryAnnoTest5() {
List<Object[]> list = boardRepository.findAllBoardSQL2(); // TITLE, WRITER๋ง!
list.stream() // ๋ฆฌ์คํธ๋ฅผ ์คํธ๋ฆผ์ผ๋ก ๋ณํ
.map(arr -> Arrays.toString(arr)) // ๊ฐ ๋ฐฐ์ด(Object[])์ ๋ฌธ์์ด๋ก ๋ณํ
.forEach(System.out::println); // ํ๋ฉด์ ์ถ๋ ฅ
assertTrue(list.size() == 100); // 100๊ฐ์ [์ ๋ชฉ, ์์ฑ์] ์์ด ๋์๋์ง!
}
// 6. EntityManager์ createQuery๋ก JPQL ์์ฑ ํ
์คํธ
@Test
@DisplayName("createQuery๋ก JPQL์์ฑ ํ
์คํธ")
public void createQueryTest() {
String query = "SELECT b FROM Board b"; // JPQL ๋ฌธ์์ด
TypedQuery<Board> tQuery = em.createQuery(query, Board.class); // EntityManager๋ก ์ฟผ๋ฆฌ ์์ฑ!
List<Board> list = tQuery.getResultList(); // ๊ฒฐ๊ณผ ๊ฐ์ ธ์ค๊ธฐ!
// list.forEach(System.out::println); // ํ์ํ๋ฉด ์ถ๋ ฅํด์ ํ์ธ
assertTrue(list.size() == 100);
}
}
๊ฐ ํ ์คํธ๋ @DisplayName์ผ๋ก ์ด๋ค ํ ์คํธ์ธ์ง ์ด๋ฆ์ ๋ถ์ฌ์คฌ๊ณ , @BeforeEach์ testData() ๋ฉ์๋ ๋๋ถ์ ํญ์ 100๊ฐ์ ๋ฐ์ดํฐ๊ฐ ์๋ ์ํ์์ ์์ํด์. ๊ทธ๋์ ๊ฐ ํ ์คํธ๊ฐ ์๋ก ์ํฅ์ ์ฃผ์ง ์๊ณ ๋ ๋ฆฝ์ ์ผ๋ก ์ ๋์๊ฐ๋์ง ํ์ธํ ์ ์๋ต๋๋ค!
๐ ์ ๋ฆฌ ์์ฝํ
JPQL | Entity ๊ธฐ์ค์ผ๋ก ์์ฑํ๋ JPA ์ ์ฉ SQL |
@Query | JPQL ๋๋ SQL์ Repository์ ์ง์ ์์ฑํ ์ ์์ |
Native Query | ์ค์ DB์ฉ SQL์ ์ง์ ์์ฑ (nativeQuery=true) |
createQuery() | EntityManager๋ฅผ ํตํด JPQL ์ง์ ์คํ |
?1, ?2 | ์์ ๊ธฐ๋ฐ ๋งค๊ฐ๋ณ์ |
:์ด๋ฆ | ์ด๋ฆ ๊ธฐ๋ฐ ๋งค๊ฐ๋ณ์ (@Param ์๋ต ๊ฐ๋ฅ) |
List<Object[]> | ์ผ๋ถ ์ปฌ๋ผ ์กฐํํ ๋ ์ฌ์ฉํ๋ ๋ฐํ ํ์ |
๐ ๋ง๋ฌด๋ฆฌ
์ค๋ ์ฐ๋ฆฌ๋ Spring Data JPA์์ ์ฐ๋ฆฌ๋ง์ ํน๋ณํ ๋ฐ์ดํฐ ์กฐํ ๋ ์ํผ๋ฅผ ๋ง๋๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ, JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ์ ๋ํด ๋ฐฐ์ ์ด์.
- JPQL์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ์๋ฐ ์ํฐํฐ ๊ฐ์ฒด์๊ฒ ๋ง์ ๊ฑฐ๋ ๋ฐฉ์์ด๋ผ ์ข ๋ ๊ฐ์ฒด์งํฅ์ ์ด๊ณ , ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ข ๋ฅ๊ฐ ๋ฐ๋์ด๋ ์ฝ๋๋ฅผ ๊ฑฐ์ ๊ณ ์น ํ์๊ฐ ์๋ค๋ ์ฅ์ ์ด ์์ด์. (๋ง์น ํ์ค์ด๋ก ๋ํํ๋ ๊ฒ๊ณผ ๊ฐ์ฃ !)
- ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์๊ฒ ์ง์ ๊ทธ๋ค์ ์ธ์ด(SQL)๋ก ๋ง์ ๊ฑฐ๋ ๋ฐฉ์์ด๋ผ, ์์ฃผ ํน๋ณํ๊ฑฐ๋ ๋ณต์กํ ์์ ์ ํ ๋, ๋๋ ์ฑ๋ฅ์ ๊ทนํ์ผ๋ก ๋์ด์ฌ๋ฆฌ๊ณ ์ถ์ ๋ ์ ์ฉํด์. (๋ง์น ํน์ ์ง์ญ์ ๋ฐฉ์ธ ์ ๋ฌธ๊ฐ์ฒ๋ผ์!)
Spring Data JPA์ @Query ์ด๋ ธํ ์ด์ ๋๋ถ์ ์ด ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์์ฃผ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉํ ์ ์์ฃ . ์ํฉ์ ๋ง๊ฒ JPQL๊ณผ ๋ค์ดํฐ๋ธ ์ฟผ๋ฆฌ๋ฅผ ์ ์ ํํด์ ์ฌ์ฉํ๋ค๋ฉด, ์ฌ๋ฌ๋ถ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ ์์ฌ๋ก ๋ํํ๋ ๋ฐ์ดํฐ ์ ๋ฌธ๊ฐ๊ฐ ๋ ์ ์์ ๊ฑฐ์์! ๐
'Web Dev > BackEnd' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ์ฟผ๋ฆฌ ๋ฉ์๋! โ JPA์์ SQL ์์ด ์กฐํํ๊ธฐ (0) | 2025.05.09 |
---|---|
[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 |