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