Skip to content

Queries

Michele Scuttari edited this page Apr 2, 2018 · 1 revision

Query builder

Entity manager provides access to the query builder, which can, as the name suggests, build the select queries in an object oriented way. The query builder instantiation requires as its only parameter the entity class desired for the query results.

QueryBuilder<ResultClass> qb = em.getQueryBuilder(ResultClass.class);

The queries are also meant to be polymorphic: by specifying as result class an entity with children, the query will return objects corresponding to their real type. So the "ResultClass" can be better seen as a common superclass of the results.

FROM clause

In order to specify the query source table (usually specified in the query "FROM" clause), we need to get the entity root by using the query builder previously created.

Root<FromClass> root = qb.getRoot(FromClass.class);

Then the entity root can be assigned to the query builder. In act of the building the query, parent and children tables will be automatically joined in case of entities implementing inheritance.

qb.from(root);

JOIN clause

Join clauses can be built by joining together different roots by means of a linkin property belonging to left side entity. When a root is joined with another one, the resulting root still refers to the first one, in order to allow for multiple joins.

Root<X> xRoot = qb.getRoot(X.class);
Root<Y> yRoot = qb.getRoot(Y.class);
Root<Z> zRoot = qb.getRoot(Z.class);

Root<X> joinRoot = xRoot.join(yRoot, X_.linkToY).join(zRoot, X_.linkToZ);

It is also possible to create complex joins by first creating the two sides of the join (which can be joins too) and then joining them together. In other words, the join structure can be seen as a bipartite tree.

// Going on with the previous example

Root<A> aRoot = qb.getRoot(A.class);
Root<B> bRoot = qb.getRoot(B.class);
Root<A> aJoinRoot = aRoot.join(bRoot, A_.linkToB);

Root<X> doubleJoinRoot = joinRoot.join(aJoinRoot, X_.linkToA);

WHERE clause

Where clauses can be built in mostly the same way of joins clauses. Each root allows to create expressions based upon root class properties, which can be linked to a specific value or to another property.

  • IS NULL: Expression isNull = root.isNull(Entity_.property);
  • EQUAL: Expression eq = root.eq(Entity_.property, value / property);
  • GREATER: Expression gt = root.gt(Entity_.property, value / property);
  • GREATER OR EQUAL: Expression ge = root.ge(Entity_.property, value / property);
  • LESS: Expression lt = root.lt(Entity_.property, value / property);
  • LESS OR EQUAL: Expression le = root.le(Entity_.property, value / property);

Expression can then be concatenated to create more complex ones by using "not", "and" and "or" logical operators.

  • NOT: Expression negatedExpression = expression.not();
  • AND: Expression andExpression = firstExpression.and(secondExpression);
  • OR: Expression orExpression = firstExpression.or(secondExpression);

Then the expression can be assigned to the query builder as the query "where" clause.

root.where(expression);

Build and run

After having assignined at least the "from" clause, the query can be built and run. The target root must be one of the roots used during the "from" clause creation and represent the root from which the results will be extracted

List<ResultClass> resultsList = qb.build(targetRoot).getResultsList();

If just the first query result item is needed, it is possible to call the dedicated method:

ResultClass resultObject = qb.build(targetRoot).getSingleResult();
Clone this wiki locally