[JPA] 일부 컬럼 값만 가져오는 native query 사용
JPA 마스터 한줄 알았는데 나를 너무 과대평가했다.
이것 때문에 하루하고 반나절 해멨다....
내가 하려고 한 테이블 값을 가져오는 조건은 아래와 같다.
student 테이블의 일부컬럼만 가져와서 연산자(sum)와 group by 사용
매개변수로 가져온 날짜로 where절에 insert_date 필터 적용
student 테이블의 컬럼값은 student_id, student_name, address, phone, math_score, eng_score, kor_score 이다.
처음에 시도엔 일반적인 native query문처럼 사용하려고 하였다.
package com.beige0905.test.repository;
import com.beige0905.test.repository.vo.StudentVo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
@Repository
public interface StudentTotalScore extends JpaRepository<StudentVo, Long> {
@Query(nativeQuery = true,
value ="SELECT student_id AS student_id, student_name AS student_name," +
" SUM(math_score) AS math_score, SUM(eng_score) AS eng_score, SUM(kor_score) AS kor_score " +
" FROM student" +
" WHERE insert_date BETWEEN ?1 AND ?2" +
" GROUP BY student_id, student_name" +
" ORDER BY student_id")
List<StudentVo> selectStudentScoreList(LocalDate startDate, LocalDate endDate);
}
이렇게 시도하는 경우 student 테이블의 컬럼값인 address, phone의 컬럼명을 찾을수 없습니다. 라는 오류를 보게 될 것이다.
해결하기 위해 SELECT절에 MAX(address), MAX(phone)를 추가하여 의미없는 값을 가져오면 해결은 되지만
이것보다 컬럼수가 더 많게 된다면 불필요한 값이 너무 많아지고, 코드도 복잡하게 된다.
찾아보다가 return 타입을 List<VO>가 아닌 List<Object[]>로 값을 받은 후 Service단에서 데이터를 가공하는 방법으로 변경하였다.
Repository
package com.beige0905.test.repository;
import com.beige0905.test.repository.vo.StudentVo;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
@Repository
public interface StudentTotalScore extends JpaRepository<StudentVo, Long> {
@Query(nativeQuery = true,
value ="SELECT student_id AS student_id, student_name AS student_name," +
" SUM(math_score) AS math_score, SUM(eng_score) AS eng_score, SUM(kor_score) AS kor_score " +
" FROM student" +
" WHERE insert_date BETWEEN ?1 AND ?2" +
" GROUP BY student_id, student_name" +
" ORDER BY student_id")
List<Object[]> selectStudentScoreList(LocalDate startDate, LocalDate endDate);
}
Service
public List<StudentVo> getStudentTotalScore(LocalDate startDate, LocalDate endDate) {
List<Object[]> list = studentRepository.selectStudentScoreList(startDate, endDate);
List<StudentVo> result = new ArrayList<>();
for(Object[] obj : list) {
result.add(StudentVo.builder()
.studentId(obj[0].toString())
.studentName(obj[1].toString())
.mathScore(Long.parseLong(String.valueOf(obj[2])))
.engScore(Long.parseLong(String.valueOf(obj[3])))
.korScore(Integer.parseInt(String.valueOf(obj[4])))
.build());
}
return result;
}
형변환은 math, eng는 long, kor는 int로 형변환 해봤다.
(Intege) (Long) 강제형변환은 적용이 안되어서 이렇게 형변환 함
https://stackoverflow.com/questions/22653858/how-to-get-multiple-columns-from-table-using-jpa
How to get multiple columns from table using JPA?
For example I have a table as Student it's contain columns like id, name, age I am reverting particular column values by using NativeQuery like below. Query query = entityManager.createNativeQuery("
stackoverflow.com