2주차 중간발표때 멘토님에게 Query Dsl의 장점에 대해서 질문을 받았는데
가독성이 향상된다 라고만 답변을 했다.
분명히 봤고 Query Dsl의 장점을 딱 두가지로만 나눌 수 있을 정도로 명확했는데
당황해서 그런가 대답을 하지 못했는데 이번에 구현을 하면서 다시 마음속에 새기기로 했다
Query Dsl의 장점
- 문자가 아닌 코드로 쿼리를 작성함으로써, 컴파일 시점에 문법 오류를 쉽게 확인할 수 있다.
- 자동 완성 등 IDE의 도움을 받을 수 있다.
- 동적인 쿼리 작성이 편리하다.
- 쿼리 작성 시 제약 조건 등을 메서드 추출을 통해 재사용할 수 있다.
근데 이 장점들을 요약해보면은
가독성이 좋은 쿼리문 / 동적 쿼리
2가지로 볼 수 있다.
준비
StringUtils 라이브러리만 있으면 된다. 이게 왜 있어야하는지는 아래에 설명하겠음
import문
import org.apache.commons.lang3.StringUtils;
bulid.gradle
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'
StringUtils이란?
String 문자열과 관련된 많은 일들을 해주는 라이브러리로 사용 가능한 함수들은 아래 링크 참고
https://velog.io/@dingdoooo/JavaStudy-StringUtils-문자열-작업-관련-기능-Library
[JavaStudy] 3. StringUtils - 문자열 작업 관련 기능 Library
StringUtils? StringUtils를 사용하면 java.lang.String이 즉시 제공하는 작업을 보완/ 확장하는 인력의 작업들을 수행할 수 있다. 문자열이 공백인지, 비어있는지, 소문자인지 ,대문자인지, 영숫자 인지 확
velog.io
StringUtils을 왜 써야함?
StringUtils의 특징때문에 그렇다
파라미터 값으로 null을 주더라도 절대 NullPointException을 발생시키지 않음.
=> 동적쿼리를 구현하기 위해서는 다양한 조건값을 줘야하는데 null값이 나왔을때
NullPointException이 떠버리면 시스템이 죽어버리기때문에 구현할 수가 없다
즉 null값에 대한 처리가 간편하기 때문에 StringUtils를 사용한다
null이 입력되는 경우 메소드에 따라 알맞은 결과를 리턴하게 된다.
구현
config
@Data
public class SearchCondition {
private Long storeId; // DB에 저장되는 id
private String address; // 일반 주소
private String roadNameAddress; // 도로명 주소
private int postNumber; // 우편 번호
private String storeName; // 가게 이름
private String typeOfBusiness; // 업종
private double xCoordinate; // 위도(x좌표)
private double yCoordinate; // 경도(y좌표)
private double starScore; // 별점
private int reviewCnt; // 리뷰 갯수
}
SearchCondition을 생성하고 검색 조건이 되는 필드들을 생성하고 이를 한번에 주고 받게 된다.
ex) storeName을 검색할 경우
SearchCondition
(storeId=null, address=null, roadNameAddress=null, postNumber=0, storeName=장안순대국밥, typeOfBusiness=null, xCoordinate=0.0, yCoordinate=0.0, starScore=0.0, reviewCnt=0)
controller
service
RepositoryCustom
RepositoryImpl
where절에서 함수를 따로 만들어 다양한 조건으로 들어 갈 수 있게끔 해줬다.
하지만 전부 다 실행되지는 않는다. 왜냐하면
StringUtils에 의해서 isEmpty일 경우 null을 반환하게 되고 StringUtils는 NullPointException을 띄우지 않기
때문에 null값이 그대로 where로 넘어가게 되면서 그 다음 조건값으로 넘어 가게 된다.
(BooleanExpression 와 같이 사용해야한다.)
그렇게 되면 아까 검색해서 얻은
SearchCondition
(storeId=null, address=null, roadNameAddress=null, postNumber=0, storeName=장안순대국밥, typeOfBusiness=null, xCoordinate=0.0, yCoordinate=0.0, starScore=0.0, reviewCnt=0)
condition에 담겨져 있는 값들에 따라서 값이 들어 있는 조건만 where에 걸리게 되면서 쿼리가 동작하게 된다.
조금 더
가게 이름 일치, 도로명 주소, 가게 이름, 업종과 같이 조건값이 명확한 경우
condition을 통해 넘어오는 값도 한가지 해당하는 검색조건도 한가지이지만
starScore와 reviewCnt의 경우에는 한가지의 값으로 두가지의 경우를 처리해야하고
검색어가 없는 검색어 없이 탭의 4가지 조건은 아예 조건값조차 없는데 이걸 어떻게 판단할까 라는 고민을 했다.
이 고민은 각각의 검색항목들은 html에서 url로 구분하고 있기 때문에 그 구분하고 있는 url을 받아와서
처리할 수 있도록 getRequestURI 메소드를 활용하기로 했다
index.html
<optgroup label="=== 검색어 지정 ===">
<option name="test" value="/api/search/storeName/?storeName=">가게 이름 일치</option>
<option name="test" value="/api/search/roadAddressInclude/?roadNameAddress=">도로명 주소</option>
<option name="test" value="/api/search/storeNameInclude/?storeNameInclude=">가게 이름
</option>
<option name="test" value="/api/search/Business/?typeOfBusiness=">업종</option>
<option name="test" value="/api/search/StarScoreHigh/?starScore=">평점 n점이상</option>
<option name="test" value="/api/search/StarScoreLow/?starScore=">평점 n점이하</option>
<option name="test" value="/api/search/ReviewHigh/?reviewCnt=">리뷰 n개이상</option>
<option name="test" value="/api/search/ReviewLow/?reviewCnt=">리뷰 n개이하</option>
</optgroup>
<optgroup label="=== 검색어 없이 ===">
<option name="test" value="/api/search/ReviewASC">리뷰 적은순</option>
<option name="test" value="/api/search/ReviewDESC">리뷰 많은순</option>
<option name="test" value="/api/search/StarScoreASC">평점 낮은순</option>
<option name="test" value="/api/search/StarScoreDESC">평점 높은순</option>
</optgroup>
controller
앞쪽의 url 길이가 일정했던만큼 그 부분만큼을 잘라서 반환하도록 하고 그것을 매개변수로 넘겨줬다.
service
repository
위와 같이 변경해서 용도에 맞게 사용하도록 했다.
평점과 관련된 부분도 이제 구분이 가능해졌다.
오름차순 내림차순 정렬 관련
orderBy는 orderSpecifier로 넘겨줘야한다.
Booleanexception으로 반환받을수 있으면 좋겠지만 orderBy조건에서는 불가했다
그러면 위와같은 조건이 어떤 점이 문제냐면은 반환값에 에러가 있으면 안된다.
그래서 마지막에 아무 조건에 걸리지 않는 반환값이라면 Id로 정렬되게끔 처리했다
다른 방법을 찾아보려고 했으나 page에 관련된 내용이 많고 다른 방법은 없어서
그냥 이렇게 처리 했다
개선
'web > JAVA & SpringBoot' 카테고리의 다른 글
Jmeter 사용도 해보자 (0) | 2023.01.18 |
---|---|
m1 Mac에서 Jmeter 설치하기 (0) | 2023.01.18 |
가독성을 늘려주는 Query Dsl #2 (0) | 2023.01.12 |
가독성을 늘려주는 Query Dsl #1 (0) | 2023.01.12 |
내가 헷갈려서 쓰는 EC2와 RDS의 관계 (0) | 2023.01.06 |