JPA를 이용한 커스텀 쿼리 만들기

뚜우웅이·2023년 2월 18일
0

SpringBoot웹

목록 보기
10/23

@Query

지금까지는 findByUsername처럼 JPA에 예약된 키워드를 이용해서 데이터를 가져왔습니다. 하지만 좀 더 복잡한 상황에서는 직접 쿼리를 작성해서 데이터를 가져와야 합니다.
직접 쿼리를 작성하기 위해서는 @Query를 사용해줘야 합니다.

@Query("select u from User u where u.firstname like %?1")
  List<User> findByFirstnameEndsWith(String firstname);

이 코드를 가져와서 사용해줍니다.
일반적인 SQL과 차이점으로 select 절에서 전체 목록을 가져올 때 SQL을 *을 쓰지만 JPQL에서는 from 절에 있는 User의 약자 u를 사용해줍니다.

UserRepository에 아래 코드를 추가해줍니다.
파라미터로 들어온 username이 user 테이블에 존재하는 username과 1글자라도 일치하면 데이터를 가져오는 쿼리입니다.

@Query("select u from User u where u.username like %?1%")
    List<User> findByUsernameQuery(String username);

UserApiController를 수정해줍니다.
required = true인 경우에는 파라미터가 무조건 들어와야 합니다.
query라는 이름으로 들어온 경우에 findByUsernameQuery를 실행합니다.

@GetMapping("/users")
    List<User> all(@RequestParam(required = false) String method, @RequestParam(required = false) String text) {
        List<User> users = null;
        if("query".equals(method)){
            users = repository.findByUsernameQuery(text);
        }
        else users = repository.findAll();
        return users;
    }

@Query에 nativeQuery옵션을 true로 넣어주면 일반적인 SQL 문법을 사용할 수 있습니다.

@Query(value = "select * from User u where u.username like %?1%", nativeQuery = true)
    List<User> findByUsernameNativeQuery(String username);
@GetMapping("/users")
    List<User> all(@RequestParam(required = false) String method, @RequestParam(required = false) String text) {
        List<User> users = null;
        if("query".equals(method)){
            users = repository.findByUsernameQuery(text);
        }
        else if("nativeQuery".equals(method)){
            users = repository.findByUsernameNativeQuery(text);
        }
        else users = repository.findAll();
        return users;
    }

Mybatis 세팅 후 데이터 조회

pom.xml에 Mybatis 의존성을 추가해줍니다.

<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>

application.properties 설정

mybatis.type-aliases-package=com.project.myhome.model
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.mapper.locations=classpath:mapper/**/*.xml

mybatis.mapper.locations을 사용해서 mapper 인터페이스와 xml 파일이 들어있는 mapper가 서로 연동이 되는 것입니다.

Mybatis의 모든 기능을 사용하지 않고 커스텀 쿼리에 대한 기능만 사용할 것입니다.
mapper 패키지를 생성하고 이 아래에 UserMapper 인터페이스를 생성해줍니다.

@Param을 써서 쿼리에서 어떤 변수명을 사용할지 지정해줘야 합니다.

package com.project.myhome.mapper;

import com.project.myhome.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@Mapper
public interface UserMapper {
    List<User> getUsers(@Param("text") String text);
}

resources 밑에 mapper 폴더를 생성해줍니다.
여기에는 xml 파일을 넣어줄 것입니다.
mapper 아래에 user.xml 파일을 생성하고 아래의 코드를 넣어줍니다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.project.myhome.mapper.UserMapper">
  <select id="getUsers" resultType="User">
    SELECT *
    FROM user
    WHERE username LIKE CONCAT('%', #{text}, '%')
  </select>
</mapper>

resultType은 application.properties에 정의한 패키지 안에 있는 클래스가 됩니다.

SELECT *
FROM user
WHERE username LIKE '%1%'

이러한 쿼리를 사용할 때 '%1%'이 부분이 text 변수가 되는 것입니다. % 기호와 함께 사용하기는 어렵기 때문에 concat을 사용해줍니다.

UserApiController도 수정해줍니다.

@Autowired
    private UserMapper userMapper;
    
@GetMapping("/users")
    List<User> all(@RequestParam(required = false) String method, @RequestParam(required = false) String text) {
        List<User> users = null;
        if("query".equals(method)){
            users = repository.findByUsernameQuery(text);
        }
        else if("nativeQuery".equals(method)){
            users = repository.findByUsernameNativeQuery(text);
        }
        else if("mybatis".equals(method)){
            users = userMapper.getUsers(text);
        }
        else users = repository.findAll();
        return users;
    }

postman으로 조회를 할 경우 제대로 조회가 되는 것을 확인할 수 있습니다.

profile
공부하는 초보 개발자

0개의 댓글