To avoid a generic signature in Querydsl query 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 Querydsl 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);
Querydsl provides the possibility to use constructor invocations in projections. To use a constructor in a query projection, you need to annotate it with the QueryProjection annotation :
class CustomerDTO { @QueryProjection public CustomerDTO(long id, String name){ ... } }
And then you can use it like this in the query
QCustomer customer = QCustomer.customer; JPQLQuery query = new HibernateQuery(session); List<CustomerDTO> dtos = qry.from(customer).list(new QCustomerDTO(customer.id, customer.name));
While the example is Hibernate specific, this feature is available in all modules.
If the type with the QueryProjection annotation is not an annotated entity type, you can use the constructor projection like in the example, but if the annotated type would be an entity type, then the constructor projection would need to be created via a call to the static create method of the query type :
@Entity class Customer { @QueryProjection public Customer(long id, String name){ ... } }
QCustomer customer = QCustomer.customer;
JPQLQuery query = new HibernateQuery(session);
List<Customer> dtos = qry.from(customer).list(QCustomer.create(customer.id, customer.name));
Alternatively, if code generation is not an option, you can create a constructor projection like this :
List<Customer> dtos = qry.from(customer)
.list(EConstructor.create(Customer.class, customer.id, customer.name));
To construct complex boolean expressions, use the BooleanBuilder class. It implements Predicate and can be used in cascaded form :
public List<Customer> getCustomer(String... names){ QCustomer customer = QCustomer.customer; HibernateQuery qry = new HibernateQuery(session).from(customer); BooleanBuilder builder = new BoolenBuilder(); for (String name : names){ builder.or(customer.name.eq(name)); } qry.where(builder); // customer.name eq name1 OR customer.name eq name2 OR ... return qry.list(customer); }
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.
For dynamic path generation the PathBuilder class can be used. It extends EntityPathBase and can be used as an alternative to class generation and alias-usage for path generation.
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();