[삽질 피하기] 객체지향 쿼리 (Native Query, JPQL)
2021. 4. 21. 17:27ㆍ삽질 피하기
1. 객체지향 쿼리
JPA는 복잡한 검색 조건을 사용해서 엔티티 객체를 조회할 수 있는 다양한 쿼리 기술을 지원한다.
JPQL (Java Persistence Query Language) | |
Criteria Query | JPQL을 편하게 작성하도록 도와주는 API, 빌더 클래스 모음 |
Native SQL | JPA에서 JPQL 대신 직접 SQL을 사용할 수 있다. |
QueryDLS | JPA가 공식 지원하는 기능은 아니지만 Criteria 처럼 JPQL을 편하게 작성하도록 도와주는 빌더 클래스, 비표준 오픈소스 프레임워크이다. |
JDBC 직접 사용, MyBatis 같은 SQL 매퍼 프레임워크 | 필요하다면 JDBC를 직접 사용할 수 있다. |
2. JPQL
- 지루하게 반복되는 CRUD 문제를 세련된 방법으로 해결
- 개발자는 인터페이스만 작성한다
- @Query 어노테이션을 이용하여 JPQL을 직접 정의할 수 있다.
※ JPA는 카멜케이스에 대해 '_' 처리되며 자동으로 매핑이 된다.
[참고] 삽질 피하기 - @Query, @Modifying, @Transactional 어노테이션 사용법
3. Native Query
Native Query의 경우 자동으로 매핑이 되지 않는다. 따라서 개별적으로 코드를 작성해주거나 JPA를 지원하는 ResultSet Mapper인 QLRM으로 매핑을 해주어야 한다. (또는 Entity에 @SqlResultSetMapping()를 설정해주어 해결 가능)
implementation group: 'ch.simas.qlrm', name: 'qlrm', version: '1.7.1'
...
import lombok.RequiredArgsConstructor;
import org.qlrm.mapper.JpaResultMapper;
import org.springframework.stereotype.Repository;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
import java.util.stream.Collectors;
@RequiredArgsConstructor
@Repository
public class BoardTypeCustomRepository {
private final EntityManager entityManager;
public List<BoardTypeCount> getBoardTypeCount() {
String sql = " " +
"SELECT bt.id, bt.board_name, bt.reg_date, bt.using_yn," +
"(SELECT COUNT(*) FROM board b WHERE b.board_type_id = bt.id) as board_count " +
"FROM board_type bt ";
// 직접 매핑할 경우
// List<BoardTypeCount> boardTypeCountList = entityManager.createNativeQuery(sql).getResultList();
// List<Object[]> resultList = entityManager.createNativeQuery(sql).getResultList();
// return resultList.stream().map(e -> new BoardTypeCount(e)).collect(Collectors.toList());
// QLRM 방법
Query nativeQuery = entityManager.createNativeQuery(sql);
JpaResultMapper jpaResultMapper = new JpaResultMapper();
return jpaResultMapper.list(nativeQuery, BoardTypeCount.class);
}
}
...
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.time.LocalDateTime;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class BoardTypeCount {
private Long id;
private String boardName;
private LocalDateTime regDate;
private boolean usingYn;
private Long boardCount;
public BoardTypeCount(Object[] arrObj) {
this.id = ((BigInteger)arrObj[0]).longValue();
this.boardName = ((String)arrObj[1]);
this.regDate = ((Timestamp)arrObj[2]).toLocalDateTime();
this.usingYn = ((Boolean)arrObj[3]);
this.boardCount = ((BigInteger)arrObj[4]).longValue();
}
public BoardTypeCount(BigInteger id, String boardName, Timestamp regDate, Boolean usingYn, BigInteger boardCount) {
this.id = id.longValue();
this.boardName = boardName;
this.regDate = regDate.toLocalDateTime();
this.boardCount = boardCount.longValue();
}
}
[참고] https://mvnrepository.com/artifact/ch.simas.qlrm/qlrm
728x90
'삽질 피하기' 카테고리의 다른 글
[삽질 피하기] @Query, @Modifying, @Transactional 어노테이션 사용법 (0) | 2021.04.21 |
---|---|
[삽질 피하기] JpaRepository 규칙에 맞는 메서드 (0) | 2021.04.21 |
[삽질 피하기] 메일 전송, Scheduler (0) | 2021.04.21 |
[삽질 피하기] 인터셉터 (0) | 2021.04.21 |