com.avaje.ebean.Query Maven / Gradle / Ivy
/**
* Copyright (C) 2009 Authors
*
* This file is part of Ebean.
*
* Ebean is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* Ebean is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package com.avaje.ebean;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.config.ServerConfig;
/**
* Object relational query for finding a List, Set, Map or single entity bean.
*
* Example: Create the query using the API.
*
*
*
* List<Order> orderList =
* Ebean.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
*
*
*
* 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<Order> query = Ebean.createQuery(Order.class, oql);
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List<Order> orderList = query.findList();
* ...
*
*
*
* Example: Using a named query called "with.cust.and.details"
*
*
*
* Query<Order> query = Ebean.createNamedQuery(Order.class,"with.cust.and.details");
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List<Order> orderList = query.findList();
* ...
*
*
* Autofetch
*
* Ebean has built in support for "Autofetch". 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 Autofetch 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.
*
*
*
* [ 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
*
*
*
* find order
*
*
*
* Find orders fetching all its properties
*
*
*
* 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.
*
*
*
* find order (shipDate, status)
*
*
*
* Find orders with a named bind variable (that will need to be bound via
* {@link Query#setParameter(String, Object)}).
*
*
*
* 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.
*
*
*
* 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.
*
*
*
* 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 extends Serializable {
/**
* How this query should use (or not) the Lucene Index if one is defined for
* the bean type.
*/
public enum UseIndex {
NO, DEFAULT, YES_IDS, YES_OBJECTS
}
/**
* The type of query result.
*/
public enum Type {
/**
* Find by Id or unique returning a single bean.
*/
BEAN,
/**
* Find returning a List.
*/
LIST,
/**
* Find returning a Set.
*/
SET,
/**
* Find returning a Map.
*/
MAP,
/**
* Find the Id's.
*/
ID_LIST,
/**
* Find rowCount.
*/
ROWCOUNT,
/**
* A subquery used as part of a where clause.
*/
SUBQUERY
}
/**
* Explicitly specify how this query should use a Lucene Index if one is
* defined for this bean type.
*/
public Query setUseIndex(UseIndex useIndex);
/**
* Return the setting for how this query should use a Lucene Index if one is
* defined for this bean type.
*/
public UseIndex getUseIndex();
/**
* Return the type of query (List, Set, Map, Bean, rowCount etc).
*/
public Type getType();
/**
* Return the RawSql that was set to use for this query.
*/
public RawSql getRawSql();
/**
* Set RawSql to use for this query.
*/
public Query setRawSql(RawSql rawSql);
/**
* Cancel the query execution if supported by the underlying database and
* driver.
*
* This must be called from a different thread to the query executor.
*
*/
public 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.
*
*/
public Query copy();
/**
* Return the ExpressionFactory used by this query.
*/
public ExpressionFactory getExpressionFactory();
/**
* Returns true if this query was tuned by autoFetch.
*/
public boolean isAutofetchTuned();
/**
* Explicitly specify whether to use Autofetch for this query.
*
* If you do not call this method on a query the "Implicit Autofetch mode"
* is used to determine if Autofetch should be used for a given query.
*
*
* Autofetch 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 Autofetch will not remove.
*
*/
public Query setAutofetch(boolean autofetch);
/**
* Deprecated in favour of {@link EbeanServer#createQuery(Class, String)}.
*
* Set the query using the query language.
*
*
* @deprecated
*/
public Query setQuery(String oql);
/**
* Explicitly set a comma delimited list of the properties to fetch on the
* 'main' entity bean (aka partial object). Note that '*' means all
* properties.
*
*
* Query<Customer> query = Ebean.createQuery(Customer.class);
*
* // Only fetch the customer id, name and status.
* // This is described as a "Partial Object"
* query.select("name, status");
* query.where("lower(name) like :custname").setParameter("custname", "rob%");
*
* List<Customer> customerList = query.findList();
*
*
* @param fetchProperties
* the properties to fetch for this bean (* = all properties).
*/
public 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.
*
*
*
* // query orders...
* Query<Order> query = Ebean.createQuery(Order.class);
*
* // fetch the customer...
* // ... getting the customer's name and phone number
* query.fetch("customer", "name, phNumber");
*
* // ... also fetch the customers billing address (* = all properties)
* query.fetch("customer.billingAddress", "*");
*
*
*
* If columns is null or "*" then all columns/properties for that path are
* fetched.
*
*
*
* // fetch customers (their id, name and status)
* Query<Customer> query = Ebean.createQuery(Customer.class);
*
* // only fetch some of the properties of the customers
* query.select("name, status");
* List<Customer> list = query.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).
*/
public Query fetch(String path, String fetchProperties);
/**
* Same as {@link #fetch(String, String)}.
*
* This will eventually be deprecated in favour of the matching "fetch"
* method.
*
* @deprecated Deprecated in favour of {@link #fetch(String, String)}
*/
public Query join(String assocProperty, String fetchProperties);
/**
* Additionally specify a FetchConfig to use a separate query or lazy
* loading to load this path.
*/
public Query fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig);
/**
* Additionally specify a JoinConfig to specify a "query join" and or define
* the lazy loading query.
*
* @deprecated Deprecated in favour of {@link #fetch(String, String, FetchConfig)}
*/
public Query join(String assocProperty, String fetchProperties, JoinConfig joinConfig);
/**
* Specify a path to load including all its properties.
*
* The same as {@link #fetch(String, String)} with the fetchProperties as
* "*".
*
*
* @param path
* the property of an associated (1-1,1-M,M-1,M-M) bean.
*/
public Query fetch(String path);
/**
* Deprecated in favour of {@link #fetch(String)}
*
* @deprecated in favour of {@link #fetch(String)}
*/
public Query join(String path);
/**
* Additionally specify a JoinConfig to specify a "query join" and or define
* the lazy loading query.
*/
public Query fetch(String path, FetchConfig joinConfig);
/**
* Deprecated in favour of {@link #fetch(String, FetchConfig)}
*
* @deprecated in favour of {@link #fetch(String, FetchConfig)}
*/
public Query join(String path, JoinConfig joinConfig);
/**
* 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)
*/
public List