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