Prerequisites
Applications are required to provide a CDI exposed EntityManager.
public class EntityManagerProducer { @PersistenceContext private EntityManager em; @Produces public EntityManager expose() { return em; } }
Repositories
Repositories are marked with the @Repository
annotation:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Inherited @InvocationHandlerBinding public @interface Repository { Class<?> forEntity() default Object.class; String methodPrefix() default "findBy"; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Query { /** * Defines the Query to execute. Can be left empty for method expression queries * or when referencing a {@link #named()} query. */ String value() default ""; /** * References a named query. */ String named() default ""; /** * Flag indicating a native SQL query. */ String isNative() default false; /** * Limits the number of results the query returns. */ int max() default 0; /** * Defines a lock mode for the query. */ LockModeType lockMode() default LockModeType.NONE; /** * (Optional) Query properties and hints. May include vendor-specific query hints. */ QueryHint[] hints() default { }; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface QueryParam { String value() default ""; } @Repository(forEntity = Person.class) public interface PersonRepository { // Method expression with ordering List<Person> findByLastNameLikeAndBirthdateAndAddress_ZipOrderByLastNameAsc(String lastName, Date birthdate, String zip); // JPQL Query with indexed parameters @Query("from Person p where p.firstName = ?1 and p.lastName = ?2") Person findByFullName(String first, String last); // JPQL Query with named parameters - @QueryParam optional with Java 8 // Lock mode for update @Query(value = "from Person p where p.age >= :minAge", lockMode = LockModeType.PESSIMISTIC_WRITE) List<Person> findAllAdultsForUpdate(@QueryParam("minAge") int minAge); // Named Query with indexed parameter @Query(named = "Person.findBySSN") Person findBySSN(String ssn); // Native SQL @Query(value = "SELECT * FROM PERSON_TABLE p WHERE p.AGE > ?1", isNative = true) List<Person> findOlderThan(int age); }
Supported in method expressions:
Equal NotEqual Like GreaterThan GreaterThanEquals LessThan LessThanEquals Between IsNull IsNotNull
Limiting Queries
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface FirstResult { } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface MaxResults { } @Repository(forEntity = Person.class) public interface PersonRepository { // Static limit @Query(max = 10) List<Person> findByAge(int age) // Paged queries @Query("from Person p where p.lastName like ?2") List<Person> findByLastNameLike(String last, @FirstResult int from, @MaxResults max); }
Updating Queries
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Modifying { } @Repository(forEntity = Person.class) public interface PersonDao { @Modifying @Query("update Person as p set p.classifyer = ?1 where p.classifyer = ?2") int updateClassifyer(Classifier current, Classifier next); }
Base Types
Base interface to extend, contains most common persistence operations. Example queries are mainly interesting for search screens, although it only supports like and equal queryies. Can be made optional.
public interface EntityRepository<E, PK extends Serializable> { /** * Persist (new entity) or merge the given entity. * @param entity Entity to save. * @return Returns the modified entity. */ E save(E entity); /** * {@link #save(Object)}s the given entity and flushes the persistence context afterwards. * @param entity Entity to save. * @return Returns the modified entity. */ E saveAndFlush(E entity); /** * {@link #save(Object)}s the given entity and flushes the persistence context afterwards, * followed by a refresh (e.g. to load DB trigger modifications). * @param entity Entity to save. * @return Returns the modified entity. */ E saveAndFlushAndRefresh(E entity); /** * Convenience access to {@link javax.persistence.EntityManager#remove(Object)}. * @param entity Entity to remove. */ void remove(E entity); /** * Convenience access to {@link javax.persistence.EntityManager#remove(Object)} * with a following flush. * @param entity Entity to remove. */ void removeAndFlush(E entity); /** * Convenience access to {@link javax.persistence.EntityManager#refresh(Object)}. * @param entity Entity to refresh. */ void refresh(E entity); /** * Convenience access to {@link javax.persistence.EntityManager#flush()}. */ void flush(); /** * Entity lookup by primary key. Convenicence method around * {@link javax.persistence.EntityManager#find(Class, Object)}. * @param primaryKey DB primary key. * @return Entity identified by primary or null if it does not exist. */ E findBy(PK primaryKey); /** * Lookup all existing entities of entity class {@code <E>}. * @return List of entities, empty if none found. */ List<E> findAll(); /** * Lookup a range of existing entities of entity class {@code <E>} with support for pagination. * @param start The starting position. * @param max The maximum number of results to return * @return List of entities, empty if none found. */ List<E> findAll(int start, int max); /** * Query by example - for a given object and a specific set of properties. * @param example Sample entity. Query all like. * @param attributes Which attributes to consider for the query. * @return List of entities matching the example, or empty if none found. */ List<E> findBy(E example, SingularAttribute<E, ?>... attributes); /** * Query by example - for a given object and a specific set of properties with support for pagination. * @param example Sample entity. Query all like. * @param start The starting position. * @param max The maximum number of results to return * @param attributes Which attributes to consider for the query. * @return List of entities matching the example, or empty if none found. */ List<E> findBy(E example, int start, int max, SingularAttribute<E, ?>... attributes); /** * Query by example - for a given object and a specific set of properties using a like operator for Strings. * @param example Sample entity. Query all like. * @param attributes Which attributes to consider for the query. * @return List of entities matching the example, or empty if none found. */ List<E> findByLike(E example, SingularAttribute<E, ?>... attributes); /** * Query by example - for a given object and a specific set of properties * using a like operator for Strings with support for pagination. * @param example Sample entity. Query all like. * @param start The starting position. * @param max The maximum number of results to return * @param attributes Which attributes to consider for the query. * @return List of entities matching the example, or empty if none found. */ List<E> findByLike(E example, int start, int max, SingularAttribute<E, ?>... attributes); /** * Count all existing entities of entity class {@code <E>}. * @return Counter. */ Long count(); /** * Count existing entities of entity class {@code <E>} * with for a given object and a specific set of properties.. * @param example Sample entity. Query all like. * @param attributes Which attributes to consider for the query. * * @return Counter. */ Long count(E example, SingularAttribute<E, ?>... attributes); /** * Count existing entities of entity class using the like operator for String attributes {@code <E>} * with for a given object and a specific set of properties.. * @param example Sample entity. Query all like. * @param attributes Which attributes to consider for the query. * * @return Counter. */ Long countLike(E example, SingularAttribute<E, ?>... attributes); } @Repository public abstract class AbstractEntityRepository<E, PK extends Serializable> implements EntityRepository<E, PK> { /** * Utility method to get hold of the entity manager for this Repository. * * @return Entity manager instance. */ protected abstract EntityManager getEntityManager(); /** * Utility method to create a criteria query. * @return Criteria query */ protected abstract CriteriaQuery<E> getCriteriaQuery(); /** * Get the entity class this Repository is related to. * @return Repository entity class. */ protected abstract Class<E> getEntityClass(); } // @Repository inherited // Entity is extracted from type parameters public abstract class PersonRepository extends AbstractEntityRepository<Person, Long> { // Concrete query sample with some logic // Can also be done with the Criteria API public List<Person> findByFullNameBirtdateZip(String first, String last, Date bdate, String zip) { String jpql = "from Person p where "; if (!isEmpty(last)) { jpql += "p.lastName = :last"; } ... return getEntityManager().createQuery(jpql) ... } }
Annotation inheritance
// @Repository inherited public abstract class PersonRepository extends AbstractEntityRepository<Person, Long> { ... } @Repository // caution, NOT inherited public interface PersonRepository extends EntityRepository<Person, Long> { ... } @Repository // caution, NOT inherited public abstract class PersonRepository implements EntityRepository<Person, Long> { ... }
Pagination, Sorting and Dynamic Query Options
/** * Can be used as query result type, which will not execute the query immediately. * Allows some post processing like defining query ordering. * * @param <E> Entity type */ public interface QueryResult<E> { /** * Sort the query result ascending by the given entity singular attribute. * This is the typesafe version, alternatively a {@link #orderAsc(String)} * String can be used. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ <X> QueryResult<E> orderAsc(SingularAttribute<E, X> attribute); /** * Sort the query result ascending by the given entity attribute. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ QueryResult<E> orderAsc(String attribute); /** * Sort the query result descending by the given entity singular attribute. * This is the typesafe version, alternatively a {@link #orderDesc(String)} * String can be used. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ <X> QueryResult<E> orderDesc(SingularAttribute<E, X> attribute); /** * Sort the query result descending by the given entity attribute. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ QueryResult<E> orderDesc(String attribute); /** * Revert an existing order attribute sort direction. Defaults to ascending * order if the sort attribute was not used before. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ <X> QueryResult<E> changeOrder(SingularAttribute<E, X> attribute); /** * Remove any ordering from the query result object. * @return Fluent API: the result instance. */ QueryResult<E> clearOrder(); /** * Revert an existing order attribute sort direction. Defaults to ascending * order if the sort attribute was not used before. * * @param attribute Sort attribute. * @return Fluent API: the result instance. */ QueryResult<E> changeOrder(String attribute); /** * Limit the number of results returned by the query. * * @param max Max number of results. * @return Fluent API: the result instance. */ QueryResult<E> maxResults(int max); /** * Pagination: Set the result start position. 0-based (as the JPA Query API). * * @param first Result start position. * @return Fluent API: the result instance. */ QueryResult<E> firstResult(int first); /** * Sets the query lock mode. * * @param lockMode Query lock mode to use in the query. * @return Fluent API: the result instance. */ QueryResult<E> lockMode(LockModeType lockMode); /** * Apply a query hint to the query to execute. * * @param hint Hint name. * @param value Hint value. * @return Fluent API: the result instance. */ QueryResult<E> hint(String hint, Object value); /** * Fetch the result set. * * @return List of entities retrieved by the query. */ List<E> getResultList(); /** * Fetch a single result entity. * * @return Entity retrieved by the query. */ E getSingleResult(); /** * Count the result set. * @return Result count. */ long count(); /** * Turns the query into a paged query with the given page size. * Defaults to 10 if paging methods are called without this. * * @param pageSize Page size for further queries. * @return Fluent API: the result instance. */ QueryResult<E> withPageSize(int pageSize); /** * Move the page cursor to a specific page. First page is page 0. * * @param page Page to move to for the next query. * @return Fluent API: the result instance. */ QueryResult<E> toPage(int page); /** * Move to the next page. * * @return Fluent API: the result instance. */ QueryResult<E> nextPage(); /** * Move to the previous page. * * @return Fluent API: the result instance. */ QueryResult<E> previousPage(); /** * Count the number of pages. * @return Page count. */ int countPages(); /** * Return the actual page. * @return Page position. */ int getCurrentPage(); /** * Return the actual page size. * @return Page size. */ int getPageSize(); }
Counting queries will have to modify the JPQL. For named queries this needs access to the underlying provider classes.
Usage:
@Repository public interface PersonRepository extends EntityRepository<Person, Long> { QueryResult<Person> findByAge(int age); QueryResult<Person> findBySSN(String ssn); } // Sorting personRepository.findByAge(age) .sortAsc(Person_.lastName) .getResultList(); QueryResult<Person> result = personRepository.findByAge(age) .sortDesc("lastName"); result.changeOrder(Person_.lastName) .getResultList(); // Dynamic Query Options personRepository.findBySSN(ssn) .lockMode(LockModeType.WRITE) .hint("org.hibernate.timeout", Integer.valueOf(10)) .getSingleResult(); // Count long total = personRepository.findByAge(age).count(); // Pagination // Query API style QueryResult<Person> paged = personRepository.findByAge(age) .maxResults(10) .firstResult(50); // or paging style QueryResult<Person> paged = personRepository.findByAge(age) .withPageSize(10) // equivalent to maxResults .toPage(5); int totalPages = paged.countPages();
Repository Extensions
Used to add custom new behavior to Repositories:
import com.mysema.query.jpa.impl.JPAQuery; public interface QueryDslSupport { JPAQuery jpaQuery(); } public class QueryDslRepositoryExtension implements QueryDslSupport, DelegateQueryHandler { @Inject private QueryInvocationContext context; @Override public JPAQuery jpaQuery() { return new JPAQuery(context.getEntityManager()); } } @Repository(forEntity = Person.class) public interface PersonRepository extends QueryDslSupport { }
API:
public interface DelegateQueryHandler { } /** * Expose the current query invocation to extensions. */ public interface QueryInvocationContext { /** * Entity Manager used for the query. */ EntityManager getEntityManager(); /** * The class of the Entity related to the invoked Repository. */ Class<?> getEntityClass(); /** * Given the object parameter is an entity, checks if the entity is * persisted or not. * @param entity Entity object, non nullable. * @return true if the entity is not persisted, false otherwise and if no entity. */ boolean isNew(Object entity); }
Multiple EntityManagers
public interface EntityManagerResolver { EntityManager resolveEntityManager(); } @Target({ TYPE }) @Retention(RUNTIME) @Documented public @interface EntityManagerConfig { /** * References the type which provides the EntityManager for a specific repository. * Must be resolvable over the BeanManager. */ Class<? extends EntityManagerResolver> entityManagerResolver() default EntityManagerResolver.class; /** * Set the flush mode for the repository EntityManager. */ FlushModeType flushMode() default FlushModeType.AUTO; }
Usage:
@Repository @EntityManagerConfig(entityManagerResolver = CrmEntityManagerResolver.class, flushMode = FlushModeType.COMMIT) public interface PersonRepository extends EntityRepository<Person, Long> { ... } public class CrmEntityManagerResolver implements EntityManagerResolver { @Inject @CustomerData // Qualifier - assumes producer is around... private EntityManager em; @Override public EntityManager resolveEntityManager() { return em; } }
It's probably worth noting that the same restrictions for annotation inheritance apply here as for @Repository (interface annotations don't inherit on classes).
Auditing
API:
/** * Marks a property which should be updated with a timestamp when the entity gets persisted. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface CreatedOn { } /** * Marks a property which should be updated with a timestamp when the entity gets updated. * By settings {@link #onCreate()} to {@code true}, the property gets also set when * the entity is persisted. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface ModifiedOn { boolean onCreate() default false; } /** * Marks a property which should keep track on the last changing user. */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD, ElementType.METHOD }) public @interface ModifiedBy { } /** * Identifies the current user responsible for entity creation or modification. */ @Qualifier @Target({ TYPE, METHOD, PARAMETER, FIELD }) @Retention(RUNTIME) @Documented public @interface CurrentUser { }
Usage:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd" version="2.0"> <persistence-unit-metadata> <persistence-unit-defaults> <entity-listeners> <entity-listener class="org.apache.deltaspike.data.impl.audit.AuditEntityListener" /> </entity-listeners> </persistence-unit-defaults> </persistence-unit-metadata> </entity-mappings>
@Entity public class AuditedEntity { @Temporal(TemporalType.TIMESTAMP) @CreatedOn private Calendar created; @ModifiedBy private String changer; @Temporal(TemporalType.TIME) @ModifiedOn(onCreate = true) private Date modified; ... } @Produces @CurrentUser public String who() { return currentUser.username; }
Criteria API simplifications
Reduces boilerplate for common cases around the criteria API without giving up on typesafety. There's also only support for metamodel classes, skipping any bloating string attribute based API calls.
Use case first, API makes probably more sense then:
@Repository(forEntity = Person.class) public abstract class PersonDao implements CriteriaSupport { // AND criteria with sorting public List<Person> findAdultFamilyMembers(String name, Integer minAge) { return criteria() .like(Person_.name, "%" + name + "%") .gtOrEq(Person_.age, minAge) .eq(Person_.validated, Boolean.TRUE) .orderDesc(Person_.age) .getResultList(); } // Joins public List<Person> findByCompanyName(String companyName) { return criteria() .join(Person_.company, where(Company.class) .eq(Company_.name, companyName) ) .eq(Person_.validated, Boolean.TRUE) .getResultList(); } public Person findBySSN(String ssn) { return criteria() .fetch(Person_.familyMembers) .eq(Person_.ssn, ssn) .distinct() .getSingleResult(); } // OR public List<Person> findAdults() { return criteria() .or( criteria(). .gtOrEq(Person_.age, 18) .eq(Person_.origin, Country.SWITZERLAND), criteria(). .gtOrEq(Person_.age, 21) .eq(Person_.origin, Country.USA) ) .getResultList(); } // Selections public Statistics ageStatsFor(Segment segment) { return criteria() .select(Statistics.class, avg(Person_.age), min(Person_.age), max(Person_.age)) .eq(Person_.segment, segment) .getSingleResult(); } public List<Object[]> personViewForFamily(String name) { return criteria() .select(upper(Person_.name), attribute(Person_.age), substring(Person_.firstname, 1)) .like(Person_.name, name) .getResultList(); } }
API:
/** * Criteria API utilities, base class. * * @param <C> Entity type. * @param <R> Result type. */ public interface Criteria<C, R> { /** * Executes the query and returns the result list. * @return List of entities matching the query. */ List<R> getResultList(); /** * Executes the query which has a single result. * @return Entity matching the search query. */ R getSingleResult(); /** * Creates a JPA query object to be executed. * @return A {@link TypedQuery} object ready to return results. */ TypedQuery<R> createQuery(); /** * Boolean OR with another Criteria. * @param criteria The right side of the boolean OR. * @return Fluent API: Criteria instance. */ Criteria<C, R> or(Criteria<C, R>... criteria); /** * Boolean OR with another Criteria. * @param criteria The right side of the boolean OR. * @return Fluent API: Criteria instance. */ Criteria<C, R> or(Collection<Criteria<C, R>> criteria); /** * Join an attribute with another Criteria. * @param att The attribute to join. * @param criteria The join criteria. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> join(SingularAttribute<? super C, P> att, Criteria<P, P> criteria); /** * Join a collection attribute with another Criteria. * @param att The attribute to join. * @param criteria The join criteria. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> join(ListAttribute<? super C, P> att, Criteria<P, P> criteria); /** * Join a collection attribute with another Criteria. * @param att The attribute to join. * @param criteria The join criteria. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> join(CollectionAttribute<? super C, P> att, Criteria<P, P> criteria); /** * Join a collection attribute with another Criteria. * @param att The attribute to join. * @param criteria The join criteria. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> join(SetAttribute<? super C, P> att, Criteria<P, P> criteria); /** * Join a collection attribute with another Criteria. * @param att The attribute to join. * @param criteria The join criteria. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> join(MapAttribute<? super C, E, P> att, Criteria<P, P> criteria); /** * Fetch join an attribute. * @param att The attribute to fetch. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> fetch(SingularAttribute<? super C, P> att); /** * Fetch join an attribute. * @param att The attribute to fetch. * @param joinType The JoinType to use. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> fetch(SingularAttribute<? super C, P> att, JoinType joinType); /** * Fetch join an attribute. * @param att The attribute to fetch. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> fetch(PluralAttribute<? super C, P, E> att); /** * Fetch join an attribute. * @param att The attribute to fetch. * @param joinType The JoinType to use. * @return Fluent API: Criteria instance. */ <P, E> Criteria<C, R> fetch(PluralAttribute<? super C, P, E> att, JoinType joinType); /** * Apply sorting by an attribute, ascending direction. * @param att The attribute to order for. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> orderAsc(SingularAttribute<? super C, P> att); /** * Apply sorting by an attribute, descending direction. * @param att The attribute to order for. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> orderDesc(SingularAttribute<? super C, P> att); /** * Create a select query. * @param resultClass The query result class. * @param selection List of selects (attributes, scalars...) * @return Fluent API: Criteria instance. */ <N> Criteria<C, N> select(Class<N> resultClass, QuerySelection<? super C, ?>... selection); /** * Create a select query. * @param selection List of selects (attributes, scalars...) * @return Fluent API: Criteria instance. */ Criteria<C, Object[]> select(QuerySelection<? super C, ?>... selection); /** * Apply a distinct on the query. * @return Fluent API: Criteria instance. */ Criteria<C, R> distinct(); /** * Equals predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> eq(SingularAttribute<? super C, P> att, P value); /** * Not Equals predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> notEq(SingularAttribute<? super C, P> att, P value); /** * Like predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> like(SingularAttribute<? super C, String> att, String value); /** * Not like predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> notLike(SingularAttribute<? super C, String> att, String value); /** * Less than predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P extends Number> Criteria<C, R> lt(SingularAttribute<? super C, P> att, P value); /** * Less than or equals predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P extends Comparable<? super P>> Criteria<C, R> ltOrEq(SingularAttribute<? super C, P> att, P value); /** * Greater than predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P extends Number> Criteria<C, R> gt(SingularAttribute<? super C, P> att, P value); /** * Greater than or equals predicate. * @param att The attribute to compare with. * @param value The comparison value. * @return Fluent API: Criteria instance. */ <P extends Comparable<? super P>> Criteria<C, R> gtOrEq(SingularAttribute<? super C, P> att, P value); /** * Between predicate. * @param att The attribute to compare with. * @param lower The lower bound comparison value. * @param upper The upper bound comparison value. * @return Fluent API: Criteria instance. */ <P extends Comparable<? super P>> Criteria<C, R> between(SingularAttribute<? super C, P> att, P lower, P upper); /** * IsNull predicate. * @param att The null attribute. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> isNull(SingularAttribute<? super C, P> att); /** * NotNull predicate. * @param att The non-null attribute. * @return Fluent API: Criteria instance. */ <P> Criteria<C, R> notNull(SingularAttribute<? super C, P> att); /** * Empty predicate. * @param att The collection attribute to check for emptyness. * @return Fluent API: Criteria instance. */ <P extends Collection<?>> Criteria<C, R> empty(SingularAttribute<? super C, P> att); /** * Not empty predicate. * @param att The collection attribute to check for non-emptyness. * @return Fluent API: Criteria instance. */ <P extends Collection<?>> Criteria<C, R> notEmpty(SingularAttribute<? super C, P> att); /** * In predicte. * @param att The attribute to check for. * @param values The values for the in predicate. * @return */ <P> Criteria<C, R> in(SingularAttribute<? super C, P> att, P... values); /** * Return the list of predicates applicable for this Criteria instance. * @param builder A CriteriaBuilder used to instantiate the Predicates. * @param path Current path. * @return List of predicates applicable to this Criteria. */ List<Predicate> predicates(CriteriaBuilder builder, Path<C> path); } /** * From an entity criteria query to a selection query. */ public interface QuerySelection<P, X> { /** * Convert the instance to a criteria selection. * @param query The current criteria query. * @param builder The query builder used to instantiate the selection. * @param path Current path. * @return Criteria API selection instance corresponding to the * QuerySelection implementation. */ <R> Selection<X> toSelection(CriteriaQuery<R> query, CriteriaBuilder builder, Path<? extends P> path); } /** * Entry type to create criteria queries. * Provides also helper methods for joins and selections. */ public interface CriteriaSupport<E> { /** * Create a {@link Criteria} instance. * @return Criteria instance related to the Repository entity class. */ Criteria<E, E> criteria(); /** * Create a {@link Criteria} instance. * @param <T> Type related to the current criteria class. * @param clazz Class other than the current entity class. * @return Criteria instance related to a join type of the current entity class. */ <T> Criteria<T, T> where(Class<T> clazz); /** * Create a {@link Criteria} instance with a join type. * @param <T> Type related to the current criteria class. * @param clazz Class other than the current entity class. * @param joinType Join type to apply. * @return Criteria instance related to a join type of the current entity class. */ <T> Criteria<T, T> where(Class<T> clazz, JoinType joinType); /** * Create a query selection for an Entity attribute. * @param attribute Attribute to show up in the result selection * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <X> QuerySelection<E, X> attribute(SingularAttribute<E, X> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#abs(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> abs(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#avg(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> avg(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#count(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> count(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#max(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> max(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#min(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> min(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#neg(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> neg(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#sum(javax.persistence.criteria.Expression)} * over an attribute. * @param attribute Attribute to use in the aggregate. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ <N extends Number> QuerySelection<E, N> sum(SingularAttribute<E, N> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#mod(javax.persistence.criteria.Expression, Integer)} * for an attribute. * @param attribute Attribute to use in the aggregate. * @param modulo Modulo what. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, Integer> modulo(SingularAttribute<E, Integer> attribute, Integer modulo); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#upper(javax.persistence.criteria.Expression)} * over a String attribute. * @param attribute Attribute to uppercase. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, String> upper(SingularAttribute<E, String> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#lower(javax.persistence.criteria.Expression)} * over a String attribute. * @param attribute Attribute to lowercase. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, String> lower(SingularAttribute<E, String> attribute); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#substring(javax.persistence.criteria.Expression, int)} * over a String attribute. * @param attribute Attribute to create a substring from. * @param from Substring start. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from); /** * Create a query selection for the * {@link javax.persistence.criteria.CriteriaBuilder#substring(javax.persistence.criteria.Expression, int, int)} * over a String attribute. * @param attribute Attribute to create a substring from. * @param from Substring start. * @param length Substring length. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, String> substring(SingularAttribute<E, String> attribute, int from, int length); /** * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentDate()}. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, Date> currDate(); /** * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentTime()}. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, Time> currTime(); /** * Create a query selection for the {@link javax.persistence.criteria.CriteriaBuilder#currentTimestamp()}. * @return {@link QuerySelection} part of a {@link Criteria#select(Class, QuerySelection...)} call. */ QuerySelection<E, Timestamp> currTStamp(); }