001package io.ebean;
002
003import io.avaje.lang.NonNullApi;
004import io.ebean.service.SpiFetchGroupQuery;
005
006/**
007 * Defines what part of the object graph to load (select and fetch clauses).
008 * <p>
009 * Using a FetchGroup effectively sets the select() and fetch() clauses for a query. It is alternative
010 * to specifying the select() and fetch() clauses on the query allowing for more re-use of "what to load"
011 * that can be defined separately from the query and combined with other FetchGroups.
012 * </p>
013 *
014 * <h3>Select example</h3>
015 * <pre>{@code
016 *
017 * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
018 *
019 * Customer.query()
020 *   .select(fetchGroup)
021 *   .findList();
022 *
023 * }</pre>
024 *
025 * <h3>Select and fetch example</h3>
026 * <pre>{@code
027 *
028 * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
029 *   .select("name, status")
030 *   .fetch("contacts", "firstName, lastName, email")
031 *   .build();
032 *
033 * Customer.query()
034 *   .select(fetchGroup)
035 *   .findList();
036 *
037 * }</pre>
038 *
039 * <h3>Combining FetchGroups</h3>
040 * <p>
041 *   FetchGroups can be combined together to form another FetchGroup.
042 * </p>
043 * <pre>{@code
044 *
045 *  FetchGroup<Address> FG_ADDRESS = FetchGroup.of(Address.class)
046 *    .select("line1, line2, city")
047 *    .fetch("country", "name")
048 *    .build();
049 *
050 *  FetchGroup<Customer> FG_CUSTOMER = FetchGroup.of(Customer.class)
051 *    .select("name, version")
052 *    .fetch("billingAddress", FG_ADDRESS)
053 *    .build();
054 *
055 *
056 *  Customer.query()
057 *    .select(FG_CUSTOMER)
058 *    .findList();
059 *
060 * }</pre>
061 *
062 * @param <T> The bean type the Fetch group can be applied to
063 */
064@NonNullApi
065public interface FetchGroup<T> {
066
067  /**
068   * Return the FetchGroup with the given select clause.
069   * <p>
070   *   We use this for simple FetchGroup that only select() properties and do not have additional fetch() clause.
071   * </p>
072   * <pre>{@code
073   *
074   * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class, "name, status");
075   *
076   * Customer.query()
077   *   .select(fetchGroup)
078   *   .findList();
079   *
080   * }</pre>
081   *
082   * @param select The select clause of the FetchGroup
083   *
084   * @return The FetchGroup with the given select clause
085   */
086  static <T> FetchGroup<T> of(Class<T> cls, String select) {
087    return XServiceProvider.fetchGroupOf(cls, select);
088  }
089
090  /**
091   * Return the FetchGroupBuilder with the given select clause that we can add fetch clauses to.
092   * <p>
093   * We chain select() with one or more fetch() clauses to define the object graph to load.
094   * </p>
095   * <pre>{@code
096   *
097   * FetchGroup<Customer> fetchGroup = FetchGroup.of(Customer.class)
098   *   .select("name, status")
099   *   .fetch("contacts", "firstName, lastName, email")
100   *   .build();
101   *
102   * Customer.query()
103   *   .select(fetchGroup)
104   *   .findList();
105   *
106   * }</pre>
107   *
108   * @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
109   */
110  static <T> FetchGroupBuilder<T> of(Class<T> cls) {
111    return XServiceProvider.fetchGroupOf(cls);
112  }
113
114  /**
115   * Return a query to be used by query beans for constructing FetchGroup.
116   */
117  static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
118    return XServiceProvider.fetchGroupQueryFor(beanType);
119  }
120
121}