Querydsl defines a general statically typed syntax for querying on top of persisted domain model data. JDO and JPA are the primary integration technologies for Querydsl. This guide describes how to use Querydsl in combination with JPA/Hibernate.
Add the following dependency to your Maven project and make sure that the Maven 2 repo of Mysema Source (http://source.mysema.com/maven2/releases) is accessible from your POM :
<http://xslthl.sf.net:tag><dependency></http://xslthl.sf.net:tag> <http://xslthl.sf.net:tag><groupId></http://xslthl.sf.net:tag>com.mysema.querydsl<http://xslthl.sf.net:tag></groupId></http://xslthl.sf.net:tag> <http://xslthl.sf.net:tag><artifactId></http://xslthl.sf.net:tag>querydsl-hql<http://xslthl.sf.net:tag></artifactId></http://xslthl.sf.net:tag> <http://xslthl.sf.net:tag><version></http://xslthl.sf.net:tag>0.4.0<http://xslthl.sf.net:tag></version></http://xslthl.sf.net:tag> <http://xslthl.sf.net:tag></dependency></http://xslthl.sf.net:tag>
And now, configure the Maven APT plugin :
<http://xslthl.sf.net:tag><project></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><build></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><plugins></http://xslthl.sf.net:tag>
...
<http://xslthl.sf.net:tag><plugin></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><groupId></http://xslthl.sf.net:tag>com.mysema.maven<http://xslthl.sf.net:tag></groupId></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><artifactId></http://xslthl.sf.net:tag>maven-apt-plugin<http://xslthl.sf.net:tag></artifactId></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><version></http://xslthl.sf.net:tag>0.3.0<http://xslthl.sf.net:tag></version></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><executions></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><execution></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><goals></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><goal></http://xslthl.sf.net:tag>process<http://xslthl.sf.net:tag></goal></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></goals></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><configuration></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><outputDirectory></http://xslthl.sf.net:tag>target/generated-sources/java<http://xslthl.sf.net:tag></outputDirectory></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag><processor></http://xslthl.sf.net:tag>com.mysema.query.hql.apt.JPAAnnotationProcessor<http://xslthl.sf.net:tag></processor></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></configuration></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></execution></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></executions></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></plugin></http://xslthl.sf.net:tag>
...
<http://xslthl.sf.net:tag></plugins></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></build></http://xslthl.sf.net:tag>
<http://xslthl.sf.net:tag></project></http://xslthl.sf.net:tag>
The JPAAnnotationProcessor finds domain types annotated with the javax.persistence.Entity annotation and generates query types for them.
Run mvn eclipse:eclipse or clean install and you will get your Query types generated into target/generated-sources/java. Now you are able to construct JPAQL/HQL query instances and instances of the query domain model.
To create queries with Querydsl you need to instantiate variables and Query implementations. We will start with the variables.
Let's assume that your project has the following domain type :
@Entity
public class Customer {
private String firstName;
private String lastName;
public String getFirstName(){
return firstName;
}
public String getLastName(){
return lastName;
}
public void setFirstName(String fn){
firstName = fn;
}
public void setLastName(String ln)[
lastName = ln;
}
}
Querydsl will generate a query type with the simple name QCustomer into the same package as Customer. QCustomer can be used as a statically typed variable in Querydsl queries as a representative for the Customer type.
QCustomer has a default instance variable which can be accessed as a static field :
QCustomer customer = QCustomer.customer;
Alternatively you can define your own Customer variables like this :
QCustomer customer = new QCustomer("myCustomer");
For the HQL-module HQLQueryImpl is the main Query implementation. It is instantiated like this :
HQLQuery query = new HQLQueryImpl (session); // where session is a Hibernate session
To retrieve the customer with the first name Bob you would construct a query like this :
QCustomer customer = QCustomer.customer;
HQLQuery query = new HQLQueryImpl (session);
Customer bob = query.from(customer)
.where(customer.firstName.eq("Bob"))
.uniqueResult(customer);
The from call defines the query source, the where part defines the filter and uniqueResult defines the projection and tells Querydsl to return a single element. Easy, right?
To create a query with multiple sources you just use the HQLQuery interface like this :
query.from(customer, company);
And to use multiple filters use it like this
query.from(customer)
.where(customer.firstName.eq("Bob"), customer.lastName.eq("Wilson"));
Or like this
query.form(customer)
.where(customer.firstName.eq("Bob").and(customer.lastName.eq("Wilson")));
In native HQL form the query would be written like this :
from Customer as customer
where customer.firstName = "Bob" and customer.lastName = "Wilson"
Querydsl supports the following join variants in HQL/JPAQL : inner join, join, left join and full join. Join usage is typesafe, and follows the following pattern :
query.from(cat)
.innerJoin(cat.mate, mate)
.leftJoin(cat.kittens, kitten)
.list(cat);
The native HQL version of the query would be
from Cat as cat
inner join cat.mate as mate
left outer join cat.kittens as kitten
Another example
query.from(cat)
.leftJoin(cat.kittens, kitten)
.on(kitten.bodyWeight.gt(10.0))
.list(cat);
With the following HQL version
from Cat as cat
left join cat.kittens as kitten
with kitten.bodyWeight > 10.0
The syntax for declaring ordering is
query.from(customer)
.orderBy(customer.lastName.asc(), customer.firstName.desc())
.list(customer);
which is equivalent to the following native HQL
from Customer as customer
order by customer.lastName asc, customer.firstName desc
Grouping can be done in the following form
query.from(customer)
.groupBy(customer.lastName)
.list(customer.lastName);
which is equivalent to the following native HQL
select customer.lastName
from Customer as customer
group by customer.lastName
Subqueries in the HQL module are just special projections of the HQLQuery interface. To create a subquery you create a HQLQuery instance, define the query parameters via from, where etc and use uniqueExpr or listExpr to create a subquery, which is just a type-safe Querydsl expression for the query. uniqueExpr is used for a unique result and listExpr for a list result.
query().from(department)
.where(department.employees.size().eq(
query().from(d).uniqueExpr(AggregationFunctions.max(d.employees.size()))
)).list(department);
Another example
query().from(employee)
.where(employee.weeklyhours.gt(
query().from(employee.department.employees, e)
.where(e.manager.eq(employee.manager))
.uniqueExpr(AggregationFunctions.avg(e.weeklyhours))
)).list(employee);