com.avaje.ebean.Query Maven / Gradle / Ivy
package com.avaje.ebean;
import org.jetbrains.annotations.Nullable;
import javax.persistence.NonUniqueResultException;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Object relational query for finding a List, Set, Map or single entity bean.
*
* Example: Create the query using the API.
*
*
* {@code
*
* List orderList =
* ebeanServer.find(Order.class)
* .fetch("customer")
* .fetch("details")
* .where()
* .like("customer.name","rob%")
* .gt("orderDate",lastWeek)
* .orderBy("customer.id, id desc")
* .setMaxRows(50)
* .findList();
*
* ...
* }
*
*
* Example: The same query using the query language
*
*
* {@code
*
* String oql =
* " find order "
* +" fetch customer "
* +" fetch details "
* +" where customer.name like :custName and orderDate > :minOrderDate "
* +" order by customer.id, id desc "
* +" limit 50 ";
*
* Query query = ebeanServer.createQuery(Order.class, oql);
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List orderList = query.findList();
* ...
* }
*
*
* Example: Using a named query called "with.cust.and.details"
*
*
* {@code
*
* Query query = ebeanServer.createNamedQuery(Order.class,"with.cust.and.details");
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List orderList = query.findList();
* ...
* }
*
* AutoTune
*
* Ebean has built in support for "AutoTune". This is a mechanism where a query
* can be automatically tuned based on profiling information that is collected.
*
*
* This is effectively the same as automatically using select() and fetch() to
* build a query that will fetch all the data required by the application and no
* more.
*
*
* It is expected that AutoTune will be the default approach for many queries
* in a system. It is possibly not as useful where the result of a query is sent
* to a remote client or where there is some requirement for "Read Consistency"
* guarantees.
*
*
* Query Language
*
* Partial Objects
*
*
* The find and fetch clauses support specifying a list of
* properties to fetch. This results in objects that are "partially populated".
* If you try to get a property that was not populated a "lazy loading" query
* will automatically fire and load the rest of the properties of the bean (This
* is very similar behaviour as a reference object being "lazy loaded").
*
*
* Partial objects can be saved just like fully populated objects. If you do
* this you should remember to include the "Version" property in the
* initial fetch. If you do not include a version property then optimistic
* concurrency checking will occur but only include the fetched properties.
* Refer to "ALL Properties/Columns" mode of Optimistic Concurrency checking.
*
*
* {@code
* [ find {bean type} [ ( * | {fetch properties} ) ] ]
* [ fetch {associated bean} [ ( * | {fetch properties} ) ] ]
* [ where {predicates} ]
* [ order by {order by properties} ]
* [ limit {max rows} [ offset {first row} ] ]
* }
*
*
* FIND {bean type} [ ( * | {fetch properties} ) ]
*
*
* With the find you specify the type of beans to fetch. You can optionally
* specify a list of properties to fetch. If you do not specify a list of
* properties ALL the properties for those beans are fetched.
*
*
* In object graph terms the find clause specifies the type of bean at
* the root level and the fetch clauses specify the paths of the object
* graph to populate.
*
*
* FETCH {associated property} [ ( * | {fetch
* properties} ) ]
*
*
* With the fetch you specify the associated property to fetch and populate. The
* associated property is a OneToOnem, ManyToOne, OneToMany or ManyToMany
* property. When the query is executed Ebean will fetch the associated data.
*
*
* For fetch of a path we can optionally specify a list of properties to fetch.
* If you do not specify a list of properties ALL the properties for that bean
* type are fetched.
*
*
* WHERE {list of predicates}
*
*
* The list of predicates which are joined by AND OR NOT ( and ). They can
* include named (or positioned) bind parameters. These parameters will need to
* be bound by {@link Query#setParameter(String, Object)}.
*
*
* ORDER BY {order by properties}
*
*
* The list of properties to order the result. You can include ASC (ascending)
* and DESC (descending) in the order by clause.
*
*
* LIMIT {max rows} [ OFFSET {first row} ]
*
*
* The limit offset specifies the max rows and first row to fetch. The offset is
* optional.
*
* Examples of Ebean's Query Language
*
* Find orders fetching all its properties
*
*
* {@code
* find order
* }
*
*
* Find orders fetching all its properties
*
*
* {@code
* find order (*)
* }
*
*
* Find orders fetching its id, shipDate and status properties. Note that the id
* property is always fetched even if it is not included in the list of fetch
* properties.
*
*
* {@code
* find order (shipDate, status)
* }
*
*
* Find orders with a named bind variable (that will need to be bound via
* {@link Query#setParameter(String, Object)}).
*
*
* {@code
* find order
* where customer.name like :custLike
* }
*
*
* Find orders and also fetch the customer with a named bind parameter. This
* will fetch and populate both the order and customer objects.
*
*
* {@code
* find order
* fetch customer
* where customer.id = :custId
* }
*
*
* Find orders and also fetch the customer, customer shippingAddress, order
* details and related product. Note that customer and product objects will be
* "Partial Objects" with only some of their properties populated. The customer
* objects will have their id, name and shipping address populated. The product
* objects (associated with each order detail) will have their id, sku and name
* populated.
*
*
* {@code
* find order
* fetch customer (name)
* fetch customer.shippingAddress
* fetch details
* fetch details.product (sku, name)
* }
*
* Early parsing of the Query
*
* When you get a Query object from a named query, the query statement has
* already been parsed. You can then add to that query (add fetch paths, add to
* the where clause) or override some of its settings (override the order by
* clause, first rows, max rows).
*
*
* The thought is that you can use named queries as a 'starting point' and then
* modify the query to suit specific needs.
*
* Building the Where clause
*
* You can add to the where clause using Expression objects or a simple String.
* Note that the ExpressionList has methods to add most of the common
* expressions that you will need.
*
* - where(String addToWhereClause)
* - where().add(Expression expression)
* - where().eq(propertyName, value).like(propertyName , value)...
*
*
*
* The full WHERE clause is constructed by appending together
*
original query where clause (Named query or query.setQuery(String oql))
* clauses added via query.where(String addToWhereClause)
* clauses added by Expression objects
*
*
* The above is the order that these are clauses are appended to give the full
* WHERE clause.
*
* Design Goal
*
* This query language is NOT designed to be a replacement for SQL. It is
* designed to be a simple way to describe the "Object Graph" you want Ebean to
* build for you. Each find/fetch represents a node in that "Object Graph" which
* makes it easy to define for each node which properties you want to fetch.
*
*
* Once you hit the limits of this language such as wanting aggregate functions
* (sum, average, min etc) or recursive queries etc you use SQL. Ebean's goal is
* to make it as easy as possible to use your own SQL to populate entity beans.
* Refer to {@link RawSql} .
*
*
* @param
* the type of Entity bean this query will fetch.
*/
public interface Query {
/**
* Return the RawSql that was set to use for this query.
*/
RawSql getRawSql();
/**
* Set RawSql to use for this query.
*/
Query setRawSql(RawSql rawSql);
/**
* Perform an 'As of' query using history tables to return the object graph
* as of a time in the past.
*
* To perform this query the DB must have underlying history tables.
*
*
* @param asOf the date time in the past at which you want to view the data
*/
Query asOf(Timestamp asOf);
/**
* Execute the query against the draft set of tables.
*/
Query asDraft();
/**
* Cancel the query execution if supported by the underlying database and
* driver.
*
* This must be called from a different thread to the query executor.
*
*/
void cancel();
/**
* Return a copy of the query.
*
* This is so that you can use a Query as a "prototype" for creating other
* query instances. You could create a Query with various where expressions
* and use that as a "prototype" - using this copy() method to create a new
* instance that you can then add other expressions then execute.
*
*/
Query copy();
/**
* Specify the PersistenceContextScope to use for this query.
*
* When this is not set the 'default' configured on {@link com.avaje.ebean.config.ServerConfig#setPersistenceContextScope(PersistenceContextScope)}
* is used - this value defaults to {@link com.avaje.ebean.PersistenceContextScope#TRANSACTION}.
*
* Note that the same persistence Context is used for subsequent lazy loading and query join queries.
*
* Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for
* queries executed as #findIterate, #findEach, #findEachWhile.
*
* @param scope The scope to use for this query and subsequent lazy loading.
*/
Query setPersistenceContextScope(PersistenceContextScope scope);
/**
* Return the ExpressionFactory used by this query.
*/
ExpressionFactory getExpressionFactory();
/**
* Returns true if this query was tuned by autoTune.
*/
boolean isAutoTuned();
/**
* Explicitly specify whether to use AutoTune for this query.
*
* If you do not call this method on a query the "Implicit AutoTune mode" is
* used to determine if AutoTune should be used for a given query.
*
*
* AutoTune can add additional fetch paths to the query and specify which
* properties are included for each path. If you have explicitly defined some
* fetch paths AutoTune will not remove them.
*
*/
Query setAutoTune(boolean autoTune);
/**
* Set the default lazy loading batch size to use.
*
* When lazy loading is invoked on beans loaded by this query then this sets the
* batch size used to load those beans.
*
* @param lazyLoadBatchSize the number of beans to lazy load in a single batch
*/
Query setLazyLoadBatchSize(int lazyLoadBatchSize);
/**
* Execute the query including soft deleted rows.
*
* This means that Ebean will not add any predicates to the query for filtering out
* soft deleted rows. You can still add your own predicates for the deleted properties
* and effectively you have full control over the query to include or exclude soft deleted
* rows as needed for a given use case.
*
*/
Query setIncludeSoftDeletes();
/**
* Disable read auditing for this query.
*
* This is intended to be used when the query is not a user initiated query and instead
* part of the internal processing in an application to load a cache or document store etc.
* In these cases we don't want the query to be part of read auditing.
*
*/
Query setDisableReadAuditing();
/**
* Explicitly set a comma delimited list of the properties to fetch on the
* 'main' root level entity bean (aka partial object). Note that '*' means all
* properties.
*
* You use {@link #fetch(String, String)} to specify specific properties to fetch
* on other non-root level paths of the object graph.
*
*
* {@code
*
* List customers =
* ebeanServer.find(Customer.class)
* // Only fetch the customer id, name and status.
* // This is described as a "Partial Object"
* .select("name, status")
* .where.ilike("name", "rob%")
* .findList();
*
* }
*
* @param fetchProperties
* the properties to fetch for this bean (* = all properties).
*/
Query select(String fetchProperties);
/**
* Specify a path to fetch with its specific properties to include
* (aka partial object).
*
* When you specify a join this means that property (associated bean(s)) will
* be fetched and populated. If you specify "*" then all the properties of the
* associated bean will be fetched and populated. You can specify a comma
* delimited list of the properties of that associated bean which means that
* only those properties are fetched and populated resulting in a
* "Partial Object" - a bean that only has some of its properties populated.
*
*
* {@code
*
* // query orders...
* List orders =
* ebeanserver.find(Order.class)
* // fetch the customer...
* // ... getting the customers name and phone number
* .fetch("customer", "name, phoneNumber")
*
* // ... also fetch the customers billing address (* = all properties)
* .fetch("customer.billingAddress", "*")
* .findList();
* }
*
*
* If columns is null or "*" then all columns/properties for that path are
* fetched.
*
*
* {@code
*
* // fetch customers (their id, name and status)
* List customers =
* ebeanServer.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email")
* .findList();
*
* }
*
* @param path
* the path of an associated (1-1,1-M,M-1,M-M) bean.
* @param fetchProperties
* properties of the associated bean that you want to include in the
* fetch (* means all properties, null also means all properties).
*/
Query fetch(String path, String fetchProperties);
/**
* Additionally specify a FetchConfig to use a separate query or lazy loading
* to load this path.
*
* {@code
*
* // fetch customers (their id, name and status)
* List customers =
* ebeanServer.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10))
* .findList();
*
* }
*/
Query fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig);
/**
* Specify a path to load including all its properties.
*
* The same as {@link #fetch(String, String)} with the fetchProperties as "*".
*
* {@code
*
* // fetch customers (their id, name and status)
* List customers =
* ebeanServer.find(Customer.class)
* // eager fetch the contacts
* .fetch("contacts")
* .findList();
*
* }
*
* @param path
* the property of an associated (1-1,1-M,M-1,M-M) bean.
*/
Query fetch(String path);
/**
* Additionally specify a JoinConfig to specify a "query join" and or define
* the lazy loading query.
*
*
* {@code
*
* // fetch customers (their id, name and status)
* List customers =
* ebeanServer.find(Customer.class)
* // lazy fetch contacts with a batch size of 100
* .fetch("contacts", new FetchConfig().lazy(100))
* .findList();
*
* }
*/
Query fetch(String path, FetchConfig fetchConfig);
/**
* Apply the path properties replacing the select and fetch clauses.
*
* This is typically used when the FetchPath is applied to both the query and the JSON output.
*
*/
Query apply(FetchPath fetchPath);
/**
* Execute the query returning the list of Id's.
*
* This query will execute against the EbeanServer that was used to create it.
*
*
* @see EbeanServer#findIds(Query, Transaction)
*/
List