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.
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;
}