본문 바로가기

Programming!

QueryDSL Predicate Builder 추가

조건관련 작업시 아래처럼 엔티티별 별도의 Predicate를 사용하기는 하는데 가끔 보기 싫을 때가 있다.

기존에는 아래처럼 조건을 별도로 구분해서 나눈 후, allOf로 조합처리 했는데.

	public static Predicate containsBrandName(BrandFindCondition condition) {
		BooleanBuilder builder = new BooleanBuilder();
		if (!StringUtils.isEmpty(condition.getBrandName())) {
			builder.and(qBrandEntity.brandName.contains(condition.getBrandName()));
		}
		return builder;
	}

	public static Predicate containsBrandCode(BrandFindCondition condition) {
		BooleanBuilder builder = new BooleanBuilder();
		if (!StringUtils.isEmpty(condition.getBrandCode())) {
			builder.and(qBrandEntity.brandCode.contains(condition.getBrandCode()));
		}
		return builder;
	}

 

막 사용하다 보면 이런식으로 사용되어지고 있게 되어서...

public static Predicate whereAll(BrandFindCondition condition) {
	BooleanBuilder builder = new BooleanBuilder();
	if (!StringUtils.isEmpty(condition.getBrandName())) {
		builder.and(qBrandEntity.brandName.contains(condition.getBrandName()));
	}
	if (!StringUtils.isEmpty(condition.getBrandCode())) {
		builder.and(qBrandEntity.brandCode.contains(condition.getBrandCode()));
	}
	if ( .....
	return builder;
}

이거나 저거나 if 조건이 자꾸 늘어나서 아타까움(optional로 걸어봐야 그게 그거). 물론 별도 Predicate를 만든 후라 Repository나 Service는 깔끔하게 보이기는 하는데..

 

해서, 비교 확인차 우선 Builder를 만들어 추가해 보기로 함.

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class WhereClauseBuilder {

	private List<Predicate> predicateBuilders = new ArrayList<>();

	public static WhereClauseBuilder builder() {
		return new WhereClauseBuilder();
	}

	public WhereClauseBuilder and(Predicate predicate) {
		predicateBuilders.add(predicate);
		return this;
	}

	public Predicate build() {
		return ExpressionUtils.allOf(predicateBuilders);
	}

	public WhereClauseBuilder like(StringPath path, String value) {
		if (StringUtils.isEmpty(value)) {
			return this;
		}
		predicateBuilders.add(path.contains(value));
		return this;
	}

	public WhereClauseBuilder eq(StringPath path, String value) {
		if (StringUtils.isEmpty(value)) {
			return this;
		}
		predicateBuilders.add(path.eq(value));
		return this;
	}

	public WhereClauseBuilder eq(BooleanPath path, Boolean value) {
		predicateBuilders.add(path.eq(value));
		return this;
	}

	public WhereClauseBuilder eqId(NumberPath<Long> path, Long value) {
		if (Objects.isNull(value)) {
			return this;
		}
		predicateBuilders.add(path.eq(value));
		return this;
	}
}

사용할때는 이런식.

	public List<BrandEntity> findAll(BrandFindCondition condition) {
		return from(qBrandEntity).where(
				WhereClauseBuilder.builder()
				.like(qBrandEntity.brandName, condition.getBrandName())
				.eq(qBrandEntity.brandCode, condition.getBrandCode())
				.build()
			).fetch();
	}

숫자의 경우에는 Enum처리를 했는데.. 제너릭으로 WhereClauseBuilder에서 처리해야 하나 고민 스럽.. 뭐 따로빼서 처리.

.and(NumberClausePredicate.GT.compare(qBrandEntity.price, price))

딱히 뭐가 이뻐졌는지는 모르겠...엔티티별 별도의 Predicate를 두고 하나하나 조건을 만든후에 allOf를 하는게 더 명시적이고 유지보수가 쉬울꺼 같기도하고.. 아닌거 같기도 하고.. Null이 참 그러네..ㅎㅎ

 

 

좀 더 작업해 보다가 결정해야겠다.  이런거 고민 할 시간에 서비스 하나 후딱 만들어서 돈벌게 되면 더 좋은 개발자를 데려와서 고쳐주십...콜록콜록..켁켁..