Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to simplify syntax with dynamic QueryDSL, avoiding multiple "if"

Tags:

querydsl

I am building a dynamic query using a FilfetDto If the user has filled some field in the UI, th e contains some values but not all. So i have to test each property to construct a query filtering only on filled (not empty) field :

    JPAQuery dslQuery = new JPAQuery(em);

    dslQuery.from(book);
    dslQuery.join(book.author, author);      

    String title = StringUtils.upperCase(StringUtils.trim(_filter.getTitle()));
    if (StringUtils.isNotBlank(title)) {
        dslQuery.where(book.title.upper().like(title));
    }
    String isbn = StringUtils.trim(_filter.getIsbn());
    if (StringUtils.isNotBlank(isbn)) {
        dslQuery.where(book.isbn.like(isbn));
    }
    if (_filter.getAuthorId() != null) {
        dslQuery.where(author.id.eq(_filter.getAuthorId()));
    }

Is there a way to abstract the "if" with another more readable syntax ?

I would like something like :

    JPAQuery dslQuery = new JPAQuery(em);

    dslQuery.from(book);
    dslQuery.join(book.author, author);

    dslQuery.where(book.title.upperIfNotBlank().like(title));
    dslQuery.where(book.isbn.likeIfNotNull(isbn));
    dslQuery.where(author.id.eqIfNotNull(_filter.getAuthorId()));

It would be nice if the "IfNotNull" could be turned on, or even be the default behaviour ...
so it would end up like this :

    dslQuery.where(book.title.upper().like(title));
    dslQuery.where(book.isbn.like(isbn));
    dslQuery.where(author.id.eq(_filter.getAuthorId()));
like image 609
Gauthier Peel Avatar asked Oct 06 '22 21:10

Gauthier Peel


2 Answers

Is there a way to abstract the "if" with another more readable syntax ?

No, and probably there won't be. The aim of Querydsl expressions is to stay as close to the form that is used by the underlying persistence technology.

If you want to use such an approach in your own project feel free to put this into your own subclass of AbstractJPAQuery. Querydsl queries are meant to be customized for such cases.

like image 108
Timo Westkämper Avatar answered Oct 10 '22 03:10

Timo Westkämper


I create a QueryDSLHelper class which has static methods which do the null check before adding the expression. Something like this:

public static void goe(BooleanBuilder builder, DateTimePath<Date> path, Date value) {
    if(date!=null) {
        builder.and(path.goe(value));
    }
}

public static void like(BooleanBuilder builder, StringPath path, String value) {
    if(value!=null) {
        builder.and(path.like(value));
    }
}

Now I can just statically import those methods and call them on one line:

        like(builder, book.isbn, isbn);

This is extremely useful and very clean/readable when implementing 'filter' or 'filterByExample' queries.

like image 34
prule Avatar answered Oct 10 '22 03:10

prule