Spring Boot, JPQL (JPA Query Language/@Query)

Jihu Kim·2024년 1월 23일

Spring 입문

목록 보기
9/14
post-thumbnail

Spring의 DB 접근 기술은 순수 JDBC -> JDBC Template -> JPA -> Spring Data JPA 순으로 등장했다.

데이터베이스와 연동을 해보면서 자바의 표준 ORM 기술 스펙인 JPA를 사용했었다.
여기서는 Spring Data JPA에서 제공하는 추가적인 기능들에서 살펴보겠다.

JPA는 적절한 쿼리를 생성하고 데이터베이스를 조작해서 객체를 자동으로 매핑하는 역할을 수행한다.

이러한 JPA에서 제공하는 쿼리 메소드만으로 조회가 불가능한 경우 JPQL을 사용한다.

JPQL : JPQL은 JPA Query Language의 줄임말이다. JPA에서 사용할 수 있는 쿼리를 의미한다. JPQL의 문법은 SQL과 비슷하다. (SQL에서는 테이블이나 칼럼의 이름을 사용하지만, JPQL은 앤티티 객체를 대상으로 수행하는 쿼리여서 매핑된 엔티티의 이름과 필드의 이름을 사용한다.)

만약 데이터베이스를 변경할 일이 없으면 직접 해당 데이터베이스에 특화된 SQL을 작성하기도 하지만, 보통 JPQL 사용.

JPQL을 작성하는 다양한 방법이 있으나, @Query 어노테이션과 EntityManager.createQuery를 사용해 JPQL을 작성해보자.


@Query 사용하기

Entity

@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "user")
@AllArgsConstructor
public class User {
    @Id
    private String id;
    private String name;
    private String phone;
    private String registerInfo;
    private String deptId;
}

JpaRepository

public interface UserRepository extends JpaRepository<User, String> {
    @Query(value = "select user " +
            "from User user " +
            "where user.name = :name")
    List<User> findByName(@Param("name") String name);

@Param을 통해서 파라미터를 바인딩하는 방식으로 메서드를 구현하면 코드의 가독성이 높아지고 유지보수가 수월해진다.

DTO 매핑

위에서는 간단하게 @Query 어노테이션을 사용해 보았다.
DTO와 매핑해서 사용하는 경우, 해당 방법을 사용한다.

DTO(Data Transfer Object)는 계층간 데이터 교환을 위해 사용하는 객체이다.

보통의 패턴인 경우에는 다음과 같다.

  1. DTO 객체를 생성하고 이를 컨트롤러에 전달한다.
  2. 컨트롤러는 해당 DTO를 다시 Service에게 전달한다.
  3. Service는 JPA를 이용해서 생성된 Entity를 저장한다.

DTO

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserDto {
    private String id;
    private String name;
    private String phone;
    private String deptId;
    private String deptName;
}

JpaRepository(return DTO와 JOIN 사용)

public interface UserRepository extends JpaRepository<User, String> {
    @Query(value = "select " +
            "new `UserDto의 패키지 위치`.UserDto(user.id, user.name, user.phone, user.deptId, dept.name) " +
            "from User user " +
            "left outer join Dept dept on user.deptId = dept.id ")
    List<UserDto> findUserDept();
}

User와 User의 Dept를 조인한 테이블에서
User의 id, name, phone, deptId, name을 DTO에 담아서 반환을 해보았다.

DTO를 반환하기 위해서는 SELECT구문에서 생성자를 통해서 객체를 반환해야한다.


EntityManager 사용하기

다음에 알아보도록 하자.

보통 @Query 어노테이션을 사용해 구현하는듯 하다.


JPQL을 통해 쿼리문을 작성할 때 직접 문자열을 입력하기 때문에 컴파일 시점에 에러를 잡지 못하고, 런타임 에러가 발생할 수 있다.

이러한 단점을 해결하기위해 QueryDSL이 사용된다.

QueryDSL은 문자열이 아닌 코드로 쿼리를 작성할 수 있도록 도와주는데,

나중에 알아보도록 하자.


JPA Auditing은 데이터마다 누가, 언제 생성했고 변경했는지 감시하는 것을 의미하는데 Spring Data JPA에서는 이러한 기능을 제공한다고하니 나중에 추가로 학습을 진행하자.

profile
Jihukimme

0개의 댓글