001package io.ebean;
002
003import io.ebean.annotation.Platform;
004import io.ebean.annotation.TxIsolation;
005import io.ebean.cache.ServerCacheManager;
006import io.ebean.config.DatabaseConfig;
007import io.ebean.meta.MetaInfoManager;
008import io.ebean.plugin.Property;
009import io.ebean.plugin.SpiServer;
010import io.ebean.text.csv.CsvReader;
011import io.ebean.text.json.JsonContext;
012
013import javax.annotation.Nonnull;
014import javax.annotation.Nullable;
015import javax.persistence.OptimisticLockException;
016import javax.persistence.PersistenceException;
017import java.util.Collection;
018import java.util.List;
019import java.util.Map;
020import java.util.Set;
021import java.util.concurrent.Callable;
022
023/**
024 * Provides the API for fetching and saving beans to a particular database.
025 *
026 * <h5>Registration with the DB singleton</h5>
027 * <p>
028 * When a Database instance is created it can be registered with the DB
029 * singleton (see {@link DatabaseConfig#setRegister(boolean)}). The DB
030 * singleton is essentially a map of Database's that have been registered
031 * with it.
032 * </p>
033 * <p>
034 * The Database can then be retrieved later via {@link DB#byName(String)}.
035 * </p>
036 *
037 * <h5>The 'default' Database</h5>
038 * <p>
039 * One Database can be designated as the 'default' or 'primary' Database
040 * (see {@link DatabaseConfig#setDefaultServer(boolean)}. Many methods on DB
041 * such as {@link DB#find(Class)} etc are actually just a convenient way to
042 * call methods on the 'default/primary' Database.
043 * </p>
044 *
045 * <h5>Constructing a Database</h5>
046 * <p>
047 * Database's are constructed by the DatabaseFactory. They can be created
048 * programmatically via {@link DatabaseFactory#create(DatabaseConfig)} or they
049 * can be automatically constructed on demand using configuration information in
050 * the application.properties file.
051 * </p>
052 *
053 * <h5>Example: Get a Database</h5>
054 * <p>
055 * <pre>{@code
056 *
057 *   // Get access to the Human Resources Database
058 *   Database hrDatabase = DB.byName("hr");
059 *
060 *
061 *   // fetch contact 3 from the HR database
062 *   Contact contact = hrDatabase.find(Contact.class, new Integer(3));
063 *
064 *   contact.setStatus("INACTIVE"); ...
065 *
066 *   // save the contact back to the HR database
067 *   hrDatabase.save(contact);
068 *
069 * }</pre>
070 *
071 * <h5>Database vs DB API</h5>
072 * <p>
073 * Database provides additional API compared with DB. For example it
074 * provides more control over the use of Transactions that is not available in
075 * the DB API.
076 * </p>
077 *
078 * <p>
079 * <em>External Transactions:</em> If you wanted to use transactions created
080 * externally to Ebean then Database provides additional methods where you
081 * can explicitly pass a transaction (that can be created externally).
082 * </p>
083 *
084 * <p>
085 * <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built in
086 * ThreadLocal transaction management you can use the createTransaction()
087 * method. Example: a single thread requires more than one transaction.
088 * </p>
089 *
090 * @see DB
091 * @see DatabaseFactory
092 * @see DatabaseConfig
093 */
094public interface Database {
095
096  /**
097   * Shutdown the Database instance.
098   */
099  void shutdown();
100
101  /**
102   * Shutdown the Database instance programmatically.
103   * <p>
104   * This method is not normally required. Ebean registers a shutdown hook and shuts down cleanly.
105   * </p>
106   * <p>
107   * If the under underlying DataSource is the Ebean implementation then you
108   * also have the option of shutting down the DataSource and deregistering the
109   * JDBC driver.
110   * </p>
111   *
112   * @param shutdownDataSource if true then shutdown the underlying DataSource if it is the Ebean
113   *                           DataSource implementation.
114   * @param deregisterDriver   if true then deregister the JDBC driver if it is the Ebean
115   *                           DataSource implementation.
116   */
117  void shutdown(boolean shutdownDataSource, boolean deregisterDriver);
118
119  /**
120   * Return AutoTune which is used to control the AutoTune service at runtime.
121   */
122  AutoTune getAutoTune();
123
124  /**
125   * Return the name. This is used with {@link DB#byName(String)} to get a
126   * Database that was registered with the DB singleton.
127   */
128  String getName();
129
130  /**
131   * Return the ExpressionFactory for this database.
132   */
133  ExpressionFactory getExpressionFactory();
134
135  /**
136   * Return the MetaInfoManager which is used to get meta data from the Database
137   * such as query execution statistics.
138   */
139  MetaInfoManager getMetaInfoManager();
140
141  /**
142   * Return the platform used for this database instance.
143   * <p>
144   * Note many platforms have multiple specific platform types so often we want to
145   * get the base platform via {@link Platform#base()}.
146   * </p>
147   * <pre>{@code
148   *
149   *  Platform platform = database.getPlatform().base();
150   *  if (platform == Platform.MYSQL) {
151   *    // do MySql specific function
152   *  }
153   *
154   * }</pre>
155   *
156   * @return platform for this database instance
157   */
158  Platform getPlatform();
159
160  /**
161   * Return the extended API intended for use by plugins.
162   */
163  SpiServer getPluginApi();
164
165  /**
166   * Return the BeanState for a given entity bean.
167   * <p>
168   * This will return null if the bean is not an enhanced entity bean.
169   * </p>
170   */
171  BeanState getBeanState(Object bean);
172
173  /**
174   * Return the value of the Id property for a given bean.
175   */
176  Object getBeanId(Object bean);
177
178  /**
179   * Set the Id value onto the bean converting the type of the id value if necessary.
180   * <p>
181   * For example, if the id value passed in is a String but ought to be a Long or UUID etc
182   * then it will automatically be converted.
183   * </p>
184   *
185   * @param bean The entity bean to set the id value on.
186   * @param id   The id value to set.
187   */
188  Object setBeanId(Object bean, Object id);
189
190  /**
191   * Return a map of the differences between two objects of the same type.
192   * <p>
193   * When null is passed in for b, then the 'OldValues' of a is used for the
194   * difference comparison.
195   * </p>
196   */
197  Map<String, ValuePair> diff(Object newBean, Object oldBean);
198
199  /**
200   * Create a new instance of T that is an EntityBean.
201   * <p>
202   * Useful if you use BeanPostConstructListeners or &#64;PostConstruct Annotations.
203   * In this case you should not use "new Bean...()". Making all bean construtors protected
204   * could be a good idea here.
205   * </p>
206   */
207  <T> T createEntityBean(Class<T> type);
208
209  /**
210   * Create a CsvReader for a given beanType.
211   */
212  <T> CsvReader<T> createCsvReader(Class<T> beanType);
213
214  /**
215   * Create an Update query to perform a bulk update.
216   * <p>
217   * <pre>{@code
218   *
219   *  int rows = database
220   *      .update(Customer.class)
221   *      .set("status", Customer.Status.ACTIVE)
222   *      .set("updtime", new Timestamp(System.currentTimeMillis()))
223   *      .where()
224   *        .gt("id", 1000)
225   *        .update();
226   *
227   * }</pre>
228   *
229   * @param beanType The type of entity bean to update
230   * @param <T>      The type of entity bean
231   * @return The update query to use
232   */
233  <T> UpdateQuery<T> update(Class<T> beanType);
234
235  /**
236   * Create a named query.
237   * <p>
238   * For RawSql the named query is expected to be in ebean.xml.
239   * </p>
240   *
241   * @param beanType   The type of entity bean
242   * @param namedQuery The name of the query
243   * @param <T>        The type of entity bean
244   * @return The query
245   */
246  <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
247
248  /**
249   * Create a query for an entity bean and synonym for {@link #find(Class)}.
250   *
251   * @see #find(Class)
252   */
253  <T> Query<T> createQuery(Class<T> beanType);
254
255  /**
256   * Parse the Ebean query language statement returning the query which can then
257   * be modified (add expressions, change order by clause, change maxRows, change
258   * fetch and select paths etc).
259   * <p>
260   * <h3>Example</h3>
261   * <pre>{@code
262   *
263   *   // Find order additionally fetching the customer, details and details.product name.
264   *
265   *   String ormQuery = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
266   *
267   *   Query<Order> query = DB.createQuery(Order.class, ormQuery);
268   *   query.setParameter("orderId", 2);
269   *
270   *   Order order = query.findOne();
271   *
272   *   // This is the same as:
273   *
274   *   Order order = DB.find(Order.class)
275   *     .fetch("customer")
276   *     .fetch("details")
277   *     .fetch("detail.product", "name")
278   *     .setId(2)
279   *     .findOne();
280   *
281   * }</pre>
282   *
283   * @param beanType The type of bean to fetch
284   * @param ormQuery The Ebean ORM query
285   * @param <T>      The type of the entity bean
286   * @return The query with expressions defined as per the parsed query statement
287   */
288  <T> Query<T> createQuery(Class<T> beanType, String ormQuery);
289
290  /**
291   * Create a query for a type of entity bean.
292   * <p>
293   * You can use the methods on the Query object to specify fetch paths,
294   * predicates, order by, limits etc.
295   * </p>
296   * <p>
297   * You then use findList(), findSet(), findMap() and findOne() to execute
298   * the query and return the collection or bean.
299   * </p>
300   * <p>
301   * Note that a query executed by {@link Query#findList()}
302   * {@link Query#findSet()} etc will execute against the same Database from
303   * which is was created.
304   * </p>
305   * <p>
306   * <pre>{@code
307   *
308   *   // Find order 2 specifying explicitly the parts of the object graph to
309   *   // eagerly fetch. In this case eagerly fetch the associated customer,
310   *   // details and details.product.name
311   *
312   *   Order order = database.find(Order.class)
313   *     .fetch("customer")
314   *     .fetch("details")
315   *     .fetch("detail.product", "name")
316   *     .setId(2)
317   *     .findOne();
318   *
319   *   // find some new orders ... with firstRow/maxRows
320   *   List<Order> orders =
321   *     database.find(Order.class)
322   *       .where().eq("status", Order.Status.NEW)
323   *       .setFirstRow(20)
324   *       .setMaxRows(10)
325   *       .findList();
326   *
327   * }</pre>
328   */
329  <T> Query<T> find(Class<T> beanType);
330
331  /**
332   * Create a query using native SQL.
333   * <p>
334   * The native SQL can contain named parameters or positioned parameters.
335   * </p>
336   * <pre>{@code
337   *
338   *   String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
339   *
340   *   Query<Customer> query = database.findNative(Customer.class, sql);
341   *   query.setParameter(1, "Rob%");
342   *
343   *   List<Customer> customers = query.findList();
344   *
345   * }</pre>
346   *
347   * @param beanType  The type of entity bean to fetch
348   * @param nativeSql The SQL that can contain named or positioned parameters
349   * @return The query to set parameters and execute
350   */
351  <T> Query<T> findNative(Class<T> beanType, String nativeSql);
352
353  /**
354   * Return the next unique identity value for a given bean type.
355   * <p>
356   * This will only work when a IdGenerator is on the bean such as for beans
357   * that use a DB sequence or UUID.
358   * </p>
359   * <p>
360   * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do
361   * not need to use this method generally. It is made available for more
362   * complex cases where it is useful to get an ID prior to some processing.
363   * </p>
364   */
365  Object nextId(Class<?> beanType);
366
367  /**
368   * Create a filter for sorting and filtering lists of entities locally without
369   * going back to the database.
370   * <p>
371   * This produces and returns a new list with the sort and filters applied.
372   * </p>
373   * <p>
374   * Refer to {@link Filter} for an example of its use.
375   * </p>
376   */
377  <T> Filter<T> filter(Class<T> beanType);
378
379  /**
380   * Sort the list in memory using the sortByClause which can contain a comma delimited
381   * list of property names and keywords asc, desc, nullsHigh and nullsLow.
382   * <ul>
383   * <li>asc - ascending order (which is the default)</li>
384   * <li>desc - Descending order</li>
385   * <li>nullsHigh - Treat null values as high/large values (which is the
386   * default)</li>
387   * <li>nullsLow- Treat null values as low/very small values</li>
388   * </ul>
389   * <p>
390   * If you leave off any keywords the defaults are ascending order and treating
391   * nulls as high values.
392   * </p>
393   * <p>
394   * Note that the sorting uses a Comparator and Collections.sort(); and does
395   * not invoke a DB query.
396   * </p>
397   * <p>
398   * <pre>{@code
399   *
400   *   // find orders and their customers
401   *   List<Order> list = database.find(Order.class)
402   *     .fetch("customer")
403   *     .order("id")
404   *     .findList();
405   *
406   *   // sort by customer name ascending, then by order shipDate
407   *   // ... then by the order status descending
408   *   database.sort(list, "customer.name, shipDate, status desc");
409   *
410   *   // sort by customer name descending (with nulls low)
411   *   // ... then by the order id
412   *   database.sort(list, "customer.name desc nullsLow, id");
413   *
414   * }</pre>
415   *
416   * @param list         the list of entity beans
417   * @param sortByClause the properties to sort the list by
418   */
419  <T> void sort(List<T> list, String sortByClause);
420
421  /**
422   * Create a orm update where you will supply the insert/update or delete
423   * statement (rather than using a named one that is already defined using the
424   * &#064;NamedUpdates annotation).
425   * <p>
426   * The orm update differs from the sql update in that it you can use the bean
427   * name and bean property names rather than table and column names.
428   * </p>
429   * <p>
430   * An example:
431   * </p>
432   * <p>
433   * <pre>{@code
434   *
435   *   // The bean name and properties - "topic","postCount" and "id"
436   *
437   *   // will be converted into their associated table and column names
438   *   String updStatement = "update topic set postCount = :pc where id = :id";
439   *
440   *   Update<Topic> update = database.createUpdate(Topic.class, updStatement);
441   *
442   *   update.set("pc", 9);
443   *   update.set("id", 3);
444   *
445   *   int rows = update.execute();
446   *   System.out.println("rows updated:" + rows);
447   *
448   * }</pre>
449   */
450  <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate);
451
452  /**
453   * Create a Query for DTO beans.
454   * <p>
455   * DTO beans are just normal bean like classes with public constructor(s) and setters.
456   * They do not need to be registered with DB before use.
457   * </p>
458   *
459   * @param dtoType The type of the DTO bean the rows will be mapped into.
460   * @param sql     The SQL query to execute.
461   * @param <T>     The type of the DTO bean.
462   */
463  <T> DtoQuery<T> findDto(Class<T> dtoType, String sql);
464
465  /**
466   * Create a named Query for DTO beans.
467   * <p>
468   * DTO beans are just normal bean like classes with public constructor(s) and setters.
469   * They do not need to be registered with DB before use.
470   * </p>
471   *
472   * @param dtoType    The type of the DTO bean the rows will be mapped into.
473   * @param namedQuery The name of the query
474   * @param <T>        The type of the DTO bean.
475   */
476  <T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery);
477
478  /**
479   * Look to execute a native sql query that does not returns beans but instead
480   * returns SqlRow or direct access to ResultSet (see {@link SqlQuery#findList(RowMapper)}.
481   *
482   * <p>
483   * Refer to {@link DtoQuery} for native sql queries returning DTO beans.
484   * </p>
485   * <p>
486   * Refer to {@link #findNative(Class, String)} for native sql queries returning entity beans.
487   * </p>
488   */
489  SqlQuery sqlQuery(String sql);
490
491  /**
492   * Deprecated - migrate to sqlQuery().
493   * <p>
494   * This is an alias for {@link #sqlQuery(String)}.
495   */
496  @Deprecated
497  SqlQuery createSqlQuery(String sql);
498
499  /**
500   * Look to execute a native sql insert update or delete statement.
501   * <p>
502   * Use this to execute a Insert Update or Delete statement. The statement will
503   * be native to the database and contain database table and column names.
504   * </p>
505   *
506   * <p>
507   * See {@link SqlUpdate} for example usage.
508   * </p>
509   *
510   * @return The SqlUpdate instance to set parameters and execute
511   */
512  SqlUpdate sqlUpdate(String sql);
513
514  /**
515   * Deprecated - migrate to sqlUpdate().
516   * <p>
517   * This is an alias for {@link #sqlUpdate(String)}.
518   */
519  @Deprecated
520  SqlUpdate createSqlUpdate(String sql);
521
522  /**
523   * Create a CallableSql to execute a given stored procedure.
524   */
525  CallableSql createCallableSql(String callableSql);
526
527  /**
528   * Register a TransactionCallback on the currently active transaction.
529   * <p/>
530   * If there is no currently active transaction then a PersistenceException is thrown.
531   *
532   * @param transactionCallback The transaction callback to be registered with the current transaction.
533   * @throws PersistenceException If there is no currently active transaction
534   */
535  void register(TransactionCallback transactionCallback) throws PersistenceException;
536
537  /**
538   * Create a new transaction that is not held in TransactionThreadLocal.
539   * <p>
540   * You will want to do this if you want multiple Transactions in a single
541   * thread or generally use transactions outside of the TransactionThreadLocal
542   * management.
543   * </p>
544   */
545  Transaction createTransaction();
546
547  /**
548   * Create a new transaction additionally specifying the isolation level.
549   * <p>
550   * Note that this transaction is NOT stored in a thread local.
551   * </p>
552   */
553  Transaction createTransaction(TxIsolation isolation);
554
555  /**
556   * Start a transaction with 'REQUIRED' semantics.
557   * <p>
558   * With REQUIRED semantics if an active transaction already exists that transaction will be used.
559   * </p>
560   * <p>
561   * The transaction is stored in a ThreadLocal variable and typically you only
562   * need to use the returned Transaction <em>IF</em> you wish to do things like
563   * use batch mode, change the transaction isolation level, use savepoints or
564   * log comments to the transaction log.
565   * </p>
566   * <p>
567   * Example of using a transaction to span multiple calls to find(), save()
568   * etc.
569   * </p>
570   * <p>
571   * <h3>Using try with resources</h3>
572   * <pre>{@code
573   *
574   *    // start a transaction (stored in a ThreadLocal)
575   *
576   *    try (Transaction txn = database.beginTransaction()) {
577   *
578   *        Order order = database.find(Order.class, 10);
579   *        ...
580   *        database.save(order);
581   *
582   *        txn.commit();
583   *    }
584   *
585   * }</pre>
586   * <p>
587   * <h3>Using try finally block</h3>
588   * <pre>{@code
589   *
590   *    // start a transaction (stored in a ThreadLocal)
591   *    Transaction txn = database.beginTransaction();
592   *    try {
593   *        Order order = database.find(Order.class,10);
594   *
595   *        database.save(order);
596   *
597   *        txn.commit();
598   *
599   *    } finally {
600   *        txn.end();
601   *    }
602   *
603   * }</pre>
604   * <p>
605   * <h3>Transaction options</h3>
606   * <pre>{@code
607   *
608   *     try (Transaction txn = database.beginTransaction()) {
609   *
610   *       // explicitly turn on/off JDBC batch use
611   *       txn.setBatchMode(true);
612   *       txn.setBatchSize(50);
613   *
614   *       // control flushing when mixing save and queries
615   *       txn.setBatchFlushOnQuery(false);
616   *
617   *       // turn off persist cascade if needed
618   *       txn.setPersistCascade(false);
619   *
620   *       // for large batch insert processing when we do not
621   *       // ... need the generatedKeys, don't get them
622   *       txn.setBatchGetGeneratedKeys(false);
623   *
624   *       // explicitly flush the JDBC batch buffer
625   *       txn.flush();
626   *
627   *       ...
628   *
629   *       txn.commit();
630   *    }
631   *
632   * }</pre>
633   * <p>
634   * <p>
635   * If you want to externalise the transaction management then you use
636   * createTransaction() and pass the transaction around to the various methods on
637   * Database yourself.
638   * </p>
639   */
640  Transaction beginTransaction();
641
642  /**
643   * Start a transaction additionally specifying the isolation level.
644   */
645  Transaction beginTransaction(TxIsolation isolation);
646
647  /**
648   * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
649   * <p>
650   * <p>
651   * Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or
652   * {@link #execute(TxScope, Runnable)}.
653   * </p>
654   * <p>
655   * <h3>REQUIRES_NEW example:</h3>
656   * <pre>{@code
657   * // Start a new transaction. If there is a current transaction
658   * // suspend it until this transaction ends
659   * try (Transaction txn = database.beginTransaction(TxScope.requiresNew())) {
660   *
661   *   ...
662   *
663   *   // commit the transaction
664   *   txn.commit();
665   *
666   *   // At end this transaction will:
667   *   //  A) will rollback transaction if it has not been committed
668   *   //  B) will restore a previously suspended transaction
669   * }
670   *
671   * }</pre>
672   * <p>
673   * <h3>REQUIRED example:</h3>
674   * <pre>{@code
675   *
676   * // start a new transaction if there is not a current transaction
677   * try (Transaction txn = database.beginTransaction(TxScope.required())) {
678   *
679   *   ...
680   *
681   *   // commit the transaction if it was created or
682   *   // do nothing if there was already a current transaction
683   *   txn.commit();
684   * }
685   *
686   * }</pre>
687   */
688  Transaction beginTransaction(TxScope scope);
689
690  /**
691   * Returns the current transaction or null if there is no current transaction in scope.
692   */
693  Transaction currentTransaction();
694
695  /**
696   * Flush the JDBC batch on the current transaction.
697   * <p>
698   * This only is useful when JDBC batch is used. Flush occurs automatically when the
699   * transaction commits or batch size is reached. This manually flushes the JDBC batch
700   * buffer.
701   * </p>
702   * <p>
703   * This is the same as <code>currentTransaction().flush()</code>.
704   * </p>
705   */
706  void flush();
707
708  /**
709   * Commit the current transaction.
710   */
711  void commitTransaction();
712
713  /**
714   * Rollback the current transaction.
715   */
716  void rollbackTransaction();
717
718  /**
719   * If the current transaction has already been committed do nothing otherwise
720   * rollback the transaction.
721   * <p>
722   * Useful to put in a finally block to ensure the transaction is ended, rather
723   * than a rollbackTransaction() in each catch block.
724   * </p>
725   * <p>
726   * Code example:
727   * <p>
728   * <pre>{@code
729   *
730   *   database.beginTransaction();
731   *   try {
732   *     // do some fetching and or persisting ...
733   *
734   *     // commit at the end
735   *     database.commitTransaction();
736   *
737   *   } finally {
738   *     // if commit didn't occur then rollback the transaction
739   *     database.endTransaction();
740   *   }
741   *
742   * }</pre>
743   */
744  void endTransaction();
745
746  /**
747   * Refresh the values of a bean.
748   * <p>
749   * Note that this resets OneToMany and ManyToMany properties so that if they
750   * are accessed a lazy load will refresh the many property.
751   * </p>
752   */
753  void refresh(Object bean);
754
755  /**
756   * Refresh a many property of an entity bean.
757   *
758   * @param bean         the entity bean containing the 'many' property
759   * @param propertyName the 'many' property to be refreshed
760   */
761  void refreshMany(Object bean, String propertyName);
762
763  /**
764   * Find a bean using its unique id.
765   * <p>
766   * <pre>{@code
767   *   // Fetch order 1
768   *   Order order = database.find(Order.class, 1);
769   * }</pre>
770   * <p>
771   * <p>
772   * If you want more control over the query then you can use createQuery() and
773   * Query.findOne();
774   * </p>
775   * <p>
776   * <pre>{@code
777   *   // ... additionally fetching customer, customer shipping address,
778   *   // order details, and the product associated with each order detail.
779   *   // note: only product id and name is fetch (its a "partial object").
780   *   // note: all other objects use "*" and have all their properties fetched.
781   *
782   *   Query<Order> query = database.find(Order.class)
783   *     .setId(1)
784   *     .fetch("customer")
785   *     .fetch("customer.shippingAddress")
786   *     .fetch("details")
787   *     .query();
788   *
789   *   // fetch associated products but only fetch their product id and name
790   *   query.fetch("details.product", "name");
791   *
792   *
793   *   Order order = query.findOne();
794   *
795   *   // traverse the object graph...
796   *
797   *   Customer customer = order.getCustomer();
798   *   Address shippingAddress = customer.getShippingAddress();
799   *   List<OrderDetail> details = order.getDetails();
800   *   OrderDetail detail0 = details.get(0);
801   *   Product product = detail0.getProduct();
802   *   String productName = product.getName();
803   *
804   * }</pre>
805   *
806   * @param beanType the type of entity bean to fetch
807   * @param id       the id value
808   */
809  @Nullable
810  <T> T find(Class<T> beanType, Object id);
811
812  /**
813   * Get a reference object.
814   * <p>
815   * This will not perform a query against the database unless some property other
816   * that the id property is accessed.
817   * </p>
818   * <p>
819   * It is most commonly used to set a 'foreign key' on another bean like:
820   * </p>
821   * <pre>{@code
822   *
823   *   Product product = database.getReference(Product.class, 1);
824   *
825   *   OrderDetail orderDetail = new OrderDetail();
826   *   // set the product 'foreign key'
827   *   orderDetail.setProduct(product);
828   *   orderDetail.setQuantity(42);
829   *   ...
830   *
831   *   database.save(orderDetail);
832   *
833   *
834   * }</pre>
835   * <p>
836   * <h3>Lazy loading characteristics</h3>
837   * <pre>{@code
838   *
839   *   Product product = database.getReference(Product.class, 1);
840   *
841   *   // You can get the id without causing a fetch/lazy load
842   *   Long productId = product.getId();
843   *
844   *   // If you try to get any other property a fetch/lazy loading will occur
845   *   // This will cause a query to execute...
846   *   String name = product.getName();
847   *
848   * }</pre>
849   *
850   * @param beanType the type of entity bean
851   * @param id       the id value
852   */
853  @Nonnull
854  <T> T getReference(Class<T> beanType, Object id);
855
856  /**
857   * Return the extended API for Database.
858   * <p>
859   * The extended API has the options for executing queries that take an explicit
860   * transaction as an argument.
861   * </p>
862   * <p>
863   * Typically we only need to use the extended API when we do NOT want to use the
864   * usual ThreadLocal based mechanism to obtain the current transaction but instead
865   * supply the transaction explicitly.
866   * </p>
867   */
868  ExtendedServer extended();
869
870  /**
871   * Either Insert or Update the bean depending on its state.
872   * <p>
873   * If there is no current transaction one will be created and committed for
874   * you automatically.
875   * </p>
876   * <p>
877   * Save can cascade along relationships. For this to happen you need to
878   * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the
879   * OneToMany, OneToOne or ManyToMany annotation.
880   * </p>
881   * <p>
882   * In this example below the details property has a CascadeType.ALL set so
883   * saving an order will also save all its details.
884   * </p>
885   * <p>
886   * <pre>{@code
887   *   public class Order { ...
888   *
889   *     ï¼ OneToMany(cascade=CascadeType.ALL, mappedBy="order")
890   *       List<OrderDetail> details;
891   *       ...
892   *   }
893   * }</pre>
894   * <p>
895   * <p>
896   * When a save cascades via a OneToMany or ManyToMany Ebean will automatically
897   * set the 'parent' object to the 'detail' object. In the example below in
898   * saving the order and cascade saving the order details the 'parent' order
899   * will be set against each order detail when it is saved.
900   * </p>
901   */
902  void save(Object bean) throws OptimisticLockException;
903
904  /**
905   * Save all the beans in the collection.
906   */
907  int saveAll(Collection<?> beans) throws OptimisticLockException;
908
909  /**
910   * Save all the beans.
911   */
912  int saveAll(Object... beans) throws OptimisticLockException;
913
914  /**
915   * Delete the bean.
916   * <p>
917   * This will return true if the bean was deleted successfully or JDBC batch is being used.
918   * </p>
919   * <p>
920   * If there is no current transaction one will be created and committed for
921   * you automatically.
922   * </p>
923   * <p>
924   * If the Bean does not have a version property (or loaded version property) and
925   * the bean does not exist then this returns false indicating that nothing was
926   * deleted. Note that, if JDBC batch mode is used then this always returns true.
927   * </p>
928   */
929  boolean delete(Object bean) throws OptimisticLockException;
930
931  /**
932   * Delete the bean with an explicit transaction.
933   * <p>
934   * This will return true if the bean was deleted successfully or JDBC batch is being used.
935   * </p>
936   * <p>
937   * If the Bean does not have a version property (or loaded version property) and
938   * the bean does not exist then this returns false indicating that nothing was
939   * deleted. However, if JDBC batch mode is used then this always returns true.
940   * </p>
941   */
942  boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
943
944  /**
945   * Delete a bean permanently without soft delete.
946   */
947  boolean deletePermanent(Object bean) throws OptimisticLockException;
948
949  /**
950   * Delete a bean permanently without soft delete using an explicit transaction.
951   */
952  boolean deletePermanent(Object bean, Transaction transaction) throws OptimisticLockException;
953
954  /**
955   * Delete all the beans in the collection permanently without soft delete.
956   */
957  int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException;
958
959  /**
960   * Delete all the beans in the collection permanently without soft delete using an explicit transaction.
961   */
962  int deleteAllPermanent(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
963
964  /**
965   * Delete the bean given its type and id.
966   */
967  int delete(Class<?> beanType, Object id);
968
969  /**
970   * Delete the bean given its type and id with an explicit transaction.
971   */
972  int delete(Class<?> beanType, Object id, Transaction transaction);
973
974  /**
975   * Delete permanent given the bean type and id.
976   */
977  int deletePermanent(Class<?> beanType, Object id);
978
979  /**
980   * Delete permanent given the bean type and id with an explicit transaction.
981   */
982  int deletePermanent(Class<?> beanType, Object id, Transaction transaction);
983
984  /**
985   * Delete all the beans in the collection.
986   */
987  int deleteAll(Collection<?> beans) throws OptimisticLockException;
988
989  /**
990   * Delete all the beans in the collection using an explicit transaction.
991   */
992  int deleteAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
993
994  /**
995   * Delete several beans given their type and id values.
996   */
997  int deleteAll(Class<?> beanType, Collection<?> ids);
998
999  /**
1000   * Delete several beans given their type and id values with an explicit transaction.
1001   */
1002  int deleteAll(Class<?> beanType, Collection<?> ids, Transaction transaction);
1003
1004  /**
1005   * Delete permanent for several beans given their type and id values.
1006   */
1007  int deleteAllPermanent(Class<?> beanType, Collection<?> ids);
1008
1009  /**
1010   * Delete permanent for several beans given their type and id values with an explicit transaction.
1011   */
1012  int deleteAllPermanent(Class<?> beanType, Collection<?> ids, Transaction transaction);
1013
1014  /**
1015   * Execute a Sql Update Delete or Insert statement. This returns the number of
1016   * rows that where updated, deleted or inserted. If is executed in batch then
1017   * this returns -1. You can get the actual rowCount after commit() from
1018   * updateSql.getRowCount().
1019   * <p>
1020   * If you wish to execute a Sql Select natively then you should use the
1021   * SqlQuery object or DtoQuery.
1022   * </p>
1023   * <p>
1024   * Note that the table modification information is automatically deduced and
1025   * you do not need to call the DB.externalModification() method when you
1026   * use this method.
1027   * </p>
1028   * <p>
1029   * Example:
1030   * </p>
1031   * <p>
1032   * <pre>{@code
1033   *
1034   *   // example that uses 'named' parameters
1035   *   String s = "UPDATE f_topic set post_count = :count where id = :id"
1036   *
1037   *   SqlUpdate update = database.createSqlUpdate(s);
1038   *
1039   *   update.setParameter("id", 1);
1040   *   update.setParameter("count", 50);
1041   *
1042   *   int modifiedCount = database.execute(update);
1043   *
1044   *   String msg = "There where " + modifiedCount + "rows updated";
1045   *
1046   * }</pre>
1047   *
1048   * @param sqlUpdate the update sql potentially with bind values
1049   * @return the number of rows updated or deleted. -1 if executed in batch.
1050   * @see CallableSql
1051   */
1052  int execute(SqlUpdate sqlUpdate);
1053
1054  /**
1055   * Execute a ORM insert update or delete statement using the current
1056   * transaction.
1057   * <p>
1058   * This returns the number of rows that where inserted, updated or deleted.
1059   * </p>
1060   */
1061  int execute(Update<?> update);
1062
1063  /**
1064   * Execute a ORM insert update or delete statement with an explicit
1065   * transaction.
1066   */
1067  int execute(Update<?> update, Transaction transaction);
1068
1069  /**
1070   * For making calls to stored procedures.
1071   * <p>
1072   * Example:
1073   * </p>
1074   * <p>
1075   * <pre>{@code
1076   *
1077   *   String sql = "{call sp_order_modify(?,?,?)}";
1078   *
1079   *   CallableSql cs = database.createCallableSql(sql);
1080   *   cs.setParameter(1, 27);
1081   *   cs.setParameter(2, "SHIPPED");
1082   *   cs.registerOut(3, Types.INTEGER);
1083   *   cs.execute();
1084   *
1085   *   // read the out parameter
1086   *   Integer returnValue = (Integer) cs.getObject(3);
1087   *
1088   * }</pre>
1089   */
1090  int execute(CallableSql callableSql);
1091
1092  /**
1093   * Inform Ebean that tables have been modified externally. These could be the
1094   * result of from calling a stored procedure, other JDBC calls or external
1095   * programs including other frameworks.
1096   * <p>
1097   * If you use database.execute(UpdateSql) then the table modification information
1098   * is automatically deduced and you do not need to call this method yourself.
1099   * </p>
1100   * <p>
1101   * This information is used to invalidate objects out of the cache and
1102   * potentially text indexes. This information is also automatically broadcast
1103   * across the cluster.
1104   * </p>
1105   * <p>
1106   * If there is a transaction then this information is placed into the current
1107   * transactions event information. When the transaction is committed this
1108   * information is registered (with the transaction manager). If this
1109   * transaction is rolled back then none of the transaction event information
1110   * registers including the information you put in via this method.
1111   * </p>
1112   * <p>
1113   * If there is NO current transaction when you call this method then this
1114   * information is registered immediately (with the transaction manager).
1115   * </p>
1116   *
1117   * @param tableName the name of the table that was modified
1118   * @param inserted  true if rows where inserted into the table
1119   * @param updated   true if rows on the table where updated
1120   * @param deleted   true if rows on the table where deleted
1121   */
1122  void externalModification(String tableName, boolean inserted, boolean updated, boolean deleted);
1123
1124  /**
1125   * Find a entity bean with an explicit transaction.
1126   *
1127   * @param <T>         the type of entity bean to find
1128   * @param beanType    the type of entity bean to find
1129   * @param id          the bean id value
1130   * @param transaction the transaction to use (can be null)
1131   */
1132  <T> T find(Class<T> beanType, Object id, Transaction transaction);
1133
1134  /**
1135   * Insert or update a bean with an explicit transaction.
1136   */
1137  void save(Object bean, Transaction transaction) throws OptimisticLockException;
1138
1139  /**
1140   * Save all the beans in the collection with an explicit transaction.
1141   */
1142  int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
1143
1144  /**
1145   * This method checks the uniqueness of a bean. I.e. if the save will work. It will return the
1146   * properties that violates an unique / primary key. This may be done in an UI save action to
1147   * validate if the user has entered correct values.
1148   * <p>
1149   * Note: This method queries the DB for uniqueness of all indices, so do not use it in a batch update.
1150   * <p>
1151   * Note: This checks only the root bean!
1152   * <p>
1153   * <pre>{@code
1154   *
1155   *   // there is a unique constraint on title
1156   *
1157   *   Document doc = new Document();
1158   *   doc.setTitle("One flew over the cuckoo's nest");
1159   *   doc.setBody("clashes with doc1");
1160   *
1161   *   Set<Property> properties = DB.checkUniqueness(doc);
1162   *
1163   *   if (properties.isEmpty()) {
1164   *     // it is unique ... carry on
1165   *
1166   *   } else {
1167   *     // build a user friendly message
1168   *     // to return message back to user
1169   *
1170   *     String uniqueProperties = properties.toString();
1171   *
1172   *     StringBuilder msg = new StringBuilder();
1173   *
1174   *     properties.forEach((it)-> {
1175   *       Object propertyValue = it.getVal(doc);
1176   *       String propertyName = it.getName();
1177   *       msg.append(" property["+propertyName+"] value["+propertyValue+"]");
1178   *     });
1179   *
1180   *     // uniqueProperties > [title]
1181   *     //       custom msg > property[title] value[One flew over the cuckoo's nest]
1182   *
1183   *  }
1184   *
1185   * }</pre>
1186   *
1187   * @param bean The entity bean to check uniqueness on
1188   * @return a set of Properties if constraint validation was detected or empty list.
1189   */
1190  @Nonnull
1191  Set<Property> checkUniqueness(Object bean);
1192
1193  /**
1194   * Same as {@link #checkUniqueness(Object)}. but with given transaction.
1195   */
1196  @Nonnull
1197  Set<Property> checkUniqueness(Object bean, Transaction transaction);
1198
1199  /**
1200   * Marks the entity bean as dirty.
1201   * <p>
1202   * This is used so that when a bean that is otherwise unmodified is updated the version
1203   * property is updated.
1204   * <p>
1205   * An unmodified bean that is saved or updated is normally skipped and this marks the bean as
1206   * dirty so that it is not skipped.
1207   * <p>
1208   * <pre>{@code
1209   *
1210   * Customer customer = database.find(Customer, id);
1211   *
1212   * // mark the bean as dirty so that a save() or update() will
1213   * // increment the version property
1214   * database.markAsDirty(customer);
1215   * database.save(customer);
1216   *
1217   * }</pre>
1218   */
1219  void markAsDirty(Object bean);
1220
1221  /**
1222   * Saves the bean using an update. If you know you are updating a bean then it is preferable to
1223   * use this update() method rather than save().
1224   * <p>
1225   * <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
1226   * update().You can create a new instance and set some of its properties programmatically for via
1227   * JSON/XML marshalling etc. This is described as a 'stateless update'.
1228   * </p>
1229   * <p>
1230   * <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
1231   * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
1232   * </p>
1233   * <pre>{@code
1234   *
1235   * // A 'stateless update' example
1236   * Customer customer = new Customer();
1237   * customer.setId(7);
1238   * customer.setName("ModifiedNameNoOCC");
1239   * database.update(customer);
1240   *
1241   * }</pre>
1242   */
1243  void update(Object bean) throws OptimisticLockException;
1244
1245  /**
1246   * Update a bean additionally specifying a transaction.
1247   */
1248  void update(Object bean, Transaction transaction) throws OptimisticLockException;
1249
1250  /**
1251   * Update a collection of beans. If there is no current transaction one is created and used to
1252   * update all the beans in the collection.
1253   */
1254  void updateAll(Collection<?> beans) throws OptimisticLockException;
1255
1256  /**
1257   * Update a collection of beans with an explicit transaction.
1258   */
1259  void updateAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
1260
1261  /**
1262   * Merge the bean using the default merge options (no paths specified, default delete).
1263   *
1264   * @param bean The bean to merge
1265   */
1266  void merge(Object bean);
1267
1268  /**
1269   * Merge the bean using the given merge options.
1270   *
1271   * @param bean    The bean to merge
1272   * @param options The options to control the merge
1273   */
1274  void merge(Object bean, MergeOptions options);
1275
1276  /**
1277   * Merge the bean using the given merge options and a transaction.
1278   *
1279   * @param bean    The bean to merge
1280   * @param options The options to control the merge
1281   */
1282  void merge(Object bean, MergeOptions options, Transaction transaction);
1283
1284  /**
1285   * Insert the bean.
1286   * <p>
1287   * Compared to save() this forces bean to perform an insert rather than trying to decide
1288   * based on the bean state. As such this is useful when you fetch beans from one database
1289   * and want to insert them into another database (and you want to explicitly insert them).
1290   * </p>
1291   */
1292  void insert(Object bean);
1293
1294  /**
1295   * Insert the bean with a transaction.
1296   */
1297  void insert(Object bean, Transaction transaction);
1298
1299  /**
1300   * Insert a collection of beans. If there is no current transaction one is created and used to
1301   * insert all the beans in the collection.
1302   */
1303  void insertAll(Collection<?> beans);
1304
1305  /**
1306   * Insert a collection of beans with an explicit transaction.
1307   */
1308  void insertAll(Collection<?> beans, Transaction transaction);
1309
1310  /**
1311   * Execute explicitly passing a transaction.
1312   */
1313  int execute(SqlUpdate updSql, Transaction transaction);
1314
1315  /**
1316   * Execute explicitly passing a transaction.
1317   */
1318  int execute(CallableSql callableSql, Transaction transaction);
1319
1320  /**
1321   * Execute a Runnable in a Transaction with an explicit scope.
1322   * <p>
1323   * The scope can control the transaction type, isolation and rollback
1324   * semantics.
1325   * </p>
1326   * <p>
1327   * <pre>{@code
1328   *
1329   *   // set specific transactional scope settings
1330   *   TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
1331   *
1332   *   database.execute(scope, new Runnable() {
1333   *       public void run() {
1334   *               User u1 = database.find(User.class, 1);
1335   *               ...
1336   *     }
1337   *   });
1338   *
1339   * }</pre>
1340   */
1341  void execute(TxScope scope, Runnable runnable);
1342
1343  /**
1344   * Execute a Runnable in a Transaction with the default scope.
1345   * <p>
1346   * The default scope runs with REQUIRED and by default will rollback on any
1347   * exception (checked or runtime).
1348   * </p>
1349   * <p>
1350   * <pre>{@code
1351   *
1352   *    database.execute(() -> {
1353   *
1354   *        User u1 = database.find(User.class, 1);
1355   *        User u2 = database.find(User.class, 2);
1356   *
1357   *        u1.setName("u1 mod");
1358   *        u2.setName("u2 mod");
1359   *
1360   *        u1.save();
1361   *        u2.save();
1362   *    });
1363   *
1364   * }</pre>
1365   */
1366  void execute(Runnable runnable);
1367
1368  /**
1369   * Execute a TxCallable in a Transaction with an explicit scope.
1370   * <p>
1371   * The scope can control the transaction type, isolation and rollback
1372   * semantics.
1373   * </p>
1374   * <p>
1375   * <pre>{@code
1376   *
1377   *   // set specific transactional scope settings
1378   *   TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
1379   *
1380   *   database.executeCall(scope, new Callable<String>() {
1381   *       public String call() {
1382   *               User u1 = database.find(User.class, 1);
1383   *               ...
1384   *               return u1.getEmail();
1385   *     }
1386   *   });
1387   *
1388   * }</pre>
1389   */
1390  <T> T executeCall(TxScope scope, Callable<T> callable);
1391
1392  /**
1393   * Execute a TxCallable in a Transaction with the default scope.
1394   * <p>
1395   * The default scope runs with REQUIRED and by default will rollback on any
1396   * exception (checked or runtime).
1397   * </p>
1398   * <p>
1399   * <pre>{@code
1400   *
1401   *   database.executeCall(new Callable<String>() {
1402   *     public String call() {
1403   *       User u1 = database.find(User.class, 1);
1404   *       User u2 = database.find(User.class, 2);
1405   *
1406   *       u1.setName("u1 mod");
1407   *       u2.setName("u2 mod");
1408   *
1409   *       database.save(u1);
1410   *       database.save(u2);
1411   *
1412   *       return u1.getEmail();
1413   *     }
1414   *   });
1415   *
1416   * }</pre>
1417   */
1418  <T> T executeCall(Callable<T> callable);
1419
1420  /**
1421   * Return the manager of the server cache ("L2" cache).
1422   */
1423  ServerCacheManager getServerCacheManager();
1424
1425  /**
1426   * Return the BackgroundExecutor service for asynchronous processing of
1427   * queries.
1428   */
1429  BackgroundExecutor getBackgroundExecutor();
1430
1431  /**
1432   * Return the JsonContext for reading/writing JSON.
1433   * <p>
1434   * This instance is safe to be used concurrently by multiple threads and this
1435   * method is cheap to call.
1436   * </p>
1437   * <p>
1438   * <h3>Simple example:</h3>
1439   * <pre>{@code
1440   *
1441   *     JsonContext json = database.json();
1442   *     String jsonOutput = json.toJson(list);
1443   *     System.out.println(jsonOutput);
1444   *
1445   * }</pre>
1446   * <p>
1447   * <h3>Using PathProperties:</h3>
1448   * <pre>{@code
1449   *
1450   *     // specify just the properties we want
1451   *     PathProperties paths = PathProperties.parse("name, status, anniversary");
1452   *
1453   *     List<Customer> customers =
1454   *       database.find(Customer.class)
1455   *         // apply those paths to the query (only fetch what we need)
1456   *         .apply(paths)
1457   *         .where().ilike("name", "rob%")
1458   *         .findList();
1459   *
1460   *     // ... get the json
1461   *     JsonContext jsonContext = database.json();
1462   *     String json = jsonContext.toJson(customers, paths);
1463   *
1464   * }</pre>
1465   *
1466   * @see FetchPath
1467   * @see Query#apply(FetchPath)
1468   */
1469  JsonContext json();
1470
1471  /**
1472   * Return a ScriptRunner for running SQL or DDL scripts.
1473   * <p/>
1474   * Intended to use mostly in testing to run seed SQL scripts or truncate table scripts etc.
1475   */
1476  ScriptRunner script();
1477
1478  /**
1479   * Return the Document store.
1480   */
1481  DocumentStore docStore();
1482
1483  /**
1484   * Publish a single bean given its type and id returning the resulting live bean.
1485   * <p>
1486   * The values are published from the draft to the live bean.
1487   * </p>
1488   *
1489   * @param <T>         the type of the entity bean
1490   * @param beanType    the type of the entity bean
1491   * @param id          the id of the entity bean
1492   * @param transaction the transaction the publish process should use (can be null)
1493   */
1494  <T> T publish(Class<T> beanType, Object id, Transaction transaction);
1495
1496  /**
1497   * Publish a single bean given its type and id returning the resulting live bean.
1498   * This will use the current transaction or create one if required.
1499   * <p>
1500   * The values are published from the draft to the live bean.
1501   * </p>
1502   *
1503   * @param <T>      the type of the entity bean
1504   * @param beanType the type of the entity bean
1505   * @param id       the id of the entity bean
1506   */
1507  <T> T publish(Class<T> beanType, Object id);
1508
1509  /**
1510   * Publish the beans that match the query returning the resulting published beans.
1511   * <p>
1512   * The values are published from the draft beans to the live beans.
1513   * </p>
1514   *
1515   * @param <T>         the type of the entity bean
1516   * @param query       the query used to select the draft beans to publish
1517   * @param transaction the transaction the publish process should use (can be null)
1518   */
1519  <T> List<T> publish(Query<T> query, Transaction transaction);
1520
1521  /**
1522   * Publish the beans that match the query returning the resulting published beans.
1523   * This will use the current transaction or create one if required.
1524   * <p>
1525   * The values are published from the draft beans to the live beans.
1526   * </p>
1527   *
1528   * @param <T>   the type of the entity bean
1529   * @param query the query used to select the draft beans to publish
1530   */
1531  <T> List<T> publish(Query<T> query);
1532
1533  /**
1534   * Restore the draft bean back to the live state.
1535   * <p>
1536   * The values from the live beans are set back to the draft bean and the
1537   * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
1538   * </p>
1539   *
1540   * @param <T>         the type of the entity bean
1541   * @param beanType    the type of the entity bean
1542   * @param id          the id of the entity bean to restore
1543   * @param transaction the transaction the restore process should use (can be null)
1544   */
1545  <T> T draftRestore(Class<T> beanType, Object id, Transaction transaction);
1546
1547  /**
1548   * Restore the draft bean back to the live state.
1549   * <p>
1550   * The values from the live beans are set back to the draft bean and the
1551   * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
1552   * </p>
1553   *
1554   * @param <T>      the type of the entity bean
1555   * @param beanType the type of the entity bean
1556   * @param id       the id of the entity bean to restore
1557   */
1558  <T> T draftRestore(Class<T> beanType, Object id);
1559
1560  /**
1561   * Restore the draft beans matching the query back to the live state.
1562   * <p>
1563   * The values from the live beans are set back to the draft bean and the
1564   * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
1565   * </p>
1566   *
1567   * @param <T>         the type of the entity bean
1568   * @param query       the query used to select the draft beans to restore
1569   * @param transaction the transaction the restore process should use (can be null)
1570   */
1571  <T> List<T> draftRestore(Query<T> query, Transaction transaction);
1572
1573  /**
1574   * Restore the draft beans matching the query back to the live state.
1575   * <p>
1576   * The values from the live beans are set back to the draft bean and the
1577   * <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
1578   * </p>
1579   *
1580   * @param <T>   the type of the entity bean
1581   * @param query the query used to select the draft beans to restore
1582   */
1583  <T> List<T> draftRestore(Query<T> query);
1584
1585  /**
1586   * Returns the set of properties/paths that are unknown (do not map to known properties or paths).
1587   * <p>
1588   * Validate the query checking the where and orderBy expression paths to confirm if
1589   * they represent valid properties/path for the given bean type.
1590   * </p>
1591   */
1592  <T> Set<String> validateQuery(Query<T> query);
1593
1594  /**
1595   * Truncate all the given tables.
1596   */
1597  void truncate(String... tables);
1598
1599  /**
1600   * Truncate the base tables for the given bean types.
1601   */
1602  void truncate(Class<?>... tables);
1603
1604}