본문 바로가기
개발자 전향 프로젝트

QueryDsl 에서는 Null 처리를 어떻게 하나요?

by 샘오리 2023. 4. 10.
728x90
반응형

Coalesce 

Query를 직접 쓴다면 뭐 DBMS에 따라 문법이 조금 다르겠지만

오라클의 경우 NVL이 바로 떠오르텐데 QueryDsl에서는 NVL이나 IF NULL 대신 Coalesce를 쓴다. 

 

단순한 조회 시 문법은 아래와 같다.

.select(
	QueryDsl 전용 엔티티(dto)의 참조변수.칼럼명.coalesce("NULL일시 표출하고 싶은 메세지").as("가명")
    )
.from(QueryDsl 전용 엔티티(dto)의 참조변수)
.fetch();

위 문법의 예시는 아래와 같다.

.select(
	codeDto.codeName.coalesce("아무것도 없네요").as("codeName")
    )
.from(codeDto)
.fetch();

여기서 포인트는 as 로 가명을 지정해두는 것인데 가명을 지정해두지 않으면 

어떤 필드로 인식해야하는지 모르기에 가명을 지정해둬야하고 그 가명은 엔티티 혹은 dto에 선언된 칼럼이어야 한다.

그래서 보통은 NVL 처리를 하고 싶었던 바로 그 칼럼을 가명으로 지정하는 경우가 많다.

출력하는 곳에서 그 칼럼을 출력하도록 설정해놨을 확률이 높기 때문이다.

 


 

위 문법을 활용해서 조금 응용해본다면 String 값으로 꼭 넣어야만 하는 것은 아니다.

칼럼을 넣을 수도 있다. 예시는 아래와 같다.

.select(
	cardDto.userType.coalesce(cardDto.errorType).as(cardDto.userType)
    )
.from(cardDto)
.fetch();

이렇게 되면 cardDto의 userType이 coalesce => NVL 이라면

cardDto의 errorType으로 출력하고 이 출력하는 것을 userType으로 인식해라 =>

HTML과 같은 VIEW에서는 userType을 출력 하도록 세팅만 해놓으면

DB에서 값을 긁어올 때 NULL인 경우 그 알맹이만 errorType으로 자동으로 치환해주고 껍데기는 userType안에 넣어놨기에 VIEW에서 바로 읽어올 수 있는 것이다. 

 


한단계 더 응용해보자.

 

UserType이라는 칼럼에 값은 존재한다. 그러므로 그 자체로는 NULL이 아니다.

하지만 다른 테이블의 특정 칼럼과 비교해서 동일한 것만 가져오도록 설정해놨다면

UserType이라는 칼럼에 값은 그 값 자체는 존재해도 조건절에 걸리지 않아서 NULL이 들어올 수 있는것이다.

 

예를 들어 어떤 이유에서인지 UserType이라는 칼럼에 01, 02, 03, 04, 05 라는 값이 존재하고

다른 테이블에는 01, 02, 03 만 각각 성인, 노인, 어린이 등으로 정의되어 있다면

04, 05는 일치하지 않는 값이 되고 , 당연히 where 조건절에 걸리지 않아서 NULL이 되는 것이다.

 

이런 경우 NULL을 반환하지 않고 coalesce 를 활용해서 04를 그대로 넣어줄 수 있고

04 대신 04-미정의 라고 표시한다든지 커스터마이징(?)을 해서 출력할 수도 있다.

아래는 QueryDsl 파트의 예시이다.

codeDto.codeValue.coalesce(cardDto.userType).as(cardDto.userTypeValue),
codeDto.codeName.coalesce("미정의").as(cardDto.userTypeName),

아래는 View 파트의 예시이다.

<td class="table-data" th:text="|${history.userTypeValue} - ${history.userTypeName}|"></td>

이렇게 되면 coalesce 처리 후 04-미정의 로 출력이 되는 것을 확인할 수 있다.

728x90
반응형