\ In this tutorial, I want to show you a way of how to perform persistence operations with Criteria API in a more convenient form using Builder pattern and JPA Static Metamodel Generator. \ **The full source code is available over on [Github](https://github.com/alexandermakeev/criteria-api-helper).** # 1 Spring Data JPA \ In the Java world, the most popular way to work with relational databases is to use Spring Data JPA. It is quite a sophisticated framework that allows you to instantly get started working with the database. The most compelling feature in the Spring Data is the Repository. All you need to do to access the database table is to create a Java interface and extend it from the `CrudRepository` with the defined domain class and with the id type of the domain class as type arguments: ```java public interface CustomerRepository extends CrudRepository<Customer, Long> { } ``` \ For each declared interface, Spring will create an appropriate bean, allowing you to easily use it with Dependency Injection. With the `CrudRepository`, this interface will provide basic implementations for CRUD operations for the managed entity class. For example, the following read operations will allow you to retrieve all the rows and a specific row by id: ```java package org.springframework.data.repository; public interface CrudRepository<T, ID> extends Repository<T, ID> { … Iterable<T> findAll(); Optional<T> findById(ID id); … } ``` \ If you want to filter the data with specific predicates, Spring Repository allows you to define your own methods with the query derivation mechanism using entity’s fields and keywords: ```java public interface CustomerRepository extends CrudRepository<Customer, Long> { List<Customer> findByLastName(String lastName); List<Customer> findByZipCode(String zipCode); List<Customer> findByLastNameAndZipCode(String lastName, String zipCode); } ``` \ It looks very clear and convenient. But there are few cons and pitfalls you should be aware of: \ 1. **Typo mistakes** Using query derivation mechanism language to compose a query, you can really minimize your code with supported keywords. Modern Intellij IDEA will help you to build such a query quite easily: ```java @Entity class Customer { @Id private Long id; private String zipCode; } interface CustomerRepository extends CrudRepository<Customer, Long> { List<Customer> findAllByZip(String zipCode); } ``` \ If we construct a query using wrong or non-existing field names, like `zip` instead of `zipCode`, when we run this code we will probably see an exception, saying that no property `zip` is found for the `Customer` type: :::info **Caused by: org.springframework.data.mapping.PropertyReferenceException: No property 'zip' found for type 'Customer' Did you mean ''id''** ::: \ But if we change the argument type of this field, for example to `Integer`, we will not receive any exception during start up: ```java @Entity class Customer { @Id private Long id; private String zipCode; } interface CustomerRepository extends CrudRepository<Customer, Long> { List<Customer> findAllByZipCode(Integer zipCode); } ``` \ You’ll receive an exception only when you manually invoke this method passing specific value: :::info **java.lang.IllegalArgumentException: Parameter value \[90001\] did not match expected type \[java.lang.String (n/a)\]** ::: \ There is no way to mock this part of code. Therefore, you should be very careful when you compose a query or when you refactor an entity’s field type. \ 2. **Read complexity** Query derivation mechanism language is quite useful, but it becomes difficult to read if you deal with a complex query containing a deep nested join. Let’s say we want to get Order entities filtered by address attributes: ```java List<Order> findAllByCustomerAddressAddressLineLikeAndCustomerAddressCityNameAndCustomerAddressCityCountryName(String addressLine, String city, String country); ``` \ Sure, you can simplify this query with JPQL using the `@Query` annotation over this method. But in this case, you will lose all the privileges of the query derivation mechanism with proper validation when Spring starts up: ```java public interface OrderRepository extends CrudRepository<Order, Long> { @Query("SELECT o FROM Order o " + " INNER JOIN o.customer cr" + " INNER JOIN cr.address a" + " INNER JOIN a.city ct" + " INNER JOIN ct.country cn" + " WHERE a.addressLine LIKE :address_line AND ct.name = :city AND cn.name = :country") List<Order> filterByAddress(@Param("address_line") String addressLine, @Param("city") String city, @Param("country") String country); } ``` \ The other scenario is to use the Criteria API by extending your Repository with `JpaSpecificationExecutor` interface and allowing you to access the `Root`, `CriteriaQuery` and `CriteriaBuilder` within the `Specification` interface: ```java orderRepository.findAll((Specification<Order>) (root, query, cb) -> { Path<Address> addressPath = root.get(Order_.customer).get(Customer_.address); Path<City> cityPath = addressPath.get(Address_.city); return cb.and( cb.equal(addressPath.get(Address_.addressLine), "%" + addressLine + "%"), cb.equal(cityPath.get(City_.name), city), cb.equal(cityPath.get(City_.country).get(Country_.name), country) ); }); ``` \ 2. **Explicitness** Using Spring Data JPA, we have to create a repository for each table. Explicitness is always good, but it’s quite problematic if you have about 200 tables. In this case, you need to create 200 repositories accordingly, even if you need only one query per repository. \ # 2 Extension implementation My idea is to eliminate all these issues by creating an extension for the Criteria API: ```java select() .equal(Order_.status, OrderStatus.Shipped) .like(Order_.customer, Customer_.address, Address_.addressLine, “11 Aleksandr Pushkin St”) .equal(Order_.customer, Customer_.address, Address_.city, City_.name, “Tbilisi”) .findAll(); ``` \ 1. First of all, to exclude all the typo errors, we will use the JPA Static Metamodel with an explicit parent-child path chain and with generic types to eliminate any errors during compilation. Each argument will accept an entity's attribute, providing only logical relations with a corresponding data value at the end: ```java equal(Order_.customer, Customer_.address, Address_.city, City_.country, Country_.name, “Georgia”) ``` \ 2. To reduce read complexity and eliminate nested path duplication, we can use the Builder pattern with common paths: ```java select() .equal(Order_.status, OrderStatus.Shipped) .and(Order_.customer, Customer_.address, like(Address_.addressLine, "11 Aleksandr Pushkin St"), and(Address_.city, equal(City_.name, "Tbilisi"), equal(City_.country, Country_.name, “Georgia”) ) ) .findAll(); ``` \ 3. To get rid of redundant explicitness by creating a separate repository for each entity, our extension will accept the entity type of the table that we use to start the query from. By passing the entity type explicitly, we can compose queries from any place in the code: ```java select(Order.class) .equal(Order_.status, OrderStatus.Shipped) .and(Order_.customer, Customer_.address, like(Address_.addressLine, "11 Aleksandr Pushkin St"), and(Address_.city, equal(City_.name, "Tbilisi"), equal(City_.country, Country_.name, “Georgia”) ) ) .findAll(); ``` \ Now, let’s dive into the code and try to build a simple implementation. Our extension will provide the ability to select, update and delete rows. \ ## 2.1 BaseQuery First, we add the `BaseQuery` interface that will contain basic operations for selecting, updating and deleting queries. This interface should have two generic types: `R` as the `Root` type and `Q extends BaseQuery<R, Q>` as the `BaseQuery` implementation itself, which we can use as a return type for Builder pattern methods: ```java public interface BaseQuery<R, Q extends BaseQuery<R, Q>> { } ``` \ Next, we add the first method for the `equal` operation. It will accept `SingularAttribute` as the entity field that we want to compare and the comparing value itself: ```java public interface BaseQuery<R, Q extends BaseQuery<R, Q>> { ... <V> Q equal(SingularAttribute<R, V> attribute, V value); } ``` \ `SingularAttribute` provides two generic types: the first one is the entity type, and the second is the type of the entity’s represented attribute. Therefore, we put `R` as the first generic type, and we add an extra `V` generic type as the second type, equal to the value type. Please note that if we want to provide type safety, the value should have the same data type as the represented attribute. \ Next, we can add the second overloaded implementation of the `equal` filter, that will contain a subsequent parent-child relation to allow you to compare a nested attribute. In this case, we need to add an extra generic type `P` for the in-between relation: ```java public interface BaseQuery<R, Q extends BaseQuery<R, Q>> { ... <P, V> Q equal(SingularAttribute<R, P> attribute1, SingularAttribute<P, V> attribute2, V value); } ``` \ Lastly, we will add the third overloaded `equal` method with an extra `P1` and `P2` generic types to allow you to reach an attribute available after two subsequent parent-child relations: ```java public interface BaseQuery<R, Q extends BaseQuery<R, Q>> { ... <P1, P2, V> Q equal(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, V> attribute3, V value); } ``` \ Now, we are ready to initialize `BaseQuery` using the Criteria API. This class again should have two generic types: the `Root` type and the `BaseQueryImpl` implementation itself, which we can use as a return type for Builder pattern methods: ```java public class BaseQueryImpl<R, Q extends BaseQueryImpl<R, Q>> implements BaseQuery<R, Q> { } ``` \ Before we initialize the equal implementations, we first need to define the collection of predicates. Our query will have nested criteria predicates with postponed initialization. Therefore, we introduce the `QueryPredicate` interface with the following arguments: `CommonAbstractCriteria`, `CriteriaBuilder` and `Path` to allow us to create the necessary predicate: ```java @FunctionalInterface public interface QueryPredicate<R> { Predicate apply(CommonAbstractCriteria criteria, CriteriaBuilder cb, Path<R> root); } ``` \ Next, we introduce a collection of `QueryPredicate` as `BaseQueryImpl` field and a method that will convert this collection to a collection of `javax.persistence.criteria.Predicate`: ```java public class BaseQueryImpl<R, Q extends BaseQueryImpl<R, Q>> implements BaseQuery<R, Q> { protected final Collection<QueryPredicate<R>> predicates; public BaseQueryImpl() { this.predicates = new ArrayList<>(); } protected <T> Predicate[] buildPredicates(CommonAbstractCriteria criteria, Collection<QueryPredicate<T>> predicates, CriteriaBuilder cb, Path<T> root) { return predicates .stream() .map(t -> t.apply(criteria, cb, root)) .toArray(Predicate[]::new); } } ``` \ In addition, we’ll introduce abstract `self()` method that should return `this` instance for each implementation: ```java public abstract class BaseQueryImpl<R, Q extends BaseQueryImpl<R, Q>> implements BaseQuery<R, Q> { ... //subclasses must override this method to return "this" protected abstract Q self(); } ``` \ Now, we are ready to create defined `equal` implementations. Each implementation should retrieve each required `Path` and accumulate an equal predicate in the predicates collection: ```java public abstract class BaseQueryImpl<R, Q extends BaseQueryImpl<R, Q>> implements BaseQuery<R, Q> { ... @Override public <V> Q equal(SingularAttribute<R, V> attribute, V value) { predicates.add((criteria, cb, root) -> cb.equal(root.get(attribute), value)); return self(); } @Override public <P, V> Q equal(SingularAttribute<R, P> attribute1, SingularAttribute<P, V> attribute2, V value) { predicates.add((criteria, cb, root) -> cb.equal(root.get(attribute1).get(attribute2), value)); return self(); } @Override public <P1, P2, V> Q equal(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, V> attribute3, V value) { predicates.add((criteria, cb, root) -> cb.equal(root.get(attribute1).get(attribute2).get(attribute3), value)); return self(); } } ``` \ You can add additional `equal` statements on your own accepting a chain of 3+ subsequent parent-child relations as well as predicates for other operators, like `notEqual`, `like`, `greaterThan`, `lessThan`, `isNull`, etc. \ ## **2.2 SelectQuery** To perform select statements, we will create the `SelectQuery` interface extending the `BaseQuery`: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { } ``` \ This interface will mostly contain the terminating methods that will return the final result from a database. The first terminating method will be `findAll()` returning the list of `R` (Root type): ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { List<R> findAll(); } ``` \ Next, we will provide two overloaded `findAll()` methods to select nested join table: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... <P> List<P> findAll(SingularAttribute<R, P> attribute); <P1, P2> List<P2> findAll(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); } ``` \ The second group of terminating interfaces we implement is `getOne()`, which will return a single result or throw an exception if there is no result found: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... R getOne(); <P> P getOne(SingularAttribute<R, P> attribute); <P1, P2> P2 getOne(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); } ``` \ The third terminating group we implement is `findOne()`, which will return a single result wrapped in the `Optional`: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... Optional<R> findOne(); <P> Optional<P> findOne(SingularAttribute<R, P> attribute); <P1, P2> Optional<P2> findOne(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); } ``` \ The next terminating group we can provide is the `count()` method that will return number of rows matching the query: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... long count(); <P> long count(SingularAttribute<R, P> attribute); <P1, P2> long count(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); } ``` \ Next, let’s add non-terminating interfaces to order the rows. Methods without Order argument will provide the ascending order: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... <P> SelectQuery<R, Q> order(SingularAttribute<R, P> attribute); <P> SelectQuery<R, Q> order(SingularAttribute<R, P> attribute, Order order); <P1, P2> SelectQuery<R, Q> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); <P1, P2> SelectQuery<R, Q> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, Order order); <P1, P2, P3> SelectQuery<R, Q> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3); <P1, P2, P3> SelectQuery<R, Q> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3, Order order); } ``` \ Lastly, if you want to initialize Lazy relations, you can add `fetch()` methods: ```java public interface SelectQuery<R, Q extends SelectQuery<R, Q>> extends BaseQuery<R, Q> { ... <P> SelectQuery<R, Q> fetch(SingularAttribute<R, P> attribute); <P1, P2> SelectQuery<R, Q> fetch(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2); <P1, P2, P3> SelectQuery<R, Q> fetch(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3); } ``` \ Now we have enough interfaces to perform select statements. You can add any other interfaces on your own including pagination, exists and so on. Let’s finish the implementation for the declared methods by creating the `SelectQueryImpl` class: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { } ``` \ This class will contain the following fields: `javax.persistence.EntityManager`, `javax.persistence.criteria.CriteriaBuilder`, `javax.persistence.criteria.CriteriaQuery`, `javax.persistence.criteria.Root` and the List of `javax.persistence.criteria.Order`: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { private final EntityManager em; private final CriteriaBuilder cb; private final CriteriaQuery query; private final Root<R> root; private final List<Order> orderList; } ``` \ Next, let’s declare a constructor. To initialize Criteria fields, we need the `EntityManager` and the root `R` entity type: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... public SelectQueryImpl(EntityManager em, Class<R> type) { this.em = em; this.cb = em.getCriteriaBuilder(); this.query = cb.createQuery(); this.root = query.from(type); this.orderList = new ArrayList<>(); } @Override protected SelectQueryImpl<R> self() { return this; } } ``` \ Before implementing declared terminating and non-terminating interfaces, we will add a private method that will accept `javax.persistence.criteria.Selection` argument and return built `TypedQuery`: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... private <T> TypedQuery<T> buildQuery(Selection<T> selection) { CriteriaQuery<T> resultQuery = query .select(selection) .orderBy(orderList); if (!predicates.isEmpty()) { resultQuery = resultQuery.where(buildPredicates(query, predicates, cb, root)); } return em.createQuery(resultQuery); } } ``` \ This method will build our query by selecting the required table path, providing predicates and orderList. Now we are ready to implement required interfaces. To implement the first group for the `findAll()` interfaces, we just need to pass desired table path to the `buildQuery()` method and call `getResultList()`: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... @Override public List<R> findAll() { return buildQuery(root) .getResultList(); } @Override public <P> List<P> findAll(SingularAttribute<R, P> attribute) { return buildQuery(root.get(attribute)) .getResultList(); } @Override public <P1, P2> List<P2> findAll(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { return buildQuery(root.get(attribute1).get(attribute2)) .getResultList(); } } ``` \ The second implementation is for the `getOne()` interface, which will act the same except for the fact that we should limit the result by one row and call the `getSingleResult()`: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... @Override public R getOne() { return buildQuery(root) .setMaxResults(1) .getSingleResult(); } @Override public <P> P getOne(SingularAttribute<R, P> attribute) { return buildQuery(root.get(attribute)) .setMaxResults(1) .getSingleResult(); } @Override public <P1, P2> P2 getOne(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { return buildQuery(root.get(attribute1).get(attribute2)) .setMaxResults(1) .getSingleResult(); } } ``` \ The next realization for the `findOne()` can be implemented using `getOne()` method with try/catch block: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... @Override public Optional<R> findOne() { try { return Optional.of(getOne()); } catch (NoResultException e) { return Optional.empty(); } } @Override public <P> Optional<P> findOne(SingularAttribute<R, P> attribute) { try { return Optional.of(getOne(attribute)); } catch (NoResultException e) { return Optional.empty(); } } @Override public <P1, P2> Optional<P2> findOne(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { try { return Optional.of(getOne(attribute1, attribute2)); } catch (NoResultException e) { return Optional.empty(); } } } ``` \ The last terminating group is `count()`, which will return count of rows matching the query: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... @Override public long count() { return buildQuery(cb.count(root)) .getSingleResult(); } @Override public <P> long count(SingularAttribute<R, P> attribute) { return buildQuery(cb.count(root.get(attribute))) .getSingleResult(); } @Override public <P1, P2> long count(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { return buildQuery(cb.count(root.get(attribute1).get(attribute2))) .getSingleResult(); } } ``` \ Lastly, we need to implement non-terminating interfaces for the `order()` and `fetch()` methods: ```java public class SelectQueryImpl<R> extends BaseQueryImpl<R, SelectQueryImpl<R>> implements SelectQuery<R, SelectQueryImpl<R>> { ... @Override public <P> SelectQueryImpl<R> order(SingularAttribute<R, P> attribute) { return order(attribute, Order.ASC); } @Override public <P> SelectQueryImpl<R> order(SingularAttribute<R, P> attribute, Order sort) { javax.persistence.criteria.Order order = sort == Order.ASC ? cb.asc(root.get(attribute)) : cb.desc(root.get(attribute)); orderList.add(order); return this; } @Override public <P1, P2> SelectQueryImpl<R> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { return order(attribute1, attribute2, Order.ASC); } @Override public <P1, P2> SelectQueryImpl<R> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, Order sort) { Path<P2> path = root.get(attribute1).get(attribute2); javax.persistence.criteria.Order order = sort == Order.ASC ? cb.asc(path) : cb.desc(path); orderList.add(order); return this; } @Override public <P1, P2, P3> SelectQueryImpl<R> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3) { return order(attribute1, attribute2, attribute3, Order.ASC); } @Override public <P1, P2, P3> SelectQueryImpl<R> order(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3, Order sort) { Path<P3> path = root.get(attribute1).get(attribute2).get(attribute3); javax.persistence.criteria.Order order = sort == Order.ASC ? cb.asc(path) : cb.desc(path); orderList.add(order); return this; } @Override public <P> SelectQueryImpl<R> fetch(SingularAttribute<R, P> attribute) { root.fetch(attribute); return this; } @Override public <P1, P2> SelectQueryImpl<R> fetch(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2) { root.fetch(attribute1).fetch(attribute2); return this; } @Override public <P1, P2, P3> SelectQueryImpl<R> fetch(SingularAttribute<R, P1> attribute1, SingularAttribute<P1, P2> attribute2, SingularAttribute<P2, P3> attribute3) { root.fetch(attribute1).fetch(attribute2).fetch(attribute3); return this; } } ``` \ ## **2.3 UpdateQuery** To perform update statements, we will create the `UpdateQuery` interface extending the `BaseQuery`: ```java public interface UpdateQuery<R, Q extends UpdateQuery<R, Q>> extends BaseQuery<R, Q> { } ``` \ This query will contain only two methods: the first one to set the attributes we want to update and the second one is the terminating method that will return the number of updated rows: ```java public interface UpdateQuery<R, Q extends UpdateQuery<R, Q>> extends BaseQuery<R, Q> { <V> UpdateQuery<R, Q> set(SingularAttribute<R, V> attribute, V value); int execute(); } ``` \ Implementation for the `UpdateQuery` should be quite straightforward except for the fact, now we should use `CriteriaUpdate` instead of `CriteriaQuery`: ```java public class UpdateQueryImpl<R> extends BaseQueryImpl<R, UpdateQueryImpl<R>> implements UpdateQuery<R, UpdateQueryImpl<R>> { private final EntityManager em; private final CriteriaBuilder cb; private final CriteriaUpdate<R> query; private final Root<R> root; public UpdateQueryImpl(EntityManager em, Class<R> type) { this.em = em; this.cb = em.getCriteriaBuilder(); this.query = cb.createCriteriaUpdate(type); this.root = query.from(type); } @Override public <V> UpdateQueryImpl<R> set(SingularAttribute<R, V> attribute, V value) { query.set(attribute, value); return this; } @Override public int execute() { if (!predicates.isEmpty()) { query.where(buildPredicates(query, predicates, cb, root)); } return em.createQuery(query) .executeUpdate(); } @Override protected UpdateQueryImpl<R> self() { return this; } } ``` \ ## **2.4 DeleteQuery** Lastly, to perform delete statements, we will create the `DeleteQuery` interface extending the `BaseQuery`: ```java public interface DeleteQuery<R, Q extends DeleteQuery<R, Q>> extends BaseQuery<R, Q> { } ``` \ `DeleteQuery` will have only one terminating method, returning the number of deleted rows: ```java public interface DeleteQuery<R, Q extends DeleteQuery<R, Q>> extends BaseQuery<R, Q> { int execute(); } ``` \ Implementation for the `DeleteQuery` with the `CriteriaDelete`: ```java public class DeleteQueryImpl<R> extends BaseQueryImpl<R, DeleteQueryImpl<R>> implements DeleteQuery<R, DeleteQueryImpl<R>> { private final EntityManager em; private final CriteriaBuilder cb; private final CriteriaDelete<R> query; private final Root<R> root; public DeleteQueryImpl(EntityManager em, Class<R> type) { this.em = em; this.cb = em.getCriteriaBuilder(); this.query = cb.createCriteriaDelete(type); this.root = query.from(type); } @Override protected DeleteQueryImpl<R> self() { return this; } @Override public int execute() { if (!predicates.isEmpty()) { query.where(buildPredicates(query, predicates, cb, root)); } return em.createQuery(query) .executeUpdate(); } } ``` \ ## **2.5 CriteriaApiHelper** In order to create any of the `BaseQuery` implementations, we should pass an instance of `EntityManager` every time we want to perform a query. To simplify this injection process, we can declare an extra class that will hold the `EntityManager`: ```java public class CriteriaApiHelper { private final EntityManager em; public CriteriaApiHelper(EntityManager em) { this.em = em; } } ``` \ Now we can just initialize methods for `BaseQuery` by creating a suitable implementation for each query type: ```java public class CriteriaApiHelper { … public <T> SelectQueryImpl<T> select(Class<T> type) { return new SelectQueryImpl<>(em, type); } public <T> UpdateQueryImpl<T> update(Class<T> type) { return new UpdateQueryImpl<>(em, type); } public <T> DeleteQueryImpl<T> delete(Class<T> type) { return new DeleteQueryImpl<>(em, type); } } ``` \ # **3 Wrapping up** Now you can perform select, update and delete queries using `CriteriaApiHelper`: ```java List<Order> listOfOrders = criteriaApiHelper.select(Order.class) .equal(Order_.status, OrderStatus.Shipped) .like(Order_.customer, Customer_.address, Address_.addressLine, "11 Aleksandr Pushkin St") .equal(Order_.customer, Customer_.address, Address_.city, City_.name, "Tbilisi") .equal(Order_.customer, Customer_.address, Address_.city, City_.country, Country_.name, “Georgia”) .findAll(); ``` \ In order to see the entities with an underscore at the end, you should include the JPA Static Metamodel Generator library: ``` <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-jpamodelgen</artifactId> <scope>provided</scope> </dependency> ``` \ After that, you need to rebuild your project and mark the `target/generated-sources/annotations` package as the Generated Sources Root:  In the next chapters, we will implement nested expressions providing `or/and` predicates and sub queries.