3. General usage

The General usage section covers aspects that are not covered in the tutorial section of the reference documentation. It follows a use case oriented structure.

3.1. Creating queries

Query construction in Querydsl involves calling query methods with expression arguments. Since query methods are mostly module specific and have already been presented in the tutorial section, this part will focus on expressions.

Expressions are normally constructed by accessing fields and calling methods on the generated expression types of your domain module. For cases where code generation is not applicable generic ways to construct expressions can be used instead.

3.1.1. Complex predicates

To construct complex boolean expressions, use the com.mysema.query.BooleanBuilder class. It implements Predicate and can be used in cascaded form:

public List<Customer> getCustomer(String... names) {
    QCustomer customer = QCustomer.customer;
    JPAQuery query = new JPAQuery(entityManager).from(customer);
    BooleanBuilder builder = new BooleanBuilder();
    for (String name : names) {
        builder.or(customer.name.eq(name));
    }
    query.where(builder); // customer.name eq name1 OR customer.name eq name2 OR ...
    return query.list(customer);
}

BooleanBuilder is mutable and represents initially null and after each and or or call the result of the operation.

3.1.2. Dynamic expressions

The com.mysema.query.support.Expressions class is a static factory class for dynamic expression construction. The factory methods are named by the returned type and are mostly self-documenting.

In general the Expressions class should be used only in cases where fluent DSL forms can't be used, such as dynamic paths, custom syntax or custom operations.

The following expression

QPerson person = QPerson.person;
person.firstName.startsWith("P");

could be constructed like this if Q-types wouldn't be available

Path<Person> person = Expressions.path(Person.class, "person");
Path<String> personFirstName = Expressions.path(String.class, person, "firstName");
Constant<String> constant = Expressions.constant("P");
Expressions.predicate(Ops.STARTS_WITH, personFirstName, constant);

Path instances represent variables and properties, Constants are constants, Operations are operations and TemplateExpression instances can be used to express expressions as String templates.

3.1.3. Dynamic paths

In addition to the Expressions based expression creation Querydsl provides also a more fluent API for dynamic path creation.

For dynamic path generation the com.mysema.query.types.path.PathBuilder class can be used. It extends EntityPathBase and can be used as an alternative to class generation and alias-usage for path generation.

Compared to the Expressions API PathBuilder doesn't provide direct support for unknown operations or custom syntax, but the syntax is closer to the normal DSL.

String property:

PathBuilder<User> entityPath = new
PathBuilder<User>(User.class, "entity");
// fully generic access
entityPath.get("userName");
// .. or with supplied type
entityPath.get("userName", String.class);
// .. and correct signature
entityPath.getString("userName").lower();

List property with component type:

entityPath.getList("list", String.class).get(0);

Using a component expression type:

entityPath.getList("list", String.class, StringPath.class).get(0).lower();

Map property with key and value type:

entityPath.getMap("map", String.class, String.class).get("key");

Using a component expression type:

entityPath.getMap("map", String.class, String.class, StringPath.class).get("key").lower();

For PathBuilder validation a PathBuilderValidator can be used. It can be injected in the constructor and will be used transitively for the new PathBuilder

PathBuilder<Customer> customer = new PathBuilder<Customer>(Customer.class, "customer", validator);

PathBuilderValidator.FIELDS will verify field existence, PathBuilderValidator.PROPERTIES validates Bean properties and JPAPathBuilderValidator validates using a JPA metamodel.

3.1.4. Case expressions

To construct case-when-then-else expressions use the CaseBuilder class like this:

QCustomer customer = QCustomer.customer;
Expression<String> cases = new CaseBuilder()
    .when(customer.annualSpending.gt(10000)).then("Premier")
    .when(customer.annualSpending.gt(5000)).then("Gold")
    .when(customer.annualSpending.gt(2000)).then("Silver")
    .otherwise("Bronze");
// The cases expression can now be used in a projection or condition

For case expressions with equals-operations use the following simpler form instead:

QCustomer customer = QCustomer.customer;
Expression<String> cases = customer.annualSpending
    .when(10000).then("Premier")
    .when(5000).then("Gold")
    .when(2000).then("Silver")
    .otherwise("Bronze");
// The cases expression can now be used in a projection or condition

Case expressions are not yet supported in JDOQL.

3.1.5. Casting expressions

To avoid a generic signature in expression types the type hierarchies are flattened. The result is that all generated query types are direct subclasses of com.mysema.query.types.path.EntityPathBase or com.mysema.query.types.path.BeanPath and cannot be directly cast to their logical supertypes.

Instead of a direct Java cast, the supertype reference is accessible via the _super field. A _super-field is available in all generated query types with a single supertype:

// from Account
QAccount extends EntityPathBase<Account> {
    // ...
}

// from BankAccount extends Account
QBankAccount extends EntityPathBase<BankAccount> {

    public final QAccount _super = new QAccount(this);

    // ...
}

To cast from a supertype to a subtype you can use the as-method of the EntityPathBase class:

QAccount account = new QAccount("account");
QBankAccount bankAccount = account.as(QBankAccount.class);

3.1.6. Select literals

Literals can be selected by refering to them via Constant expressions. Here is a simple example

query.list(Expressions.constant(1),
           Expressions.constant("abc"));

Constant expressions are often used in subqueries.