I've used CriteriaQuery a little bit, and like Jasha mentioned it isn't as 
clear to read, but they are very powerful and flexible.  The downside is you 
lose the pre-verification and caching of the named query statement.  However, I 
believe situations like this (i.e. dynamic order by clause) is what they are 
designed to be used for so I don't think there is any harm in using them.  Good 
comments always make ugly code better readable too :)

Tony

---
Anthony Carlucci | SW App Dev Eng, Sr. | R501 / KW App Development & Maint
e: [email protected] | v: 781.271.2432 | f: 781.271.3299
The MITRE Corporation | 202 Burlington Rd | Bedford, MA 01730-1420


-----Original Message-----
From: Cooper, Sean D. [mailto:[email protected]] 
Sent: Tuesday, October 25, 2011 9:11 AM
To: [email protected]
Subject: RE: Growing amount of queries

Yeah, JPA NamedQuerys are pre-generated.  You can't even use static final 
variables in them to keep field name consistency!  I don't know of a better way 
of doing this, if someone bounces a better solution to you, can you please 
forward it to me so I can see it as well.

-Sean

-----Original Message-----
From: Jasha Joachimsthal [mailto:[email protected]] 
Sent: Tuesday, October 25, 2011 9:07 AM
To: [email protected]
Subject: Growing amount of queries

For the admin interface I wanted to add search on either the widget
title/description or type or status and add sorting options of the widget
table columns (title, status, type)

For the (optional) search parameters the NamedQuery contains statements
like:
:type is null OR :type = '' OR w.type = :type

As it turns out, it's not possible to dynamically set the sort field and
order with NamedQueries. That would mean I have to create 6 queries to
support both asc and desc order for title, status and type :(

The current setup:
Widget.java:
        @NamedQuery(name =
Widget.WIDGET_GET_BY_STATUS_AND_TYPE_AND_FREE_TEXT,
                query = Widget.SELECT_W_FROM_WIDGET_W +
Widget.WHERE_CLAUSE_STATUS_TYPE_FREE_TEXT)

JpaWidgetRepository.java:
        TypedQuery<Widget> query =
manager.createNamedQuery(Widget.WIDGET_GET_BY_STATUS_AND_TYPE_AND_FREE_TEXT,
                Widget.class);
        query.setParameter(Widget.PARAM_STATUS, widgetStatus);
        query.setParameter(Widget.PARAM_TYPE, type);
        setFreeTextSearchTerm(query, searchTerm);
        return getPagedResultList(query, offset, pageSize);

Instead of using NamedQueries we can also use criteria. The new code in
JpaWidgetRepository would be:
        final CriteriaBuilder cb = manager.getCriteriaBuilder();
        final CriteriaQuery<Widget> query = cb.createQuery(Widget.class);
        Root<Widget> widget = query.from(Widget.class);
        List<Predicate> predicates = new ArrayList<Predicate>();
            predicates.add(
                    cb.or(
                            cb.like(cb.lower(widget.<String>get("title")),
getLowerCaseWildCardSearchTerm(searchTerm)),

cb.like(cb.lower(widget.<String>get("description")),
getLowerCaseWildCardSearchTerm(searchTerm))
                    )
            );
            predicates.add(cb.and(cb.equal(widget.<String>get("type"),
type)));

predicates.add(cb.and(cb.equal(widget.<WidgetStatus>get("widgetStatus"),
widgetStatus)));
        query.where(predicates.toArray(new Predicate[predicates.size()]));
        return
manager.createQuery(query).setFirstResult(offset).setMaxResults(pageSize).getResultList();

CriteriaQuery#orderBy() can be dynamically added so that would solve the
issue of having many named queries. The syntax is a bit more difficult to
understand than the named query.
Are there any other ideas that could solve this issue of having a flexible
number of criteria (type or widgetStatus may not be queried) and flexible
sort options?

Jasha Joachimsthal

Europe - Amsterdam - Oosteinde 11, 1017 WT Amsterdam - +31(0)20 522 4466
US - Boston - 1 Broadway, Cambridge, MA 02142 - +1 877 414 4776 (toll free)

www.onehippo.com

Reply via email to