package com.avaje.ebean; import com.avaje.ebean.config.ServerConfig; import java.io.Serializable; 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. * <p> * Example: Create the query using the API. * </p> * * <pre class="code"> * 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(); * * ... * </pre> * * <p> * Example: The same query using the query language * </p> * * <pre class="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<Order> query = Ebean.createQuery(Order.class, oql); * query.setParameter("custName", "Rob%"); * query.setParameter("minOrderDate", lastWeek); * * List<Order> orderList = query.findList(); * ... * </pre> * * <p> * Example: Using a named query called "with.cust.and.details" * </p> * * <pre class="code"> * Query<Order> query = Ebean.createNamedQuery(Order.class,"with.cust.and.details"); * query.setParameter("custName", "Rob%"); * query.setParameter("minOrderDate", lastWeek); * * List<Order> orderList = query.findList(); * ... * </pre> * * <h3>Autofetch</h3> * <p> * 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. * </p> * <p> * 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. * </p> * <p> * 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. * </p> * * <h3>Query Language</h3> * <p> * <b>Partial Objects</b> * </p> * <p> * The <em>find</em> and <em>fetch</em> 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"). * </p> * <p> * Partial objects can be saved just like fully populated objects. If you do * this you should remember to include the <em>"Version"</em> 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. * </p> * * <pre class="code"> * [ find {bean type} [ ( * | {fetch properties} ) ] ] * [ fetch {associated bean} [ ( * | {fetch properties} ) ] ] * [ where {predicates} ] * [ order by {order by properties} ] * [ limit {max rows} [ offset {first row} ] ] * </pre> * * <p> * <b>FIND</b> <b>{bean type}</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ] * </p> * <p> * 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. * </p> * <p> * In object graph terms the <em>find</em> clause specifies the type of bean at * the root level and the <em>fetch</em> clauses specify the paths of the object * graph to populate. * </p> * <p> * <b>FETCH</b> <b>{associated property}</b> [ ( <i>*</i> | <i>{fetch * properties}</i> ) ] * </p> * <p> * 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. * </p> * <p> * 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. * </p> * <p> * <b>WHERE</b> <b>{list of predicates}</b> * </p> * <p> * 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)}. * </p> * <p> * <b>ORDER BY</b> <b>{order by properties}</b> * </p> * <p> * The list of properties to order the result. You can include ASC (ascending) * and DESC (descending) in the order by clause. * </p> * <p> * <b>LIMIT</b> <b>{max rows}</b> [ OFFSET <i>{first row}</i> ] * </p> * <p> * The limit offset specifies the max rows and first row to fetch. The offset is * optional. * </p> * <h4>Examples of Ebean's Query Language</h4> * <p> * Find orders fetching all its properties * </p> * * <pre class="code"> * find order * </pre> * * <p> * Find orders fetching all its properties * </p> * * <pre class="code"> * find order (*) * </pre> * * <p> * 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. * </p> * * <pre class="code"> * find order (shipDate, status) * </pre> * * <p> * Find orders with a named bind variable (that will need to be bound via * {@link Query#setParameter(String, Object)}). * </p> * * <pre class="code"> * find order * where customer.name like :custLike * </pre> * * <p> * Find orders and also fetch the customer with a named bind parameter. This * will fetch and populate both the order and customer objects. * </p> * * <pre class="code"> * find order * fetch customer * where customer.id = :custId * </pre> * * <p> * 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. * </p> * * <pre class="code"> * find order * fetch customer (name) * fetch customer.shippingAddress * fetch details * fetch details.product (sku, name) * </pre> * * <h3>Early parsing of the Query</h3> * <p> * 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). * </p> * <p> * The thought is that you can use named queries as a 'starting point' and then * modify the query to suit specific needs. * </p> * <h3>Building the Where clause</h3> * <p> * 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. * <ul> * <li>where(String addToWhereClause)</li> * <li>where().add(Expression expression)</li> * <li>where().eq(propertyName, value).like(propertyName , value)...</li> * </ul> * </p> * <p> * The full WHERE clause is constructed by appending together * <li>original query where clause (Named query or query.setQuery(String oql))</li> * <li>clauses added via query.where(String addToWhereClause)</li> * <li>clauses added by Expression objects</li> * </p> * <p> * The above is the order that these are clauses are appended to give the full * WHERE clause. * </p> * <h3>Design Goal</h3> * <p> * 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. * </p> * <p> * 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} . * </p> * * @param <T> * the type of Entity bean this query will fetch. */ public interface Query<T> 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 } /** * Explicitly specify how this query should use a Lucene Index if one is * defined for this bean type. */ public Query<T> 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 RawSql that was set to use for this query. */ public RawSql getRawSql(); /** * Set RawSql to use for this query. */ public Query<T> setRawSql(RawSql rawSql); /** * Cancel the query execution if supported by the underlying database and * driver. * <p> * This must be called from a different thread to the query executor. * </p> */ public void cancel(); /** * Return a copy of the query. * <p> * 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. * </p> */ public Query<T> 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. * <p> * 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. * </p> * <p> * 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. * </p> */ public Query<T> setAutofetch(boolean autofetch); /** * Explicitly set a comma delimited list of the properties to fetch on the * 'main' entity bean (aka partial object). Note that '*' means all * properties. * * <pre class="code"> * 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(); * </pre> * * @param fetchProperties * the properties to fetch for this bean (* = all properties). */ public Query<T> select(String fetchProperties); /** * Specify a path to <em>fetch</em> with its specific properties to include * (aka partial object). * <p> * 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. * </p> * * <pre class="code"> * // 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", "*"); * </pre> * * <p> * If columns is null or "*" then all columns/properties for that path are * fetched. * </p> * * <pre class="code"> * // 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(); * </pre> * * @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<T> fetch(String path, String fetchProperties); /** * Additionally specify a FetchConfig to use a separate query or lazy loading * to load this path. */ public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig); /** * Specify a path to load including all its properties. * <p> * The same as {@link #fetch(String, String)} with the fetchProperties as "*". * </p> * * @param path * the property of an associated (1-1,1-M,M-1,M-M) bean. */ public Query<T> fetch(String path); /** * Additionally specify a JoinConfig to specify a "query join" and or define * the lazy loading query. */ public Query<T> fetch(String path, FetchConfig joinConfig); /** * Execute the query returning the list of Id's. * <p> * This query will execute against the EbeanServer that was used to create it. * </p> * * @see EbeanServer#findIds(Query, Transaction) */ public List<Object> findIds(); /** * Execute the query iterating over the results. * <p> * Remember that with {@link QueryIterator} you must call * {@link QueryIterator#close()} when you have finished iterating the results * (typically in a finally block). * </p> * <p> * This query will execute against the EbeanServer that was used to create it. * </p> */ public QueryIterator<T> findIterate(); /** * Execute the query using callbacks to a visitor to process the resulting * beans one at a time. * <p> * Similar to findIterate() this query method does not require all the result * beans to be all held in memory at once and as such is useful for processing * large queries. * </p> * * <pre class="code"> * * Query<Customer> query = server.find(Customer.class) * .fetch("contacts", new FetchConfig().query(2)) * .where().gt("id", 0) * .orderBy("id") * .setMaxRows(2); * * query.findVisit(new QueryResultVisitor<Customer>() { * * public boolean accept(Customer customer) { * // do something with customer * System.out.println("-- visit " + customer); * return true; * } * }); * </pre> * * @param visitor * the visitor used to process the queried beans. */ public void findVisit(QueryResultVisitor<T> visitor); /** * Execute the query returning the list of objects. * <p> * This query will execute against the EbeanServer that was used to create it. * </p> * * @see EbeanServer#findList(Query, Transaction) */ public List<T> findList(); /** * Execute the query returning the set of objects. * <p> * This query will execute against the EbeanServer that was used to create it. * </p> * * @see EbeanServer#findSet(Query, Transaction) */ public Set<T> findSet(); /** * Execute the query returning a map of the objects. * <p> * This query will execute against the EbeanServer that was used to create it. * </p> * <p> * You can use setMapKey() so specify the property values to be used as keys * on the map. If one is not specified then the id property is used. * </p> * * <pre class="code"> * Query<Product> query = Ebean.createQuery(Product.class); * query.setMapKey("sku"); * Map<?, Product> map = query.findMap(); * </pre> * * @see EbeanServer#findMap(Query, Transaction) */ public Map<?, T> findMap(); /** * Return a typed map specifying the key property and type. */ public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType); /** * Execute the query returning either a single bean or null (if no matching * bean is found). * <p> * If more than 1 row is found for this query then a PersistenceException is * thrown. * </p> * <p> * This is useful when your predicates dictate that your query should only * return 0 or 1 results. * </p> * * <pre class="code"> * // assuming the sku of products is unique... * Product product = * Ebean.find(Product.class) * .where("sku = ?") * .set(1, "aa113") * .findUnique(); * ... * </pre> * * <p> * It is also useful with finding objects by their id when you want to specify * further join information. * </p> * * <pre class="code"> * // Fetch order 1 and additionally fetch join its order details... * Order order = * Ebean.find(Order.class) * .setId(1) * .fetch("details") * .findUnique(); * * List<OrderDetail> details = order.getDetails(); * ... * </pre> */ public T findUnique(); /** * Return the count of entities this query should return. * <p> * This is the number of 'top level' or 'root level' entities. * </p> */ public int findRowCount(); /** * Execute find row count query in a background thread. * <p> * This returns a Future object which can be used to cancel, check the * execution status (isDone etc) and get the value (with or without a * timeout). * </p> * * @return a Future object for the row count query */ public FutureRowCount<T> findFutureRowCount(); /** * Execute find Id's query in a background thread. * <p> * This returns a Future object which can be used to cancel, check the * execution status (isDone etc) and get the value (with or without a * timeout). * </p> * * @return a Future object for the list of Id's */ public FutureIds<T> findFutureIds(); /** * Execute find list query in a background thread. * <p> * This returns a Future object which can be used to cancel, check the * execution status (isDone etc) and get the value (with or without a * timeout). * </p> * * @return a Future object for the list result of the query */ public FutureList<T> findFutureList(); /** * Return a PagingList for this query. * <p> * This can be used to break up a query into multiple queries to fetch the * data a page at a time. * </p> * <p> * This typically works by using a query per page and setting * {@link Query#setFirstRow(int)} and and {@link Query#setMaxRows(int)} on the * query. This usually would translate into SQL that uses limit offset, rownum * or row_number function to limit the result set. * </p> * * @param pageSize * the number of beans fetched per Page * */ public PagingList<T> findPagingList(int pageSize); /** * Set a named bind parameter. Named parameters have a colon to prefix the * name. * * <pre class="code"> * // a query with a named parameter * String oql = "find order where status = :orderStatus"; * * Query<Order> query = Ebean.createQuery(Order.class, oql); * * // bind the named parameter * query.bind("orderStatus", OrderStatus.NEW); * List<Order> list = query.findList(); * </pre> * * @param name * the parameter name * @param value * the parameter value */ public Query<T> setParameter(String name, Object value); /** * Set an ordered bind parameter according to its position. Note that the * position starts at 1 to be consistent with JDBC PreparedStatement. You need * to set a parameter value for each ? you have in the query. * * <pre class="code"> * // a query with a positioned parameter * String oql = "where status = ? order by id desc"; * * Query<Order> query = Ebean.createQuery(Order.class, oql); * * // bind the parameter * query.setParameter(1, OrderStatus.NEW); * * List<Order> list = query.findList(); * </pre> * * @param position * the parameter bind position starting from 1 (not 0) * @param value * the parameter bind value. */ public Query<T> setParameter(int position, Object value); /** * Set a listener to process the query on a row by row basis. * <p> * Use this when you want to process a large query and do not want to hold the * entire query result in memory. * </p> * <p> * It this case the rows are not loaded into the persistence context and * instead are processed by the query listener. * </p> * * <pre class="code"> * QueryListener<Order> listener = ...; * * Query<Order> query = Ebean.createQuery(Order.class); * * // set the listener that will process each order one at a time * query.setListener(listener); * * // execute the query. Note that the returned * // list (emptyList) will be empty ... * List<Order> emtyList = query.findList(); * </pre> */ public Query<T> setListener(QueryListener<T> queryListener); /** * Set the Id value to query. This is used with findUnique(). * <p> * You can use this to have further control over the query. For example adding * fetch joins. * </p> * * <pre class="code"> * Query<Order> query = Ebean.createQuery(Order.class); * Order order = query.setId(1).join("details").findUnique(); * List<OrderDetail> details = order.getDetails(); * ... * </pre> */ public Query<T> setId(Object id); /** * Add additional clause(s) to the where clause. * <p> * This typically contains named parameters which will need to be set via * {@link #setParameter(String, Object)}. * </p> * * <pre class="code"> * Query<Order> query = Ebean.createQuery(Order.class, "top"); * ... * if (...) { * query.where("status = :status and lower(customer.name) like :custName"); * query.setParameter("status", Order.NEW); * query.setParameter("custName", "rob%"); * } * </pre> * * <p> * Internally the addToWhereClause string is processed by removing named * parameters (replacing them with ?) and by converting logical property names * to database column names (with table alias). The rest of the string is left * as is and it is completely acceptable and expected for the addToWhereClause * string to include sql functions and columns. * </p> * * @param addToWhereClause * the clause to append to the where clause which typically contains * named parameters. * @return The query object */ public Query<T> where(String addToWhereClause); /** * Add a single Expression to the where clause returning the query. * * <pre class="code"> * List<Order> newOrders = * Ebean.find(Order.class) * .where().eq("status", Order.NEW) * .findList(); * ... * </pre> */ public Query<T> where(Expression expression); /** * Add Expressions to the where clause with the ability to chain on the * ExpressionList. You can use this for adding multiple expressions to the * where clause. * * <pre class="code"> * Query<Order> query = Ebean.createQuery(Order.class, "top"); * ... * if (...) { * query.where() * .eq("status", Order.NEW) * .ilike("customer.name","rob%"); * } * </pre> * * @see Expr * @return The ExpressionList for adding expressions to. */ public ExpressionList<T> where(); /** * This applies a filter on the 'many' property list rather than the root * level objects. * <p> * Typically you will use this in a scenario where the cardinality is high on * the 'many' property you wish to join to. Say you want to fetch customers * and their associated orders... but instead of getting all the orders for * each customer you only want to get the new orders they placed since last * week. In this case you can use filterMany() to filter the orders. * </p> * * <pre class="code"> * * List<Customer> list = Ebean * .find(Customer.class) * // .fetch("orders", new FetchConfig().lazy()) * // .fetch("orders", new FetchConfig().query()) * .fetch("orders").where().ilike("name", "rob%").filterMany("orders") * .eq("status", Order.Status.NEW).gt( * "orderDate", lastWeek).findList(); * * </pre> * * <p> * Please note you have to be careful that you add expressions to the correct * expression list - as there is one for the 'root level' and one for each * filterMany that you have. * </p> * * @param propertyName * the name of the many property that you want to have a filter on. * * @return the expression list that you add filter expressions for the many * to. */ public ExpressionList<T> filterMany(String propertyName); /** * Add Expressions to the Having clause return the ExpressionList. * <p> * Currently only beans based on raw sql will use the having clause. * </p> * <p> * Note that this returns the ExpressionList (so you can add multiple * expressions to the query in a fluent API way). * </p> * * @see Expr * @return The ExpressionList for adding more expressions to. */ public ExpressionList<T> having(); /** * Add additional clause(s) to the having clause. * <p> * This typically contains named parameters which will need to be set via * {@link #setParameter(String, Object)}. * </p> * * <pre class="code"> * Query<ReportOrder> query = Ebean.createQuery(ReportOrder.class); * ... * if (...) { * query.having("score > :min"); * query.setParameter("min", 1); * } * </pre> * * @param addToHavingClause * the clause to append to the having clause which typically contains * named parameters. * @return The query object */ public Query<T> having(String addToHavingClause); /** * Add an expression to the having clause returning the query. * <p> * Currently only beans based on raw sql will use the having clause. * </p> * <p> * This is similar to {@link #having()} except it returns the query rather * than the ExpressionList. This is useful when you want to further specify * something on the query. * </p> * * @param addExpressionToHaving * the expression to add to the having clause. * @return the Query object */ public Query<T> having(Expression addExpressionToHaving); /** * Set the order by clause replacing the existing order by clause if there is * one. * <p> * This follows SQL syntax using commas between each property with the * optional asc and desc keywords representing ascending and descending order * respectively. * </p> * <p> * This is EXACTLY the same as {@link #order(String)}. * </p> */ public Query<T> orderBy(String orderByClause); /** * Set the order by clause replacing the existing order by clause if there is * one. * <p> * This follows SQL syntax using commas between each property with the * optional asc and desc keywords representing ascending and descending order * respectively. * </p> * <p> * This is EXACTLY the same as {@link #orderBy(String)}. * </p> */ public Query<T> order(String orderByClause); /** * Return the OrderBy so that you can append an ascending or descending * property to the order by clause. * <p> * This will never return a null. If no order by clause exists then an 'empty' * OrderBy object is returned. * </p> * <p> * This is EXACTLY the same as {@link #orderBy()}. * </p> */ public OrderBy<T> order(); /** * Return the OrderBy so that you can append an ascending or descending * property to the order by clause. * <p> * This will never return a null. If no order by clause exists then an 'empty' * OrderBy object is returned. * </p> * <p> * This is EXACTLY the same as {@link #order()}. * </p> */ public OrderBy<T> orderBy(); /** * Set an OrderBy object to replace any existing OrderBy clause. * <p> * This is EXACTLY the same as {@link #setOrderBy(OrderBy)}. * </p> */ public Query<T> setOrder(OrderBy<T> orderBy); /** * Set an OrderBy object to replace any existing OrderBy clause. * <p> * This is EXACTLY the same as {@link #setOrder(OrderBy)}. * </p> */ public Query<T> setOrderBy(OrderBy<T> orderBy); /** * Set whether this query uses DISTINCT. */ public Query<T> setDistinct(boolean isDistinct); /** * Set this to true and the beans and collections returned will be plain * classes rather than Ebean generated dynamic subclasses etc. * <p> * This is *ONLY* relevant when you are not using enhancement (and using * dynamic subclasses instead). * </p> * <p> * Alternatively you can globally set the mode using ebean.vanillaMode=true in * ebean.properties or {@link ServerConfig#setVanillaMode(boolean)}. * </p> * * @see ServerConfig#setVanillaMode(boolean) * @see ServerConfig#setVanillaRefMode(boolean) */ public Query<T> setVanillaMode(boolean vanillaMode); /** * Return the first row value. */ public int getFirstRow(); /** * Set the first row to return for this query. * * @param firstRow */ public Query<T> setFirstRow(int firstRow); /** * Return the max rows for this query. */ public int getMaxRows(); /** * Set the maximum number of rows to return in the query. * * @param maxRows * the maximum number of rows to return in the query. */ public Query<T> setMaxRows(int maxRows); /** * Set the rows after which fetching should continue in a background thread. * * @param backgroundFetchAfter */ public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter); /** * Set the property to use as keys for a map. * <p> * If no property is set then the id property is used. * </p> * * <pre class="code"> * // Assuming sku is unique for products... * * Query<Product> query = Ebean.createQuery(Product.class); * * // use sku for keys... * query.setMapKey("sku"); * * Map<?,Product> productMap = query.findMap(); * ... * </pre> * * @param mapKey * the property to use as keys for a map. */ public Query<T> setMapKey(String mapKey); /** * Set this to true to use the bean cache. * <p> * If the query result is in cache then by default this same instance is * returned. In this sense it should be treated as a read only object graph. * </p> */ public Query<T> setUseCache(boolean useBeanCache); /** * Set this to true to use the query cache. */ public Query<T> setUseQueryCache(boolean useQueryCache); /** * When set to true when you want the returned beans to be read only. */ public Query<T> setReadOnly(boolean readOnly); /** * When set to true all the beans from this query are loaded into the bean * cache. */ public Query<T> setLoadBeanCache(boolean loadBeanCache); /** * Set a timeout on this query. * <p> * This will typically result in a call to setQueryTimeout() on a * preparedStatement. If the timeout occurs an exception will be thrown - this * will be a SQLException wrapped up in a PersistenceException. * </p> * * @param secs * the query timeout limit in seconds. Zero means there is no limit. */ public Query<T> setTimeout(int secs); /** * A hint which for JDBC translates to the Statement.fetchSize(). * <p> * Gives the JDBC driver a hint as to the number of rows that should be * fetched from the database when more rows are needed for ResultSet. * </p> */ public Query<T> setBufferFetchSizeHint(int fetchSize); /** * Return the sql that was generated for executing this query. * <p> * This is only available after the query has been executed and provided only * for informational purposes. * </p> */ public String getGeneratedSql(); /** * Return the total hits matched for a lucene text search query. */ public int getTotalHits(); /** * executed the select with "for update" which should lock the record * "on read" */ public Query<T> setForUpdate(boolean forUpdate); public boolean isForUpdate(); }