All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avaje.ebean.FetchConfig 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;

/**
 * Defines the configuration options for a "query fetch" or a
 * "lazy loading fetch". This gives you the ability to use multiple smaller
 * queries to populate an object graph as opposed to a single large query.
 * 

* The primary goal is to provide efficient ways of loading complex object * graphs avoiding SQL Cartesian product and issues around populating object * graphs that have multiple *ToMany relationships. *

*

* It also provides the ability to control the lazy loading queries (batch size, * selected properties and fetches) to avoid N+1 queries etc. *

* There can also be cases loading across a single OneToMany where 2 SQL queries * using Ebean FetchConfig.query() can be more efficient than one SQL query. * When the "One" side is wide (lots of columns) and the cardinality difference * is high (a lot of "Many" beans per "One" bean) then this can be more * efficient loaded as 2 SQL queries. *

* *
 * // Normal fetch join results in a single SQL query 
 * List<Order> list = Ebean.find(Order.class).join("details").findList();
 * 
 * // Find Orders join details using a single SQL query
 * 
*

* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL * queries *

* *
 * // This will use 2 SQL queries to build this object graph
 * List<Order> list = 
 *     Ebean.find(Order.class)
 *       .fetch("details", new FetchConfig().query())
 *       .findList();
 * 
 * // query 1)  find order 
 * // query 2)  find orderDetails where order.id in (?,?...) // first 100 order id's
 * 
*

* Example: Using 2 "query joins" *

* *
 * // This will use 3 SQL queries to build this object graph
 * List<Order> list = 
 *     Ebean.find(Order.class)
 *       .fetch("details", new JoinConfig().query())
 *       .fetch("customer", new JoinConfig().query(5))
 *       .findList();
 * 
 * // query 1) find order 
 * // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
 * // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
 * 
*

* Example: Using "query joins" and partial objects *

* *
 * // This will use 3 SQL queries to build this object graph
 * List<Order> list = 
 *     Ebean.find(Order.class)
 *       .select("status, shipDate")
 *       .fetch("details", "quantity, price", new FetchConfig().query())
 *       .fetch("details.product", "sku, name")
 *       .fetch("customer", "name", new FetchConfig().query(10))
 *       .fetch("customer.contacts")
 *       .fetch("customer.shippingAddress")
 *       .findList();
 * 
 * // query 1) find order (status, shipDate)
 * // query 2) find orderDetail (quantity, price) fetch product (sku, name) where order.id in (?,? ...)
 * // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*) where id in (?,?,?,?,?)
 * 
 * // Note: the fetch of "details.product" is automatically included into the 
 * //       fetch of "details"
 * //
 * // Note: the fetch of "customer.contacts" and "customer.shippingAddress" 
 * //       are automatically included in the fetch of "customer" 
 * 
*

* You can use query() and lazy together on a single join. The query is executed * immediately and the lazy defines the batch size to use for further lazy * loading (if lazy loading is invoked). *

* *
 * List<Order> list = 
 *     Ebean.find(Order.class)
 *       .fetch("customer", new FetchConfig().query(3).lazy(10))
 *       .findList();
 * 
 * // query 1) find order 
 * // query 2) find customer where id in (?,?,?) // first 3 customers 
 * // .. then if lazy loading of customers is invoked 
 * // .. use a batch size of 10 to load the customers
 * 
 * 
* *

* Example of controlling the lazy loading query: *

*

* This gives us the ability to optimise the lazy loading query for a given use * case. *

* *
 * List<Order> list = Ebean.find(Order.class)
 *   .fetch("customer","name", new FetchConfig().lazy(5))
 *   .fetch("customer.contacts","contactName, phone, email")
 *   .fetch("customer.shippingAddress")
 *   .where().eq("status",Order.Status.NEW)
 *   .findList();
 * 
 * // query 1) find order where status = Order.Status.NEW
 * //  
 * // .. if lazy loading of customers is invoked 
 * // .. use a batch size of 5 to load the customers 
 *  
 *       find  customer (name) 
 *       fetch contact (contactName, phone, email) 
 *       fetch shippingAddress (*) 
 *       where id in (?,?,?,?,?)
 * 
 * 
* * @author mario * @author rbygrave */ public class FetchConfig { private int lazyBatchSize = -1; private int queryBatchSize = -1; private boolean queryAll; /** * Construct the fetch configuration object. */ public FetchConfig() { } /** * Specify that this path should be lazy loaded using * the default batch load size. */ public FetchConfig lazy() { this.lazyBatchSize = 0; return this; } /** * Specify that this path should be lazy loaded with a specified batch size. * * @param lazyBatchSize * the batch size for lazy loading */ public FetchConfig lazy(int lazyBatchSize) { this.lazyBatchSize = lazyBatchSize; return this; } /** * Specify that this path should be loaded as a separate query * (rather than as part of the main query). *

* This will use the default batch size for separate query which is 100. *

*/ public FetchConfig query() { this.queryBatchSize = 0; this.queryAll = true; return this; } /** * Specify that this path should be loaded as a separate query (rather than * as part of the main query). *

* The queryBatchSize is the number of parent id's that this separate query * will load per batch. *

*

* This will load all beans on this path eagerly. *

* * @param queryBatchSize * the batch size used to load beans on this path */ public FetchConfig query(int queryBatchSize) { this.queryBatchSize = queryBatchSize; this.queryAll = true; return this; } /** * Similar to {@link #query(int)} but only fetches the first batch. *

* If there are more parent beans than the batch size then they will not be * loaded eagerly but instead use lazy loading. *

* * @param queryBatchSize * the number of parent beans this path is populated for */ public FetchConfig queryFirst(int queryBatchSize) { this.queryBatchSize = queryBatchSize; this.queryAll = false; return this; } /** * Return the batch size for lazy loading. */ public int getLazyBatchSize() { return lazyBatchSize; } /** * Return the batch size for separate query load. */ public int getQueryBatchSize() { return queryBatchSize; } /** * Return true if the query fetch should fetch 'all' rather than just the * 'first' batch. */ public boolean isQueryAll() { return queryAll; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy