๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  • ์žฅ์›์ต ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ
๐Ÿ“š ์‹œ๋ฆฌ์ฆˆ/- ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA

[๋ฐฐ์›Œ๋ณด์ž Spring Data JPA] ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์™€ @Query๋ฅผ ์ด์šฉํ•œ ์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ

by Wonit 2021. 4. 10.

ํ•ด๋‹น ๊ธ€์€ ๋ฐฐ์›Œ๋ณด์ž Spring Data JPA ์‹œ๋ฆฌ์ฆˆ ์ž…๋‹ˆ๋‹ค.
ํ•ด๋‹น ์‹œ๋ฆฌ์ฆˆ์˜ ๋‚ด์šฉ์ด ์ด์–ด์ง€๋Š” ํ˜•ํƒœ์ด๋ฏ€๋กœ ๊ธ€์˜ ๋‚ด์šฉ ์ค‘์— ์ƒ๋žต๋˜๋Š” ๋ง๋“ค์ด ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!


์•ž์„  ํฌ์ŠคํŒ…์—์„œ ์šฐ๋ฆฌ๋Š” JpaRepository ๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” CRUD ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜๋‹ค.

 

์ž ๊น ์–ธ๊ธ‰ํ•˜๊ธฐ๋„ ํ•˜์˜€๋Š”๋ฐ, ๋งŒ์•ฝ JpaRepository ๊ฐ€ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ๋“ค์„ ์‚ฌ์šฉํ•ด์•ผํ•  ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

 

์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž PK๊ฐ€ ์•„๋‹Œ ์ด๋ฆ„์œผ๋กœ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„ ๋•Œ, ์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ์ด๋ฉ”์ผ๋กœ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„๋•Œ, ๋‚˜์ด๊ฐ€ 20์‚ด ์ด์ƒ์ธ ์‚ฌ์šฉ์ž๋ฅผ ์กฐํšŒํ•˜๊ณ  ์‹ถ์„ ๋•Œ ๋“ฑ๋“ฑ..

 

๊ทธ๋Ÿผ ์–ด์ฉ” ์ˆ˜ ์—†์ด ์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ

์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ๋ž€? ๋ง ๊ทธ๋Œ€๋กœ JPA๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์•„๋‹Œ ์‚ฌ์šฉ์ž๊ฐ€ ์ •์˜ํ•œ ๋Œ€๋กœ ์ฟผ๋ฆฌ๊ฐ€ ์ƒ์„ฑ ํ˜น์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ข…์†์ ์ธ Native Query ๊ฐ€ ์ƒ์„ฑ ๋˜๋Š” ๊ฒƒ์„ ๋ง ํ•œ๋‹ค.

 

JPA ์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•œ๋‹ค.

 

  1. Named Query
  2. ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ
  3. @Query ์–ด๋…ธํ…Œ์ด์…˜

๊ฐ€ ์กด์žฌํ•œ๋‹ค.

 

๋„ค์ž„๋“œ ์ฟผ๋ฆฌ๋Š” ๋ง ๊ทธ๋Œ€๋กœ ์ฟผ๋ฆฌ์— ์ด๋ฆ„์„ ๋ถ€์—ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ๋ฐ, ์ปดํŒŒ์ผ์‹œ ํƒ€์ž…์ฒดํฌ, ๊ฐ€๋…์„ฑ๊ณผ ๊ฐ™์€ ๋ถ€๋ถ„์—์„œ ๋ฌธ์ œ๊ฐ€ ์กฐ๊ธˆ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— @Query ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•  ์šฐ๋ฆฌ์—๊ฒŒ๋Š” ๋‹น์žฅ ํ•„์š”ํ•˜์ง€๋Š” ์•Š๋‹ค.

 

๊ทธ๋Ÿฌ๋ฏ€๋กœ ์šฐ๋ฆฌ๋Š” 2๋ฒˆ 3๋ฒˆ, ์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ์™€ @Query ์— ๋” ์ง‘์ค‘ํ•˜๋ฉด ๋œ๋‹ค.

 

์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ

์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๊ฐ€ ์ƒ๊ฐํ•˜๋Š” JPA์—์„œ ๊ฐ€์žฅ ์‹ ๊ธฐํ•œ ๊ธฐ์ˆ ? ์ด๋‹ค.

 

๋‚˜๋Š” Intellij ๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, Intellij ์—์„œ Repository ์ธํ„ฐํŽ˜์ด์Šค ์— ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ด๋ณด์ž.

 

Optional<User> find ๊นŒ์ง€๋งŒ ์ณ๋„ ์•„๋ž˜์™€ ๊ฐ™์€ snippet ์ด ๋“ฑ์žฅํ•œ๋‹ค.

 

๋ญ˜๊นŒ..?

 

๋Œ€์ถฉ ๊ฐ์ด ์žกํžˆ์ง€ ์•Š๋Š”๊ฐ€?

 

๊ทธ๋ ‡๋‹ค. ๋ฉ”์„œ๋“œ ์ด๋ฆ„์œผ๋กœ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ์ฟผ๋ฆฌ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ์€ Spring Data JPA ์—์„œ ์ •ํ•ด๋†“์€ ๋„ค์ด๋ฐ ์ปจ๋ฒค์…˜์„ ์ง€ํ‚ค๋ฉด JPA๊ฐ€ ํ•ด๋‹น ๋ฉ”์„œ๋“œ ์ด๋ฆ„์„ ๋ถ„์„ํ•ด์„œ ์ ์ ˆํ•œ JPQL ์„ ๊ตฌ์„ฑํ•œ๋‹ค.

 

๋Œ€ํ‘œ์ ์ธ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

  • And
  • Or
  • Is, Equals
  • Between
  • LessThen
  • After, Before
  • IsNull
  • OrderBy
  • Not

์ž์„ธํ•œ ์‚ฌํ•ญ์€ Spring Data JPA-Query Method ๊ณต์‹ ๋ฌธ์„œ ๋ฅผ ์ฐธ๊ณ ํ•จ๋ฉด ์–ด๋–ค ํ‚ค์›Œ๋“œ๋กœ ๋„ค์ด๋ฐ์„ ํ–ˆ์„ ๋•Œ, ์ ์ ˆํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ฟผ๋ฆฌ ๋ฉ”์„œ๋“œ Test

  • User.class
  • UserRepository.interface
  • UserRepositoryTest.class

User ํด๋ž˜์Šค

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String address;
    private int age;
    private LocalDateTime registeredDate;
}

๊ต์œก ํŽธ์˜๋ฅผ ์œ„ํ•ด ๋กฌ๋ณต๊ณผ ๊ด€๋ จ๋œ ์–ด๋…ธํ…Œ์ด์…˜์€ ์ œ๊ฑฐํ•˜์˜€๋‹ค.

 

UserRepository ์ธํ„ฐํŽ˜์ด์Šค

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsernameAndAddress(String username, String address);
}

์ด๋ฒˆ ํ…Œ์ŠคํŠธ์˜ ํ•ต์‹ฌ์ธ UserRepository์˜ Query Method ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•œ ๋ ˆํฌ์ง€ํ† ๋ฆฌ์ด๋‹ค.

 

์ธํ…”๋ฆฌ์ œ์ด๋ฅผ ์“ด๋‹ค๋ฉด snippet ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

UserRepositoryTest ํด๋ž˜์Šค

@SpringBootTest
@Transactional
@Rollback(false)
class UserRepositoryTest {

    @Autowired
    UserRepository userRepository;

    @Test
    @DisplayName("์‚ฌ์šฉ์ž ์ด๋ฆ„๊ณผ ์ฃผ์†Œ๋กœ ์กฐํšŒ")
    void findUsernameAndAddressTest() {

        // given
        String username = "James";
        String address = "seoul";

        User user = User.builder()
                .username(username)
                .address(address)
                .age(25)
                .registeredDate(LocalDateTime.now())
                .build();
        userRepository.save(user);

        // when
        Optional<User> selectedUser = userRepository.findByUsernameAndAddress(username, address);

        // then
        selectedUser.ifPresentOrElse(
                userOptional -> assertEquals(userOptional.getUsername(), username),
                Assertions::fail
        );

        // then ๋žŒ๋‹ค๋ฅผ ์“ฐ์ง€ ์•Š์€ ๊ฒฝ์šฐ
        if(selectedUser.isEmpty()) {
            fail();
        }else {
            User userOptional = selectedUser.get();
            assertEquals(userOptional.getUsername(), username);
        }
    }
}

์ •๋ง ๋ฉ‹์ง€๋‹ค..

 

ํ•˜์ง€๋งŒ ์œ„์˜ ์ฟผ๋ฆฌ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ์ด ์›Œ๋‚™ ๊ฐ•๋ ฅํ•˜๋‹ค๊ณ  ํ•ด๋„ ๋ชจ๋“  ์‚ฌ์šฉ์ž์˜ ๋‹ˆ์ฆˆ๋ฅผ ํŒŒ์•…ํ•˜๊ธด ํž˜๋“ค๋‹ค.

 

์–ด๋–ค ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Native Query๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š” ๊ณณ๋„ ํ•„์š”ํ•  ๊ฒƒ์ด๊ณ , ๋‹ค์–‘ํ•œ ์กฐํ•ฉ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ์งœ์•ผํ•˜๋Š” ์ƒํ™ฉ์ด ์˜ฌ ๋•Œ๋Š” ์–ด๋–ป๊ฒŒ ํ• ๊นŒ?

@Query

๊ทธ๋Ÿฐ ์ƒํ™ฉ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์›ํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ง์ ‘ ์งœ์•ผ ํ•˜๋Š” ๊ทธ๋Ÿฐ ์ƒํ™ฉ์ด ์˜ฌ ๋•Œ @Query ๋Š” ์•„์ฃผ ๊ฐ•๋ ฅํ•˜๋‹ค.

 

์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ• ๊นŒ?

 

@Query๋Š” ์‹คํ–‰ํ•  ๋ฉ”์„œ๋“œ ์œ„์— ์ •์  ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑ ํ•œ๋‹ค.

์—ฌ๊ธฐ ๋“ค์–ด๊ฐ€๋Š” ์ฟผ๋ฆฌ๋Š” JPQL ์ด๋ผ๋Š” ์ฟผ๋ฆฌ๊ฐ€ ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค.

 

JQPL

Java Persistence Query Language ์ธ JPQL์€ ๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ๋กœ JPA๊ฐ€ ์ง€์›ํ•˜๋Š” ๋‹ค์–‘ํ•œ ์ฟผ๋ฆฌ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

 

๊ธฐ์กด์— SQL ์ค‘์‹ฌ์  ๊ฐœ๋ฐœ์— ์ต์ˆ™ํ•œ ์šฐ๋ฆฌ์—๊ฒŒ๋Š” ์–ด๋–ป๊ฒŒ ๋ณด๋ฉด ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฐฉ๋ฒ•์ด๊ธฐ๋„ ํ•˜๋‹ค.

 

SQL๊ณผ JPQL์˜ ์ฐจ์ด์ ์ด ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด

  • SQL
    • ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ
  • JPQL
    • ์—”ํ‹ฐํ‹ฐ ๊ฐ์ฒด๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ

๋ฅผ ํ•˜๊ฒŒ ๋œ๋‹ค.

 

์ด๋Š” JPA๊ฐ€ ํƒ„์ƒํ•œ ์ด์œ ์ธ ์ž„ํ”ผ๋˜์Šค ๋ถˆ์ผ์น˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋Š” ๋…ธ๋ ฅ์˜ ์ผํ™˜ ๊ฐ™๋‹ค.

 

์ฟผ๋ฆฌ๋ฌธ ๋‚ด๋ถ€์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฐธ์กฐ๋ณ€์ˆ˜.ํ•„๋“œ ์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

select
    m.username,
    m.address
from
    Member m
where
    m.age>18

JPQL ์— ๋Œ€ํ•ด์„œ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์„ค๋ช…ํ•˜๊ธฐ ๋ณด๋‹ค ๊ฐ„๋‹จํ•˜๊ฒŒ ์ปจ์…‰๋งŒ ์ด์•ผ๊ธฐํ•˜๋ ค ํ•œ๋‹ค.

 

SQL์„ ๋ชจ๋‘ ์•ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด์•ผ ํ•˜๋‹ˆ ์ผ๋‹จ์€ ๋„˜์–ด๊ฐ€๋„๋ก ํ•˜์ง€๋งŒ ๊ผญ SQL ์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๊ณ  JPQL์„ ์•Œ์•„๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.

 

๋งŒ์•ฝ ๋ณธ์ธ์ด SQL์— ๋Œ€ํ•ด์„œ ํ•˜๋‚˜๋„ ๋ชจ๋ฅธ๋‹ค๋ฉด ํ•ด๋‹น ๋ธ”๋กœ๊ทธ์˜ ์‹œ๋ฆฌ์ฆˆ์ธ ์ดˆ๋ณด์ž๋„ ์ค€๋น„ํ•˜๋Š” SQL ์ฝ”๋”ฉํ…Œ์ŠคํŠธ์—์„œ ํ•™์Šตํ•  ์ˆ˜ ์žˆ๋‹ค.
์ฝ”๋”ฉ ํ…Œ์ŠคํŠธ์— ์ž์ฃผ ๋‚˜์˜ค๋Š” SELECT๋ฅผ ์œ„์ฃผ๋กœ ์„ค๋ช…ํ•˜๊ณ  ์žˆ์œผ๋‚˜, ์˜ˆ์ œ์™€ ๋ฌธ์ œ๋“ค๋„ ์žˆ์–ด์„œ SQL ์ž…๋ฌธ์ž์—๊ฒŒ๋Š” ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

๋‹ค์‹œ @Query ๋กœ ๋Œ์•„์™€์„œ!

@Query๋Š” JpaRepository ๋ฅผ ์ƒ์†ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์‚ฌ์šฉํ•œ๋‹ค.

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("์ฟผ๋ฆฌ๋ฌธ")
    List<User> methodName();

์ด์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

 

๋งŒ์•ฝ age๊ฐ€ 20์‚ด ์ด์ƒ์ธ ์‚ฌ๋žŒ์„ ์กฐํšŒํ•œ๋‹ค๊ณ  ํ•ด๋ณด๋ฉด JPQL์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉ๋  ๊ฒƒ์ด๋‹ค.

 

Sring jpql = "select u from User u where u.age > 20";

์ค‘์š”ํ•œ ๊ฒƒ์€ ์šฐ๋ฆฌ๋Š” ํ…Œ์ด๋ธ”์„ ๋Œ€์ƒ์œผ๋กœ ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๋‚ ๋ฆฐ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ ์‹œํ‚ค๊ธฐ

์šฐ๋ฆฌ๊ฐ€ ์ด๊ฑธ ํ•˜๋Š” ์ด์œ ๋Š” ๋ญ˜๊นŒ?

 

๋ฐ”๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ์ฟผ๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

์ฆ‰, ์•„๋ž˜์˜ methodName() ์— ๋“ค์–ด๊ฐˆ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์šฐ๋ฆฌ์˜ ์ฟผ๋ฆฌ๋ฌธ์— ๋„ฃ๋Š” ๊ฒƒ์ด๋‹ค.

 

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("์ฟผ๋ฆฌ๋ฌธ")
    List<User> methodName();

์ด๋ฅผ ํŒŒ๋ฆฌ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์ด๋ผ๊ณ  ํ•œ๋‹ค.

 

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์—๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

 

  1. ์œ„์น˜ ๊ธฐ๋ฐ˜
  2. ์ด๋ฆ„ ๊ธฐ๋ฐ˜

์œ„์น˜ ๊ธฐ๋ฐ˜์€ ์“ฐ์ง€๋ง์ž, ์ด๋ฆ„ ๊ธฐ๋ฐ˜์„ ์“ฐ์ž

 

์œ„์น˜ ๊ธฐ๋ฐ˜์€ JDBC ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ๋•Œ์˜ ResultSet ์„ ์ƒ๊ฐํ•˜๋ฉด ์‰ฌ์šธ ๊ฒƒ ๊ฐ™๋‹ค.

 

์ด๋ฆ„ ๊ธฐ๋ฐ˜์„ ์“ฐ๋ผ๊ณ  ํ•˜๋Š” ์ด์œ ๋Š” JPA ์˜ ์„ ๊ตฌ์ž? ๊น€์˜ํ•œ ๊ฐœ๋ฐœ์ž๋‹˜๋„ ๊ฐ€๋…์„ฑ์„ ์œ„ํ•ด ์ด๋ฆ„ ๊ธฐ๋ฐ˜์„ ์จ๋ผ! ๋ผ๊ณ  ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๋‚˜๋„ 100% ๋™์˜ํ•œ๋‹ค.

 

๊ทธ๋Ÿฌ๋‹ˆ ์šฐ๋ฆฌ๋„ ์ด๋ฆ„ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜์ž ใ…Žใ…Ž

 

์ด๋ฆ„ ๊ธฐ๋ฐ˜์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ํ•˜๊ณ  ํŒŒ๋ผ๋ฏธํ„ฐ์— @Param("") ์–ด๋…ธํ…Œ์ด์…˜์œผ๋กœ ๋ฉ”์„œ๋“œ์— ๋“ค์–ด์˜ค๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์–ด๋–ค ์ด๋ฆ„์œผ๋กœ ์ง€์ •๋  ์ง€ ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

public interface UserRepository extends JpaRepository<User, Long> {
    @Query("select u from User u where u.username = :name")
    List<User> methodName(@Param("name") String username);

 

์ด์ œ @Query ์— ๋Œ€ํ•ด์„œ ์–ด๋Š ์ •๋„ ๋ฐฐ์šด ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ํ…Œ์ŠคํŠธ๋ฅผ ๋งˆ์ง€๋ง‰์œผ๋กœ ๊ธ€์„ ๋งˆ์น˜๋ ค ํ•œ๋‹ค.

 

@Query ํ…Œ์ŠคํŠธ

  • User.class
  • UserRepository.interface
  • UserRepositoryTest.class

User

UserRepository

public interface UserRepository extends JpaRepository<User, Long> {

    @Query("SELECT u FROM User u WHERE u.username LIKE %:char% and u.age > :maxAge")
    List<User> findByLetterWithConditions(@Param("char") char letter,
                                          @Param("maxAge") int age);
}

 

JPQL ๋กœ ์ด๋ฆ„ ๊ธฐ๋ฐ˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ”์ธ๋”ฉ์„ ํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

UserRepositoryTest

@SpringBootTest
@Transactional
@Rollback(false)
class UserRepositoryTest {

    @Autowired
    UserRepository userRepository;

    @Test
    void findUsernameAndAddressTest() {

        // given
        String jamesUsername = "James";
        String maryUsername = "Mary";

        User james = User.builder()
                .username(jamesUsername)
                .age(25)
                .build();

        User mary = User.builder()
                .username(maryUsername)
                .age(30)
                .build();

        userRepository.save(james);
        userRepository.save(mary);

        // when
        List<User> optionalUsers = userRepository.findByLetterWithConditions('a', 23);

        // then
        assertEquals(optionalUsers.get(0).getUsername(), jamesUsername);
        assertEquals(optionalUsers.get(1).getUsername(), maryUsername);
    }
}

๋Œ“๊ธ€