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 bean.
255   * <p>
256   * This will return true if the bean was deleted successfully or JDBC batch is being used.
257   * </p>
258   * <p>
259   * If there is no current transaction one will be created and committed for
260   * you automatically.
261   * </p>
262   * <p>
263   * If the Bean does not have a version property (or loaded version property) and
264   * the bean does not exist then this returns false indicating that nothing was
265   * deleted. Note that, if JDBC batch mode is used then this always returns true.
266   * </p>
267   *
268   * @see EbeanServer#delete(Object)
269   */
270  public boolean delete() {
271    return db().delete(this);
272  }
273
274  /**
275   * Perform an update using this entity against the specified server.
276   */
277  public void update(String server) {
278    db(server).update(this);
279  }
280
281  /**
282   * Perform an insert using this entity against the specified server.
283   */
284  public void insert(String server) {
285    db(server).insert(this);
286  }
287
288  /**
289   * Perform a delete using this entity against the specified server.
290   */
291  public boolean delete(String server) {
292    return db(server).delete(this);
293  }
294
295  /**
296   * Refreshes this entity from the database.
297   *
298   * @see EbeanServer#refresh(Object)
299   */
300  public void refresh() {
301    db().refresh(this);
302  }
303
304  /**
305   * A concrete implementation of Find.
306   * <p>
307   * It should be preferred to use {@link Find} instead of Finder as that can use reflection to determine the class
308   * literal type of the entity bean.
309   * </p>
310   * @param <I> type of the Id property
311   * @param <T> type of the entity bean
312   */
313  public static class Finder<I, T> extends Find<I, T> {
314
315    /**
316     * Create with the type of the entity bean.
317     *
318     * <pre>{@code
319     *
320     * @Entity
321     * public class Customer extends BaseModel {
322     *
323     *   public static final Finder<Long,Customer> find = new Finder<Long,Customer>(Customer.class);
324     *   ...
325     *
326     * }</pre>
327     *
328     * <p/>
329     * The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does
330     * not require the class literal Customer.class to be passed into the constructor.
331     *
332     * <pre>{@code
333     *
334     * @Entity
335     * public class Customer extends BaseModel {
336     *
337     *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
338     *   ...
339     *
340     * }</pre>
341     */
342    public Finder(Class<T> type) {
343      super(null, type);
344    }
345
346    /**
347     * Create with the type of the entity bean and specific server name.
348     */
349    public Finder(String serverName, Class<T> type) {
350      super(serverName, type);
351    }
352
353    /**
354     * Please migrate to use {@link Find} or constructor <code>Finder(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(Class<I> idType, Class<T> type) {
362      super(null, type);
363    }
364
365    /**
366     * Please migrate to use the constructor <code>Finder(String, Class)</code> that
367     * does not have the idType parameter.
368     * <p/>
369     * Create with the type of the ID property and entity bean and specific server name.
370     *
371     * @deprecated
372     */
373    public Finder(String serverName, Class<I> idType, Class<T> type) {
374      super(serverName, type);
375    }
376  }
377
378  /**
379   * Helper object for performing queries.
380   * 
381   * <p>
382   * Typically a Find instance is defined as a public static field on an entity bean class to provide a
383   * nice way to write queries.
384   *
385   * <h3>Example use:</h3>
386   *
387   * <pre>{@code
388   *
389   * @Entity
390   * public class Customer extends BaseModel {
391   *
392   *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
393   *
394   *   ...
395   *
396   * }</pre>
397   * <p/>
398   * This enables you to write code like:
399   * <pre>{@code
400   *
401   * Customer customer = Customer.find.byId(42L);
402   *
403   * List<Customer> customers =
404   *     Customer.find
405   *         .select("name, dateOfBirth")
406   *         .findList();
407   *
408   * }</pre>
409   *
410   * <h3>Kotlin</h3>
411   * In Kotlin you would typically create Find as a companion object.
412   * <pre>{@code
413   *
414   *   // kotlin
415   *   companion object : Model.Find<Long, Product>() {}
416   *
417   * }</pre>
418   * @param <I>
419   *          The Id type. This is most often a {@link Long} but is also often a {@link UUID} or
420   *          {@link String}.
421   *
422   * @param <T>
423   *          The entity bean type
424   */
425  public static abstract class Find<I, T> {
426
427    /**
428     * The entity bean type.
429     */
430    private final Class<T> type;
431
432    /**
433     * The name of the EbeanServer, null for the default server.
434     */
435    private final String serverName;
436
437    /**
438     * Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>.
439     * <p/>
440     * Typically you create Find as a public static field on each entity bean as the example below.
441     *
442     * <p/>
443     * Note that Find is an abstract class and hence <code>{}</code> is required. This is done so
444     * that the type (class literal) of the entity bean can be derived from the generics parameter.
445     *
446     * <pre>{@code
447     *
448     * @Entity
449     * public class Customer extends BaseModel {
450     *
451     *   // Note the trailing {} as Find is an abstract class.
452     *   // We do this so that we can derive the type literal Customer.class
453     *   // via reflection
454     *   public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
455     *   ...
456     *
457     * }</pre>
458     * <p/>
459     * This enables you to write code like:
460     * <pre>{@code
461     *
462     * Customer customer = Customer.find.byId(42L);
463     *
464     * List<Customer> customers =
465     *     Customer.find
466     *        .select("name, email, dateOfBirth")
467     *        .findList();
468     *
469     * }</pre>
470     *
471     * <h3>Kotlin</h3>
472     * In Kotlin you would typically create it as a companion object.
473     *
474     * <pre>{@code
475     *
476     *   // kotlin
477     *   companion object : Model.Find<Long, Product>() {}
478     *
479     * }</pre>
480     */
481    @SuppressWarnings("unchecked")
482    public Find() {
483      this.serverName = null;
484      this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
485    }
486
487    /**
488     * Construct passing the class literal type of the entity type.
489     */
490    protected Find(String serverName, Class<T> type) {
491      this.serverName = serverName;
492      this.type = type;
493    }
494
495    /**
496     * Return the underlying 'default' EbeanServer.
497     * 
498     * <p>
499     * This provides full access to the API such as explicit transaction demarcation etc.
500     * 
501     */
502    public EbeanServer db() {
503      return Ebean.getServer(serverName);
504    }
505
506    /**
507     * Return typically a different EbeanServer to the default.
508     * <p>
509     * This is equivilent to {@link Ebean#getServer(String)}
510     * 
511     * @param server
512     *          The name of the EbeanServer. If this is null then the default EbeanServer is
513     *          returned.
514     */
515    public EbeanServer db(String server) {
516      return Ebean.getServer(server);
517    }
518
519    /**
520     * Creates a Finder for the named EbeanServer.
521     *
522     * <p>
523     * Create and return a new Finder for a different server.
524     */
525    public Finder<I, T> on(String server) {
526      return new Finder<I, T>(server, type);
527    }
528
529    /**
530     * Delete a bean by Id.
531     * <p>
532     * Equivalent to {@link EbeanServer#delete(Class, Object)}
533     */
534    public void deleteById(I id) {
535      db().delete(type, id);
536    }
537
538    /**
539     * Retrieves all entities of the given type.
540     * 
541     * <p>
542     * This is the same as (synonym for) {@link #findList()}
543     */
544    public List<T> all() {
545      return findList();
546    }
547
548    /**
549     * Retrieves an entity by ID.
550     * 
551     * <p>
552     * Equivalent to {@link EbeanServer#find(Class, Object)}
553     */
554    @Nullable
555    public T byId(I id) {
556      return db().find(type, id);
557    }
558
559    /**
560     * Creates an entity reference for this ID.
561     * 
562     * <p>
563     * Equivalent to {@link EbeanServer#getReference(Class, Object)}
564     */
565    public T ref(I id) {
566      return db().getReference(type, id);
567    }
568
569    /**
570     * Creates a filter for sorting and filtering lists of entities locally without going back to
571     * the database.
572     * <p>
573     * Equivalent to {@link EbeanServer#filter(Class)}
574     */
575    public Filter<T> filter() {
576      return db().filter(type);
577    }
578
579    /**
580     * Creates a query.
581     * <p>
582     * Equivalent to {@link EbeanServer#find(Class)}
583     */
584    public Query<T> query() {
585      return db().find(type);
586    }
587
588    /**
589     * Creates a query applying the path properties to set the select and fetch clauses.
590     * <p>
591     * Equivalent to {@link Query#apply(com.avaje.ebean.text.PathProperties)}
592     */
593    public Query<T> apply(PathProperties pathProperties) {
594      return db().find(type).apply(pathProperties);
595    }
596
597    /**
598     * Returns the next identity value.
599     * 
600     * @see EbeanServer#nextId(Class)
601     */
602    @SuppressWarnings("unchecked")
603    public I nextId() {
604      return (I) db().nextId(type);
605    }
606
607    /**
608     * Executes a query and returns the results as a list of IDs.
609     * <p>
610     * Equivalent to {@link Query#findIds()}
611     */
612    public List<Object> findIds() {
613      return query().findIds();
614    }
615
616    /**
617     * Execute the query consuming each bean one at a time.
618     * <p>
619     * This is generally used to process large queries where unlike findList
620     * you do not want to hold all the results in memory at once but instead
621     * process them one at a time (requiring far less memory).
622     * </p>
623     * Equivalent to {@link Query#findEach(QueryEachConsumer)}
624     */
625    public void findEach(QueryEachConsumer<T> consumer) {
626      query().findEach(consumer);
627    }
628
629    /**
630     * Execute the query consuming each bean one at a time.
631     * <p>
632     * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
633     * <p>
634     * This is similar to #findEach except that you return boolean
635     * true to continue processing beans and return false to stop
636     * processing early.
637     * </p>
638     * <p>
639     * This is generally used to process large queries where unlike findList
640     * you do not want to hold all the results in memory at once but instead
641     * process them one at a time (requiring far less memory).
642     * </p>
643     * Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
644     */
645    public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
646      query().findEachWhile(consumer);
647    }
648
649    /**
650     * Retrieves all entities of the given type.
651     * <p>
652     * The same as {@link #all()}
653     * <p>
654     * Equivalent to {@link Query#findList()}
655     */
656    public List<T> findList() {
657      return query().findList();
658    }
659
660    /**
661     * Returns all the entities of the given type as a set.
662     * <p>
663     * Equivalent to {@link Query#findSet()}
664     */
665    public Set<T> findSet() {
666      return query().findSet();
667    }
668
669    /**
670     * Retrieves all entities of the given type as a map of objects.
671     * <p>
672     * Equivalent to {@link Query#findMap()}
673     */
674    public Map<?, T> findMap() {
675      return query().findMap();
676    }
677
678    /**
679     * Executes the query and returns the results as a map of the objects specifying the map key
680     * property.
681     * <p>
682     * Equivalent to {@link Query#findMap(String, Class)}
683     */
684    public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType) {
685      return query().findMap(keyProperty, keyType);
686    }
687
688    /**
689     * Return a PagedList of all entities of the given type (use where() to specify predicates as
690     * needed).
691     * <p>
692     * Equivalent to {@link Query#findPagedList(int, int)}
693     */
694    public PagedList<T> findPagedList(int pageIndex, int pageSize) {
695      return query().findPagedList(pageIndex, pageSize);
696    }
697
698    /**
699     * Executes a find row count query in a background thread.
700     * <p>
701     * Equivalent to {@link Query#findFutureRowCount()}
702     */
703    public FutureRowCount<T> findFutureRowCount() {
704      return query().findFutureRowCount();
705    }
706
707    /**
708     * Returns the total number of entities for this type. *
709     * <p>
710     * Equivalent to {@link Query#findRowCount()}
711     */
712    public int findRowCount() {
713      return query().findRowCount();
714    }
715
716    /**
717     * Returns the <code>ExpressionFactory</code> used by this query.
718     */
719    public ExpressionFactory getExpressionFactory() {
720      return query().getExpressionFactory();
721    }
722
723    /**
724     * Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean,
725     * to load a partial object.
726     * <p>
727     * Equivalent to {@link Query#select(String)}
728     */
729    public Query<T> select(String fetchProperties) {
730      return query().select(fetchProperties);
731    }
732
733    /**
734     * Specifies a path to load including all its properties.
735     * <p>
736     * Equivalent to {@link Query#fetch(String)}
737     */
738    public Query<T> fetch(String path) {
739      return query().fetch(path);
740    }
741
742    /**
743     * Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the
744     * lazy loading query.
745     * <p>
746     * Equivalent to {@link Query#fetch(String, FetchConfig)}
747     */
748    public Query<T> fetch(String path, FetchConfig joinConfig) {
749      return query().fetch(path, joinConfig);
750    }
751
752    /**
753     * Specifies a path to fetch with a specific list properties to include, to load a partial
754     * object.
755     * <p>
756     * Equivalent to {@link Query#fetch(String, String)}
757     */
758    public Query<T> fetch(String path, String fetchProperties) {
759      return query().fetch(path, fetchProperties);
760    }
761
762    /**
763     * Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to
764     * load this path.
765     * <p>
766     * Equivalent to {@link Query#fetch(String, String, FetchConfig)}
767     */
768    public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) {
769      return query().fetch(assocProperty, fetchProperties, fetchConfig);
770    }
771
772    /**
773     * Adds expressions to the <code>where</code> clause with the ability to chain on the
774     * <code>ExpressionList</code>.
775     * <p>
776     * Equivalent to {@link Query#where()}
777     */
778    public ExpressionList<T> where() {
779      return query().where();
780    }
781
782    /**
783     * Returns the <code>order by</code> clause so that you can append an ascending or descending
784     * property to the <code>order by</code> clause.
785     * <p>
786     * This is exactly the same as {@link #orderBy}.
787     * <p>
788     * Equivalent to {@link Query#order()}
789     */
790    public OrderBy<T> order() {
791      return query().order();
792    }
793
794    /**
795     * Sets the <code>order by</code> clause, replacing the existing <code>order by</code> clause if
796     * there is one.
797     * <p>
798     * This is exactly the same as {@link #orderBy(String)}.
799     */
800    public Query<T> order(String orderByClause) {
801      return query().order(orderByClause);
802    }
803
804    /**
805     * Returns the <code>order by</code> clause so that you can append an ascending or descending
806     * property to the <code>order by</code> clause.
807     * <p>
808     * This is exactly the same as {@link #order}.
809     * <p>
810     * Equivalent to {@link Query#orderBy()}
811     */
812    public OrderBy<T> orderBy() {
813      return query().orderBy();
814    }
815
816    /**
817     * Set the <code>order by</code> clause replacing the existing <code>order by</code> clause if
818     * there is one.
819     * <p>
820     * This is exactly the same as {@link #order(String)}.
821     */
822    public Query<T> orderBy(String orderByClause) {
823      return query().orderBy(orderByClause);
824    }
825
826    /**
827     * Sets the first row to return for this query.
828     * <p>
829     * Equivalent to {@link Query#setFirstRow(int)}
830     */
831    public Query<T> setFirstRow(int firstRow) {
832      return query().setFirstRow(firstRow);
833    }
834
835    /**
836     * Sets the maximum number of rows to return in the query.
837     * <p>
838     * Equivalent to {@link Query#setMaxRows(int)}
839     */
840    public Query<T> setMaxRows(int maxRows) {
841      return query().setMaxRows(maxRows);
842    }
843
844    /**
845     * Sets the ID value to query.
846     * 
847     * <p>
848     * Use this to perform a find byId query but with additional control over the query such as
849     * using select and fetch to control what parts of the object graph are returned.
850     * <p>
851     * Equivalent to {@link Query#setId(Object)}
852     */
853    public Query<T> setId(Object id) {
854      return query().setId(id);
855    }
856
857    /**
858     * Create and return a new query using the OQL.
859     * <p>
860     * Equivalent to {@link EbeanServer#createQuery(Class, String)}
861     */
862    public Query<T> setQuery(String oql) {
863      return db().createQuery(type, oql);
864    }
865
866    /**
867     * Create and return a new query based on the <code>RawSql</code>.
868     * <p>
869     * Equivalent to {@link Query#setRawSql(RawSql)}
870     */
871    public Query<T> setRawSql(RawSql rawSql) {
872      return query().setRawSql(rawSql);
873    }
874
875    /**
876     * Create a query with explicit 'AutoTune' use.
877     */
878    public Query<T> setAutoTune(boolean autoTune) {
879      return query().setAutoTune(autoTune);
880    }
881
882    /**
883     * Create a query with the select with "for update" specified.
884     * 
885     * <p>
886     * This will typically create row level database locks on the selected rows.
887     */
888    public Query<T> setForUpdate(boolean forUpdate) {
889      return query().setForUpdate(forUpdate);
890    }
891
892    /**
893     * Create a query specifying whether the returned beans will be read-only.
894     */
895    public Query<T> setReadOnly(boolean readOnly) {
896      return query().setReadOnly(readOnly);
897    }
898
899    /**
900     * Create a query specifying if the beans should be loaded into the L2 cache.
901     */
902    public Query<T> setLoadBeanCache(boolean loadBeanCache) {
903      return query().setLoadBeanCache(loadBeanCache);
904    }
905
906    /**
907     * Create a query specifying if the L2 bean cache should be used.
908     */
909    public Query<T> setUseCache(boolean useBeanCache) {
910      return query().setUseCache(useBeanCache);
911    }
912
913    /**
914     * Create a query specifying if the L2 query cache should be used.
915     */
916    public Query<T> setUseQueryCache(boolean useQueryCache) {
917      return query().setUseQueryCache(useQueryCache);
918    }
919
920  }
921}