001package com.avaje.ebean;
002
003import com.avaje.ebean.bean.EntityBean;
004import com.avaje.ebean.text.PathProperties;
005import com.avaje.ebean.util.ClassUtil;
006import org.jetbrains.annotations.Nullable;
007
008import javax.persistence.MappedSuperclass;
009import java.util.List;
010import java.util.Map;
011import java.util.Set;
012import java.util.UUID;
013
014/**
015 * A MappedSuperclass base class that provides convenience methods for inserting, updating and
016 * deleting beans.
017 * 
018 * <p>
019 * By having your entity beans extend this it provides a 'Active Record' style programming model for
020 * Ebean users.
021 * 
022 * <p>
023 * Note that there is a avaje-ebeanorm-mocker project that enables you to use Mockito or similar
024 * tools to still mock out the underlying 'default EbeanServer' for testing purposes.
025 * 
026 * <p>
027 * You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
028 * or if you believe it 'pollutes' your entity beans.
029 *
030 * <p>
031 * You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
032 * and have that same instance used with this Model and Finder. The way that works is that when the
033 * DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
034 * way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
035 * that same instance also used to support the Model and Finder active record style.
036 *
037 * <p>
038 * If you choose to use the Model mapped superclass you will probably also chose to additionally add
039 * a {@link Find} as a public static field to complete the active record pattern and provide a
040 * relatively nice clean way to write queries.
041 *
042 * <h3>Typical common @MappedSuperclass</h3>
043 * <pre>{@code
044 *
045 *     // Typically there is a common base model that has some
046 *     // common properties like the ones below
047 *
048 *     @MappedSuperclass
049 *     public class BaseModel extends Model {
050 *
051 *       @Id Long id;
052 *
053 *       @Version Long version;
054 *
055 *       @CreatedTimestamp Timestamp whenCreated;
056 *
057 *       @UpdatedTimestamp Timestamp whenUpdated;
058 *
059 *       ...
060 *
061 * }</pre>
062 *
063 * <h3>Extend the Model</h3>
064 * <pre>{@code
065 *
066 *     // Extend the mappedSuperclass
067 *
068 *     @Entity @Table(name="oto_account")
069 *     public class Customer extends BaseModel {
070 *
071 *       // Add a static Find
072 *       // ... with Long being the type of our @Id property.
073 *       // ... Note the {} at the end as Find is an abstract class.
074 *
075 *       public static final Find<Long,Account> find = new Find<Long,Account>(){};
076 *
077 *       String name;
078 *       ...
079 *     }
080 *
081 * }</pre>
082 *
083 * <h3>Modal: save()</h3>
084 * <pre>{@code
085 *
086 *     // Active record style ... save(), delete() etc
087 *     Customer customer = new Customer();
088 *     customer.setName("AC234");
089 *
090 *     // save() method inherited from Model
091 *     customer.save();
092 *
093 * }</pre>
094 *
095 * <h3>Find byId</h3>
096 * <pre>{@code
097 *
098 *     // find byId
099 *     Customer customer = Customer.find.byId(42);
100 *
101 * }</pre>
102 *
103 * <h3>Find where</h3>
104 * <pre>{@code
105 *
106 *     // find where ...
107 *     List<Customer> customers =
108 *         Customer.find
109 *         .where().gt("startDate", lastMonth)
110 *         .findList();
111 *
112 * }</pre>
113 */
114@MappedSuperclass
115public abstract class Model {
116
117  /**
118   * Return the underlying 'default' EbeanServer.
119   * 
120   * <p>
121   * This provides full access to the API such as explicit transaction demarcation etc.
122   * 
123   * <p>
124   * Example:
125   * <pre>{@code
126   *
127   * Transaction transaction = Customer.db().beginTransaction();
128   * try {
129   * 
130   *   // turn off cascade persist for this transaction
131   *   transaction.setPersistCascade(false);
132   * 
133   *   // extra control over jdbc batching for this transaction
134   *   transaction.setBatchGetGeneratedKeys(false);
135   *   transaction.setBatchMode(true);
136   *   transaction.setBatchSize(20);
137   * 
138   *   Customer customer = new Customer();
139   *   customer.setName(&quot;Roberto&quot;);
140   *   customer.save();
141   * 
142   *   Customer otherCustomer = new Customer();
143   *   otherCustomer.setName("Franko");
144   *   otherCustomer.save();
145   * 
146   *   transaction.commit();
147   * 
148   * } finally {
149   *   transaction.end();
150   * }
151   * 
152   * }</pre>
153   */
154  public static EbeanServer db() {
155    return Ebean.getDefaultServer();
156  }
157
158  /**
159   * Return a named EbeanServer that is typically different to the default server.
160   * 
161   * <p>
162   * If you are using multiple databases then each database has a name and maps to a single
163   * EbeanServer. You can use this method to get an EbeanServer for another database.
164   * 
165   * @param server
166   *          The name of the EbeanServer. If this is null then the default EbeanServer is returned.
167   */
168  public static EbeanServer db(String server) {
169    return Ebean.getServer(server);
170  }
171
172  /**
173   * Marks the entity bean as dirty.
174   * <p>
175   * This is used so that when a bean that is otherwise unmodified is updated the version
176   * property is updated.
177   * <p>
178   * An unmodified bean that is saved or updated is normally skipped and this marks the bean as
179   * dirty so that it is not skipped.
180   * 
181   * <pre>{@code
182   * 
183   * Customer customer = Customer.find.byId(id);
184   * 
185   * // mark the bean as dirty so that a save() or update() will
186   * // increment the version property
187   * customer.markAsDirty();
188   * customer.save();
189   * 
190   * }</pre>
191   *
192   * @see EbeanServer#markAsDirty(Object)
193   */
194  public void markAsDirty() {
195    db().markAsDirty(this);
196  }
197
198  /**
199   * Mark the property as unset or 'not loaded'.
200   * <p>
201   *   This would be used to specify a property that we did not wish to include in a stateless update.
202   * </p>
203   * <pre>{@code
204   *
205   *   // populate an entity bean from JSON or whatever
206   *   User user = ...;
207   *
208   *   // mark the email property as 'unset' so that it is not
209   *   // included in a 'stateless update'
210   *   user.markPropertyUnset("email");
211   *
212   *   user.update();
213   *
214   * }</pre>
215   *
216   * @param propertyName the name of the property on the bean to be marked as 'unset'
217   */
218  public void markPropertyUnset(String propertyName) {
219    ((EntityBean)this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
220  }
221
222  /**
223   * Insert or update this entity depending on its state.
224   * 
225   * <p>
226   * Ebean will detect if this is a new bean or a previously fetched bean and perform either an
227   * insert or an update based on that.
228   *
229   * @see EbeanServer#save(Object)
230   */
231  public void save() {
232    db().save(this);
233  }
234
235  /**
236   * Update this entity.
237   *
238   * @see EbeanServer#update(Object)
239   */
240  public void update() {
241    db().update(this);
242  }
243
244  /**
245   * Insert this entity.
246   *
247   * @see EbeanServer#insert(Object)
248   */
249  public void insert() {
250    db().insert(this);
251  }
252
253  /**
254   * Delete this entity.
255   *
256   * @see EbeanServer#delete(Object)
257   */
258  public void delete() {
259    db().delete(this);
260  }
261
262  /**
263   * Perform an update using this entity against the specified server.
264   */
265  public void update(String server) {
266    db(server).update(this);
267  }
268
269  /**
270   * Perform an insert using this entity against the specified server.
271   */
272  public void insert(String server) {
273    db(server).insert(this);
274  }
275
276  /**
277   * Perform a delete using this entity against the specified server.
278   */
279  public void delete(String server) {
280    db(server).delete(this);
281  }
282
283  /**
284   * Refreshes this entity from the database.
285   *
286   * @see EbeanServer#refresh(Object)
287   */
288  public void refresh() {
289    db().refresh(this);
290  }
291
292  /**
293   * A concrete implementation of Find.
294   * <p>
295   * It should be preferred to use {@link Find} instead of Finder as that can use reflection to determine the class
296   * literal type of the entity bean.
297   * </p>
298   * @param <I> type of the Id property
299   * @param <T> type of the entity bean
300   */
301  public static class Finder<I, T> extends Find<I, T> {
302
303    /**
304     * Create with the type of the entity bean.
305     *
306     * <pre>{@code
307     *
308     * @Entity
309     * public class Customer extends BaseModel {
310     *
311     *   public static final Finder<Long,Customer> find = new Finder<Long,Customer>(Customer.class);
312     *   ...
313     *
314     * }</pre>
315     *
316     * <p/>
317     * The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does
318     * not require the class literal Customer.class to be passed into the constructor.
319     *
320     * <pre>{@code
321     *
322     * @Entity
323     * public class Customer extends BaseModel {
324     *
325     *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
326     *   ...
327     *
328     * }</pre>
329     */
330    public Finder(Class<T> type) {
331      super(null, type);
332    }
333
334    /**
335     * Create with the type of the entity bean and specific server name.
336     */
337    public Finder(String serverName, Class<T> type) {
338      super(serverName, type);
339    }
340
341    /**
342     * Please migrate to use {@link Find} or constructor <code>Finder(Class)</code> that
343     * does not have the idType parameter.
344     * <p/>
345     * Create with the type of the ID property and entity bean and specific server name.
346     *
347     * @deprecated
348     */
349    public Finder(Class<I> idType, Class<T> type) {
350      super(null, type);
351    }
352
353    /**
354     * Please migrate to use the constructor <code>Finder(String, Class)</code> that
355     * does not have the idType parameter.
356     * <p/>
357     * Create with the type of the ID property and entity bean and specific server name.
358     *
359     * @deprecated
360     */
361    public Finder(String serverName, Class<I> idType, Class<T> type) {
362      super(serverName, type);
363    }
364  }
365
366  /**
367   * Helper object for performing queries.
368   * 
369   * <p>
370   * Typically a Find instance is defined as a public static field on an entity bean class to provide a
371   * nice way to write queries.
372   *
373   * <h3>Example use:</h3>
374   *
375   * <pre>{@code
376   *
377   * @Entity
378   * public class Customer extends BaseModel {
379   *
380   *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
381   *
382   *   ...
383   *
384   * }</pre>
385   * <p/>
386   * This enables you to write code like:
387   * <pre>{@code
388   *
389   * Customer customer = Customer.find.byId(42L);
390   *
391   * List<Customer> customers =
392   *     Customer.find
393   *         .select("name, dateOfBirth")
394   *         .findList();
395   *
396   * }</pre>
397   *
398   * <h3>Kotlin</h3>
399   * In Kotlin you would typically create Find as a companion object.
400   * <pre>{@code
401   *
402   *   // kotlin
403   *   companion object : Model.Find<Long, Product>() {}
404   *
405   * }</pre>
406   * @param <I>
407   *          The Id type. This is most often a {@link Long} but is also often a {@link UUID} or
408   *          {@link String}.
409   *
410   * @param <T>
411   *          The entity bean type
412   */
413  public static abstract class Find<I, T> {
414
415    /**
416     * The entity bean type.
417     */
418    private final Class<T> type;
419
420    /**
421     * The name of the EbeanServer, null for the default server.
422     */
423    private final String serverName;
424
425    /**
426     * Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>.
427     * <p/>
428     * Typically you create Find as a public static field on each entity bean as the example below.
429     *
430     * <p/>
431     * Note that Find is an abstract class and hence <code>{}</code> is required. This is done so
432     * that the type (class literal) of the entity bean can be derived from the generics parameter.
433     *
434     * <pre>{@code
435     *
436     * @Entity
437     * public class Customer extends BaseModel {
438     *
439     *   // Note the trailing {} as Find is an abstract class.
440     *   // We do this so that we can derive the type literal Customer.class
441     *   // via reflection
442     *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
443     *   ...
444     *
445     * }</pre>
446     * <p/>
447     * This enables you to write code like:
448     * <pre>{@code
449     *
450     * Customer customer = Customer.find.byId(42L);
451     *
452     * List<Customer> customers =
453     *     Customer.find
454     *        .select("name, email, dateOfBirth")
455     *        .findList();
456     *
457     * }</pre>
458     *
459     * <h3>Kotlin</h3>
460     * In Kotlin you would typically create it as a companion object.
461     *
462     * <pre>{@code
463     *
464     *   // kotlin
465     *   companion object : Model.Find<Long, Product>() {}
466     *
467     * }</pre>
468     */
469    @SuppressWarnings("unchecked")
470    public Find() {
471      this.serverName = null;
472      this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
473    }
474
475    /**
476     * Construct passing the class literal type of the entity type.
477     */
478    protected Find(String serverName, Class<T> type) {
479      this.serverName = serverName;
480      this.type = type;
481    }
482
483    /**
484     * Return the underlying 'default' EbeanServer.
485     * 
486     * <p>
487     * This provides full access to the API such as explicit transaction demarcation etc.
488     * 
489     */
490    public EbeanServer db() {
491      return Ebean.getServer(serverName);
492    }
493
494    /**
495     * Return typically a different EbeanServer to the default.
496     * <p>
497     * This is equivilent to {@link Ebean#getServer(String)}
498     * 
499     * @param server
500     *          The name of the EbeanServer. If this is null then the default EbeanServer is
501     *          returned.
502     */
503    public EbeanServer db(String server) {
504      return Ebean.getServer(server);
505    }
506
507    /**
508     * Creates a Finder for the named EbeanServer.
509     *
510     * <p>
511     * Create and return a new Finder for a different server.
512     */
513    public Finder<I, T> on(String server) {
514      return new Finder<I, T>(server, type);
515    }
516
517    /**
518     * Delete a bean by Id.
519     * <p>
520     * Equivalent to {@link EbeanServer#delete(Class, Object)}
521     */
522    public void deleteById(I id) {
523      db().delete(type, id);
524    }
525
526    /**
527     * Retrieves all entities of the given type.
528     * 
529     * <p>
530     * This is the same as (synonym for) {@link #findList()}
531     */
532    public List<T> all() {
533      return findList();
534    }
535
536    /**
537     * Retrieves an entity by ID.
538     * 
539     * <p>
540     * Equivalent to {@link EbeanServer#find(Class, Object)}
541     */
542    @Nullable
543    public T byId(I id) {
544      return db().find(type, id);
545    }
546
547    /**
548     * Creates an entity reference for this ID.
549     * 
550     * <p>
551     * Equivalent to {@link EbeanServer#getReference(Class, Object)}
552     */
553    public T ref(I id) {
554      return db().getReference(type, id);
555    }
556
557    /**
558     * Creates a filter for sorting and filtering lists of entities locally without going back to
559     * the database.
560     * <p>
561     * Equivalent to {@link EbeanServer#filter(Class)}
562     */
563    public Filter<T> filter() {
564      return db().filter(type);
565    }
566
567    /**
568     * Creates a query.
569     * <p>
570     * Equivalent to {@link EbeanServer#find(Class)}
571     */
572    public Query<T> query() {
573      return db().find(type);
574    }
575
576    /**
577     * Creates a query applying the path properties to set the select and fetch clauses.
578     * <p>
579     * Equivalent to {@link Query#apply(com.avaje.ebean.text.PathProperties)}
580     */
581    public Query<T> apply(PathProperties pathProperties) {
582      return db().find(type).apply(pathProperties);
583    }
584
585    /**
586     * Returns the next identity value.
587     * 
588     * @see EbeanServer#nextId(Class)
589     */
590    @SuppressWarnings("unchecked")
591    public I nextId() {
592      return (I) db().nextId(type);
593    }
594
595    /**
596     * Executes a query and returns the results as a list of IDs.
597     * <p>
598     * Equivalent to {@link Query#findIds()}
599     */
600    public List<Object> findIds() {
601      return query().findIds();
602    }
603
604    /**
605     * Execute the query consuming each bean one at a time.
606     * <p>
607     * This is generally used to process large queries where unlike findList
608     * you do not want to hold all the results in memory at once but instead
609     * process them one at a time (requiring far less memory).
610     * </p>
611     * Equivalent to {@link Query#findEach(QueryEachConsumer)}
612     */
613    public void findEach(QueryEachConsumer<T> consumer) {
614      query().findEach(consumer);
615    }
616
617    /**
618     * Execute the query consuming each bean one at a time.
619     * <p>
620     * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
621     * <p>
622     * This is similar to #findEach except that you return boolean
623     * true to continue processing beans and return false to stop
624     * processing early.
625     * </p>
626     * <p>
627     * This is generally used to process large queries where unlike findList
628     * you do not want to hold all the results in memory at once but instead
629     * process them one at a time (requiring far less memory).
630     * </p>
631     * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
632     */
633    public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
634      query().findEachWhile(consumer);
635    }
636
637    /**
638     * Retrieves all entities of the given type.
639     * <p>
640     * The same as {@link #all()}
641     * <p>
642     * Equivalent to {@link Query#findList()}
643     */
644    public List<T> findList() {
645      return query().findList();
646    }
647
648    /**
649     * Returns all the entities of the given type as a set.
650     * <p>
651     * Equivalent to {@link Query#findSet()}
652     */
653    public Set<T> findSet() {
654      return query().findSet();
655    }
656
657    /**
658     * Retrieves all entities of the given type as a map of objects.
659     * <p>
660     * Equivalent to {@link Query#findMap()}
661     */
662    public Map<?, T> findMap() {
663      return query().findMap();
664    }
665
666    /**
667     * Executes the query and returns the results as a map of the objects specifying the map key
668     * property.
669     * <p>
670     * Equivalent to {@link Query#findMap(String, Class)}
671     */
672    public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType) {
673      return query().findMap(keyProperty, keyType);
674    }
675
676    /**
677     * Return a PagedList of all entities of the given type (use where() to specify predicates as
678     * needed).
679     * <p>
680     * Equivalent to {@link Query#findPagedList(int, int)}
681     */
682    public PagedList<T> findPagedList(int pageIndex, int pageSize) {
683      return query().findPagedList(pageIndex, pageSize);
684    }
685
686    /**
687     * Executes a find row count query in a background thread.
688     * <p>
689     * Equivalent to {@link Query#findFutureRowCount()}
690     */
691    public FutureRowCount<T> findFutureRowCount() {
692      return query().findFutureRowCount();
693    }
694
695    /**
696     * Returns the total number of entities for this type. *
697     * <p>
698     * Equivalent to {@link Query#findRowCount()}
699     */
700    public int findRowCount() {
701      return query().findRowCount();
702    }
703
704    /**
705     * Returns the <code>ExpressionFactory</code> used by this query.
706     */
707    public ExpressionFactory getExpressionFactory() {
708      return query().getExpressionFactory();
709    }
710
711    /**
712     * Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean,
713     * to load a partial object.
714     * <p>
715     * Equivalent to {@link Query#select(String)}
716     */
717    public Query<T> select(String fetchProperties) {
718      return query().select(fetchProperties);
719    }
720
721    /**
722     * Specifies a path to load including all its properties.
723     * <p>
724     * Equivalent to {@link Query#fetch(String)}
725     */
726    public Query<T> fetch(String path) {
727      return query().fetch(path);
728    }
729
730    /**
731     * Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the
732     * lazy loading query.
733     * <p>
734     * Equivalent to {@link Query#fetch(String, FetchConfig)}
735     */
736    public Query<T> fetch(String path, FetchConfig joinConfig) {
737      return query().fetch(path, joinConfig);
738    }
739
740    /**
741     * Specifies a path to fetch with a specific list properties to include, to load a partial
742     * object.
743     * <p>
744     * Equivalent to {@link Query#fetch(String, String)}
745     */
746    public Query<T> fetch(String path, String fetchProperties) {
747      return query().fetch(path, fetchProperties);
748    }
749
750    /**
751     * Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to
752     * load this path.
753     * <p>
754     * Equivalent to {@link Query#fetch(String, String, FetchConfig)}
755     */
756    public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) {
757      return query().fetch(assocProperty, fetchProperties, fetchConfig);
758    }
759
760    /**
761     * Adds expressions to the <code>where</code> clause with the ability to chain on the
762     * <code>ExpressionList</code>.
763     * <p>
764     * Equivalent to {@link Query#where()}
765     */
766    public ExpressionList<T> where() {
767      return query().where();
768    }
769
770    /**
771     * Returns the <code>order by</code> clause so that you can append an ascending or descending
772     * property to the <code>order by</code> clause.
773     * <p>
774     * This is exactly the same as {@link #orderBy}.
775     * <p>
776     * Equivalent to {@link Query#order()}
777     */
778    public OrderBy<T> order() {
779      return query().order();
780    }
781
782    /**
783     * Sets the <code>order by</code> clause, replacing the existing <code>order by</code> clause if
784     * there is one.
785     * <p>
786     * This is exactly the same as {@link #orderBy(String)}.
787     */
788    public Query<T> order(String orderByClause) {
789      return query().order(orderByClause);
790    }
791
792    /**
793     * Returns the <code>order by</code> clause so that you can append an ascending or descending
794     * property to the <code>order by</code> clause.
795     * <p>
796     * This is exactly the same as {@link #order}.
797     * <p>
798     * Equivalent to {@link Query#orderBy()}
799     */
800    public OrderBy<T> orderBy() {
801      return query().orderBy();
802    }
803
804    /**
805     * Set the <code>order by</code> clause replacing the existing <code>order by</code> clause if
806     * there is one.
807     * <p>
808     * This is exactly the same as {@link #order(String)}.
809     */
810    public Query<T> orderBy(String orderByClause) {
811      return query().orderBy(orderByClause);
812    }
813
814    /**
815     * Sets the first row to return for this query.
816     * <p>
817     * Equivalent to {@link Query#setFirstRow(int)}
818     */
819    public Query<T> setFirstRow(int firstRow) {
820      return query().setFirstRow(firstRow);
821    }
822
823    /**
824     * Sets the maximum number of rows to return in the query.
825     * <p>
826     * Equivalent to {@link Query#setMaxRows(int)}
827     */
828    public Query<T> setMaxRows(int maxRows) {
829      return query().setMaxRows(maxRows);
830    }
831
832    /**
833     * Sets the ID value to query.
834     * 
835     * <p>
836     * Use this to perform a find byId query but with additional control over the query such as
837     * using select and fetch to control what parts of the object graph are returned.
838     * <p>
839     * Equivalent to {@link Query#setId(Object)}
840     */
841    public Query<T> setId(Object id) {
842      return query().setId(id);
843    }
844
845    /**
846     * Create and return a new query using the OQL.
847     * <p>
848     * Equivalent to {@link EbeanServer#createQuery(Class, String)}
849     */
850    public Query<T> setQuery(String oql) {
851      return db().createQuery(type, oql);
852    }
853
854    /**
855     * Create and return a new query based on the <code>RawSql</code>.
856     * <p>
857     * Equivalent to {@link Query#setRawSql(RawSql)}
858     */
859    public Query<T> setRawSql(RawSql rawSql) {
860      return query().setRawSql(rawSql);
861    }
862
863    /**
864     * Create a query with explicit 'AutoTune' use.
865     */
866    public Query<T> setAutoTune(boolean autoTune) {
867      return query().setAutoTune(autoTune);
868    }
869
870    /**
871     * Create a query with the select with "for update" specified.
872     * 
873     * <p>
874     * This will typically create row level database locks on the selected rows.
875     */
876    public Query<T> setForUpdate(boolean forUpdate) {
877      return query().setForUpdate(forUpdate);
878    }
879
880    /**
881     * Create a query specifying whether the returned beans will be read-only.
882     */
883    public Query<T> setReadOnly(boolean readOnly) {
884      return query().setReadOnly(readOnly);
885    }
886
887    /**
888     * Create a query specifying if the beans should be loaded into the L2 cache.
889     */
890    public Query<T> setLoadBeanCache(boolean loadBeanCache) {
891      return query().setLoadBeanCache(loadBeanCache);
892    }
893
894    /**
895     * Create a query specifying if the L2 bean cache should be used.
896     */
897    public Query<T> setUseCache(boolean useBeanCache) {
898      return query().setUseCache(useBeanCache);
899    }
900
901    /**
902     * Create a query specifying if the L2 query cache should be used.
903     */
904    public Query<T> setUseQueryCache(boolean useQueryCache) {
905      return query().setUseQueryCache(useQueryCache);
906    }
907
908  }
909}