Last weekend I posted a thread in our Mysema Source Forum related to the verbosity of JPA 2 Criteria queries.
The thread presents JPA 2 and Querydsl queries side by side. Just that, not more. Here is one query comparison example.
The use case of this example is to query for single men and women as an cartesian view. At first the query expressed via the JPA 2 Criteria API :
CriteriaQuery query = builder.createQuery(); Root<Person> men = query.from( Person.class ); Root<Person> women = query.from( Person.class ); Predicate menRestriction = builder.and( builder.equal( men.get( Person_.gender ), Gender.MALE ), builder.equal( men.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )); Predicate womenRestriction = builder.and( builder.equal( women.get( Person_.gender ), Gender.FEMALE ), builder.equal( women.get( Person_.relationshipStatus ), RelationshipStatus.SINGLE )); query.where( builder.and( menRestriction, womenRestriction ) );
and now via Querydsl
JPAQuery query = new JPAQuery(em); QPerson men = new QPerson("men"); QPerson women = new QPerson("women"); query.from(men, women).where( men.gender.eq(Gender.MALE), men.relationshipStatus.eq(RelationshipStatus.SINGLE), women.gender.eq(Gender.FEMALE), women.relationshipStatus.eq(RelationshipStatus.SINGLE));
The guys from the JPA group decided that fluent expression construction is not an option so a CriteriaBuilder for criteria construction was needed. CriteriaBuilder contains methods for all possible operation constructs, not grouped in any way.
Compare this with Querydsl, which has a dynamic query model with a fluent API, which supports IDE autocomplete and a much faster and compact way to write queries.
Also the distinction of paths, joins and the metamodel doesn't really make query construction easy.
A root path for the Person type is constructed like this in JPA 2 :
Root<Person> men = query.from( Person.class );
In Querydsl you just create an instance of the metatype for Person :
QPerson men = new QPerson("men");
In most cases though you can use the default instance of the metatype like this :
QPerson men = QPerson.person;
And to refer to the gender property of the Person path :
whereas in Querydsl you just use a field of the metatype instance :
The dynamic metatypes of Querydsl combine a type-safe representation of the query domain, path references and operation construction in a fluent and concise way.
In addition to JPAQL and HQL Querydsl supports JDOQL, SQL, RDF, Lucene, Hibernate Search and Java collections.
We at Mysema use Querydsl in all our own projects with multiple backends and are 100% happy with it. ;)