Programming!

QueryDSL Predicate Builder 추가

eclipse4j(Grissom) 2019. 12. 19. 11:44

조건관련 작업시 아래처럼 엔티티별 별도의 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이 참 그러네..ㅎㅎ

 

 

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