Search code examples
javajpajava-8querydsl

QueryDsl avoiding multiple if blocks


Currently I am using Query DSL in my Java(with JPA) EE project. I recieve a filterObject from UI as json with all the filters. My FilterObject looks like this

public class FilterObject {

    private String name;
    private List<Status> status;
    private String module;
    private List<Source> source;
    ......
}

And in my service class I have something like this

 public List<MyModel> findByFilter(FilterObject filterObject) {
        BooleanBuilder builder = new BooleanBuilder();

        QMyModel mymodel= QMyModel.myModel;

        if(filterObject.getName() != null) {
            builder.and(mymodel.name.contains(filterObject.getName()));
        }
        if(! CollectionUtils.isEmpty(filterObject.getStatus())) {
            builder.and(mymodel.status.in(filterObject.getStatus()));
        }
        ...............
        ...............
}

And finally I have this

JPAQuery<MyModel> query = new JPAQuery<>(getEntityManager());
List<MyModel> myModels =  query.from(QMyModel.mymodel).where(builder).fetch();

EDIT:

/**
 * QMyModel is a Querydsl query type for MyModel
 */
@Generated("com.querydsl.codegen.EntitySerializer")
public class QMyModel extends EntityPathBase<MyModel> {

    private static final long serialVersionUID = 1041638507L;

    private static final PathInits INITS = PathInits.DIRECT2;

    public static final QMyModel myModel = new QMyModel("myModel");

    public final StringPath name = createString("name");

    public final EnumPath<Status> status = createEnum("status", Status.class);

    public final StringPath module = createString("module");

     ........
     .......
}

All these work. But my FilterObject is growing and has more than 10 fields. So I have like 10 If blocks in my service class method. Is there a better way to do this where I could avoid so many if blocks.


Solution

  • You can use lambda's, or (even better in this case) method reference:

    public List<MyModel> findByFilter(FilterObject filterObject) {
        BooleanBuilder builder = new BooleanBuilder();
    
        QMyModel mymodel = QMyModel.myModel;
    
        add(builder, filterObject.getName(), mymodel.name::contains);
        add(builder, filterObject.getStatus(), mymodel.status::in);
    
        ...
    }
    
    private <T> void add(BooleanBuilder builder, T filterElement, Function<T, BooleanExpression> booleanExpressionFunction) {
        if (valid(filterElement)) {
            builder.and(booleanExpressionFunction.apply(filterElement));
        }
    }
    
    private boolean valid(Object filterElement) {
        if (filterElement == null) {
            return false;
        }
        if (filterElement instanceof Collection) {
            return !((Collection) filterElement).isEmpty();
        }
        return true;
    }