[AXBoot] QueryDSL groupBy / BigDecimal 더하기 연산

yesjm·2021년 5월 25일
0

매출현황 보고서 페이지

  • 날짜별 투숙건수, 판매금액, 서비스금액을 표시하고 첫줄에는 합계를 표시하는 페이지이다.
  • 필터 기능을 통해 표시되는 기간을 선택할 수 있다.

QueryDsl - gruopBy

axboot 프론트에서 summary를 지원하지만 해당 기능은 지원하지 않아서 서비스단에서 해결했다.

groupBy를 통해 가져온 데이터를 컨트롤러로 보내기 위해 ChkReportListResponseDto를 생성했다. 처음엔 Map을 이용하려 했는데 생각해보니 그럴 필요가 없었다..

import lombok.Getter;
import java.math.BigDecimal;

@Getter
public class ChkReportListResponseDto {
    private String arrDt;
    private Long roomCount;
    private BigDecimal salePrc;
    private BigDecimal svcPrc;

    public ChkReportListResponseDto(String arrDt, Long roomCount, BigDecimal salePrc, BigDecimal svcPrc) {
        this.arrDt = arrDt;
        this.roomCount = roomCount;
        this.salePrc = salePrc;
        this.svcPrc = svcPrc;
    }
}

ChkService.java

    public List<ChkReportListResponseDto> getTotal(RequestParams<ChkReportListResponseDto> requestParams) {
        String arrDt = requestParams.getString("arrDt","");
        String arrDtEnd = requestParams.getString("arrDtEnd","");

        BooleanBuilder builder = new BooleanBuilder();
        if (isNotEmpty(arrDt)){
            if (isNotEmpty(arrDtEnd)){
                builder.and(qChk.arrDt.between(arrDt,arrDtEnd));
            }else
                builder.and(qChk.arrDt.between(arrDt, String.valueOf(today)));
        }

        JPAQueryFactory queryFactory = new JPAQueryFactory(em);
        List<ChkReportListResponseDto> chkReportList = queryFactory.selectFrom(qChk)
                .where(builder)
                .groupBy(qChk.arrDt)
                .select(Projections.constructor(ChkReportListResponseDto.class, qChk.arrDt, qChk.rsvNum.count(), qChk.salePrc.sum(), qChk.svcPrc.sum()))
                .orderBy(qChk.rsvNum.count().desc())
                .fetch();
                
        return chkReportList;
    }

가져올 데이터 범위 설정을 위한 builder.

날짜별로 가져오기 위해 groupBy, Dto에 값 바인딩하기위해 .select(Projections.constructor(ChkReportListResponseDto.class, ~) select문 작성했다.

BigDecimal 참고

  • BigDecimal은 Java 언어에서 숫자를 정밀하게 저장하고 표현할 수 있는 유일한 방법이다.
  • 소수점을 저장할 수 있는 가장 크기가 큰 타입인 double은 소수점의 정밀도에 있어 한계가 있어 값이 유실될 수 있다.
  • Java 언어에서 돈과 소수점을 다룬다면 BigDecimal은 선택이 아니라 필수이다.
  • BigDecimal의 유일한 단점은 느린 속도와 기본 타입보다 조금 불편한 사용법 뿐이다.
    (조금 불편한 사용법 덕에 1시간 정도 고생했다.)

첫줄에 합계는 투숙건수, 판매금액, 서비스금액, 합계 열의 합계를 나타낸다.
판매금액과 서비스금액의 자료형이 BigDecimal이다. 처음 사용해본 타입이라 고생했다.

getTotal 메소드에 아래 코드를 추가했다.

    public List<ChkReportListResponseDto> getTotal(RequestParams<ChkReportListResponseDto> requestParams) {
    ...
        long count=0;
        BigDecimal salePrc = BigDecimal.ZERO;
        BigDecimal svcPrc = BigDecimal.ZERO;
        for (ChkReportListResponseDto chkReport : chkReportList){
            count += chkReport.getRoomCount();
            if (chkReport.getSalePrc() != null) salePrc = salePrc.add(chkReport.getSalePrc());
            if (chkReport.getSvcPrc() != null) svcPrc = svcPrc.add(chkReport.getSvcPrc());
        }
        ChkReportListResponseDto reportDto = new ChkReportListResponseDto("합계", count, salePrc,svcPrc);
        chkReportList.add(0, reportDto);
        return chkReportList;
    }

BigDecimal 변수가 null일때 더하면 널포인트 에러가 나서 놀랐고.,
salePrc.add(chkReport.getSalePrc()); 하면 당연히 기존 타입들 처럼 salePrc에 중첩되어 저장될 줄 알았으나 아니었고,, 0으로 자꾸 회귀하더라...
https://hermeslog.tistory.com/408 여기 보고 지금의 코드로 만들었다.

profile
yesjm's second brain

0개의 댓글