스프링 JPA는 다양한 쿼리 방법을 지원한다.
그 중 JPQL을 쓴 내용을 정리해보았다.
📕 JPQL (Java persistence Query Language)
📗 JPQL 이란?
- 테이블 대상으로 쿼리하는 것이 아니라 엔티티 객체를 대상으로 쿼리한다.
- SQL과 비슷한 문법을 가지며, JPQL은 결국 SQL로 변환된다.
- JPA에서 제공하는 메소드 호출만으로 섬세한 쿼리 작성이 어렵다는 문제에서 JPQL이 탄생된 것이다.
📗 특징
- 객체를 검색하는 객체지향 쿼리
- SQL을 추상화 했기 때문에 특정 벤더에 종속적이지 않음
- JPA는 JPQL을 분석하여 SQL을 생성한 후 DB에서 조회
📕 프로젝트 중 활용(로스트아크 숙제 체크)
📗 엔티티 구조
[Content] - 일일 숙제와 주간 숙제를 나누기 위해 추상클래스로 생성
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Data
public abstract class Content {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "content_id")
private long id;
@Enumerated(EnumType.STRING)
private Category category; // 일일 숙제, 주간 숙제 분류
private String name;
private double level; //컨텐츠 레벨
}
[DayContent] - 일일 컨텐츠 (카오스 던전, 가디언 토벌등)
@Entity
@Getter
public class DayContent extends Content{
@Enumerated(EnumType.STRING)
private Category dayContentCategory; // 가디언 토벌, 카오스 던전 분류
private double shilling; //실링
private double honorShard; //명파
private double leapStone; //돌파석
private double destructionStone; //파괴석
private double guardianStone; //수호석
private double jewelry; //1레벨 보석
private double gold; //평균 골드
}
📗 기존 코드
[ContentRepository]
DayContent findTop1ByLevelLessThanEqualOrderByLevelDesc(double level);
- JPA 쿼리 메소드를 이용하여 만든 메서드이다
- 특정 레벨이하의 컨텐츠를 정렬해서 하나의 데이터만을 가져온다.
- 몇 가지 기능만을 넣었는데도 메소드명이 너무 길어 수정하였다.
📗 변경 코드
[ContentRepository]
@Query("select c from DayContent c " +
"where c.level <= :level " +
"and c.dayContentCategory = :contentCategory " +
"order by c.level desc")
List<DayContent> findDayContentByLevel(
@Param("level") double level, @Param("contentCategory") Category category);
- DayContent 중 특정 레벨 이하, 컨텐츠 이름 분류(카오스던전, 가디언토벌), 레벨 순으로 정렬하여 가져온다.
- JPQL은 limit를 지원하지 않아 리스트로 반환하고 서비스 단에서 하나를 선택하였다.
[ContentService]
public Map<Category, DayContent> getDayContentByLevel(double level) {
DayContent chaosContent = contentRepository.findDayContentByLevel(level, Category.카오스던전).get(0);
DayContent guardianContent = contentRepository.findDayContentByLevel(level, Category.가디언토벌).get(0);
Map<Category, DayContent> dayContentMap = new HashMap<>();
dayContentMap.put(Category.카오스던전, chaosContent);
dayContentMap.put(Category.가디언토벌, guardianContent);
return dayContentMap;
}
- 쉽게 사용하기 위해 Map으로 만들어서 리턴하였다.