필터 요청 - 중복 가능
클라이언트가 다음과 같이 요청을 한다.
http://localhost:8080/api/list?departmentFilter=A&departmentFilter=B&genderFilter=M&order=AGE
쿼리스트링을 살펴보면, departmentFilter 2개, genderFilter 1개, order 1개이다.
쿼리스트링의 모든 값 중에서 하나라도 해당하면 조회가 가능하도록 설계해보자.
먼저, Controller에서 요청 받는 부분이다.
Controller.java
@GetMapping("/list")
public ResponseEntity<List<PersonnelListResponse>> personnelList(
@RequestParam(value = "departmentFilter", required = false) List<DepartmentType> departmentFilter,
@RequestParam(value = "genderFilter", required = false) Gender genderFilter,
@RequestParam(value = "order", required = false) PersonnelOrderCondRequest orderCond
){
if(departmentFilter == null)
departmentFilter = new ArrayList<>();
List<PersonnelListResponse> responseDto = personnelService.personnelList(
new PersonnelFilterCondRequest(departmentFilter, genderFilter), orderCond);
return ResponseEntity.ok(responseDto);
}
departmentFilter는 여러 값을 받아야하기에 List로 선언해주어야 한다. 참고로 DepartmentType, Gender는 Enum 타입, order는 정렬 조건이다.
다른 계층에서 departmentFilter를 조작하기 전에 null체크를 한번 더 해주어야 하기 때문에 Controller에서 ArrayList로 초기화한다.
다음은 Querydsl로 작성한 코드이다.
Repository.java
private BooleanExpression filterEq(PersonnelFilterCondRequest filterCond){
final BooleanExpression[] booleanExpressionDepartmentType = new BooleanExpression[1];
if(!filterCond.getDepartmentTypeList().isEmpty()){
booleanExpressionDepartmentType[0] = (departmentTypeEq(filterCond.getDepartmentTypeList().get(0)));
filterCond.getDepartmentTypeList().stream()
.filter(departmentType -> !departmentType.equals(filterCond.getDepartmentTypeList().get(0)))
.forEach(
departmentType -> booleanExpressionDepartmentType[0] = (
departmentTypeEqOr(booleanExpressionDepartmentType[0], departmentType))
);
} else {
booleanExpressionDepartmentType[0] = null;
}
}
private BooleanExpression departmentTypeEq(DepartmentType departmentType){
return departmentType != null ? personnel.departmentType.eq(departmentType) : null;
}
BooleanExpression은 서로 조립해서 사용할 수 있다는 특징이 있다.
이를 이용하여 먼저 departmentFilter List를 순회하여 각각의 BooleanExpression을 만들어준다.
private BooleanExpression departmentTypeEqOr(BooleanExpression booleanExpression, DepartmentType departmentType){
return booleanExpression.or(departmentTypeEq(departmentType));
}
이 때 하나라도 조건이 만족하면 조회가 가능해야 하므로, or로 모든 BooleanExpression을 이어주어야한다.
BooleanExpression와 Filter 값을 null체크 하면서 gender도 마찬가지로 BooleanExpression값을 or로 이어준다.
private BooleanExpression filterEq(PersonnelFilterCondRequest filterCond){
BooleanExpression booleanExpressionGender;
if(!Objects.isNull(filterCond.getGender())){
booleanExpressionGender = genderEq(filterCond.getGender());
} else {
booleanExpressionGender = null;
}
}
private BooleanExpression genderEq(Gender gender){
return gender != null ? personnel.gender.eq(gender) : null;
}
전체코드
public List<PersonnelListResponse> findAllByCondition(PersonnelFilterCondRequest filterCond, PersonnelOrderCondRequest orderCond) {
return queryFactory
.select(Projections.constructor(PersonnelListResponse.class,
personnel.id,
personnel.name,
personnel.dateOfBirth,
personnel.phone,
personnel.address,
personnel.profileImage,
personnel.departmentType
))
.where(filterEq(filterCond))
.from(personnel)
.fetch();
}
private BooleanExpression filterEq(PersonnelFilterCondRequest filterCond){
final BooleanExpression[] booleanExpressionDepartmentType = new BooleanExpression[1];
if(!filterCond.getDepartmentTypeList().isEmpty()){
booleanExpressionDepartmentType[0] = (departmentTypeEq(filterCond.getDepartmentTypeList().get(0)));
filterCond.getDepartmentTypeList().stream()
.filter(departmentType -> !departmentType.equals(filterCond.getDepartmentTypeList().get(0)))
.forEach(
departmentType -> booleanExpressionDepartmentType[0] = (
departmentTypeEqOr(booleanExpressionDepartmentType[0], departmentType))
);
} else {
booleanExpressionDepartmentType[0] = null;
}
BooleanExpression booleanExpressionGender;
if(!Objects.isNull(filterCond.getGender())){
booleanExpressionGender = genderEq(filterCond.getGender());
} else {
booleanExpressionGender = null;
}
if(booleanExpressionDepartmentType[0] == null){
return booleanExpressionGender;
}
return booleanExpressionDepartmentType[0].or(booleanExpressionGender);
}
private BooleanExpression departmentTypeEq(DepartmentType departmentType){
return departmentType != null ? personnel.departmentType.eq(departmentType) : null;
}
private BooleanExpression departmentTypeEqOr(BooleanExpression booleanExpression, DepartmentType departmentType){
return booleanExpression.or(departmentTypeEq(departmentType));
}
private BooleanExpression genderEq(Gender gender){
return gender != null ? personnel.gender.eq(gender) : null;
}
'Spring' 카테고리의 다른 글
Spring Security Remember-Me (0) | 2024.06.22 |
---|---|
Spring Cloud Config URL 조회 시 보안 (0) | 2023.11.04 |
Embedded Redis로 테스트 환경 구축하기 (0) | 2023.10.30 |
Spring Cloud Config Watch (1) | 2023.10.11 |
Spring Gateway 에러 핸들링 (0) | 2023.09.19 |