JPA

[JPA] 일부 컬럼 값만 가져오는 native query 사용

이나피스 2023. 4. 5. 13:27
반응형

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

 

반응형