001package io.ebean;
002
003import io.ebean.annotation.TxIsolation;
004import io.ebean.cache.ServerCacheManager;
005import io.ebean.config.BeanNotEnhancedException;
006import io.ebean.config.ServerConfig;
007import io.ebean.datasource.DataSourceConfigurationException;
008import io.ebean.plugin.Property;
009import io.ebean.text.csv.CsvReader;
010import io.ebean.text.json.JsonContext;
011import org.slf4j.Logger;
012import org.slf4j.LoggerFactory;
013
014import javax.annotation.Nonnull;
015import javax.annotation.Nullable;
016import javax.persistence.OptimisticLockException;
017import javax.persistence.PersistenceException;
018import java.util.Collection;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023import java.util.concurrent.Callable;
024import java.util.concurrent.ConcurrentHashMap;
025
026/**
027 * Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
028 * <p>
029 * Ebean is effectively this is an alias for {@link DB} which is the new and improved name for Ebean.
030 * <p>
031 * The preference is to use DB and Database rather than Ebean and EbeanServer.
032 */
033public final class Ebean {
034  private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
035
036  static {
037    EbeanVersion.getVersion(); // initialises the version class and logs the version.
038  }
039
040  /**
041   * Manages creation and cache of EbeanServers.
042   */
043  private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager();
044
045  /**
046   * Helper class for managing fast and safe access and creation of
047   * EbeanServers.
048   */
049  private static final class ServerManager {
050
051    /**
052     * Cache for fast concurrent read access.
053     */
054    private final ConcurrentHashMap<String, EbeanServer> concMap = new ConcurrentHashMap<>();
055
056    /**
057     * Cache for synchronized read, creation and put. Protected by the monitor object.
058     */
059    private final HashMap<String, EbeanServer> syncMap = new HashMap<>();
060
061    private final Object monitor = new Object();
062
063    /**
064     * The 'default' EbeanServer.
065     */
066    private EbeanServer defaultServer;
067
068    private ServerManager() {
069
070      try {
071        if (!PrimaryServer.isSkip()) {
072          // look to see if there is a default server defined
073          String defaultName = PrimaryServer.getDefaultServerName();
074          logger.debug("defaultName:{}", defaultName);
075          if (defaultName != null && !defaultName.trim().isEmpty()) {
076            defaultServer = getWithCreate(defaultName.trim());
077          }
078        }
079      } catch (BeanNotEnhancedException e) {
080        throw e;
081
082      } catch (DataSourceConfigurationException e) {
083        String msg = "Configuration error creating DataSource for the default EbeanServer." +
084          " This typically means a missing application-test.yaml or missing ebean-test-config dependency." +
085          " See https://ebean.io/docs/trouble-shooting#datasource";
086        throw new DataSourceConfigurationException(msg, e);
087
088      } catch (Throwable e) {
089        logger.error("Error trying to create the default EbeanServer", e);
090        throw new RuntimeException(e);
091      }
092    }
093
094    private EbeanServer getDefaultServer() {
095      if (defaultServer == null) {
096        String msg = "The default EbeanServer has not been defined?";
097        msg += " This is normally set via the ebean.datasource.default property.";
098        msg += " Otherwise it should be registered programmatically via registerServer()";
099        throw new PersistenceException(msg);
100      }
101      return defaultServer;
102    }
103
104    private EbeanServer get(String name) {
105      if (name == null || name.isEmpty()) {
106        return defaultServer;
107      }
108      // non-synchronized read
109      EbeanServer server = concMap.get(name);
110      if (server != null) {
111        return server;
112      }
113      // synchronized read, create and put
114      return getWithCreate(name);
115    }
116
117    /**
118     * Synchronized read, create and put of EbeanServers.
119     */
120    private EbeanServer getWithCreate(String name) {
121
122      synchronized (monitor) {
123
124        EbeanServer server = syncMap.get(name);
125        if (server == null) {
126          // register when creating server this way
127          server = EbeanServerFactory.create(name);
128          register(server, false);
129        }
130        return server;
131      }
132    }
133
134    /**
135     * Register a server so we can get it by its name.
136     */
137    private void register(EbeanServer server, boolean isDefaultServer) {
138      registerWithName(server.getName(), server, isDefaultServer);
139    }
140
141    private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
142      synchronized (monitor) {
143        concMap.put(name, server);
144        syncMap.put(name, server);
145        if (isDefaultServer) {
146          defaultServer = server;
147        }
148      }
149    }
150
151  }
152
153  private Ebean() {
154  }
155
156  /**
157   * Get the EbeanServer for a given DataSource. If name is null this will
158   * return the 'default' EbeanServer.
159   * <p>
160   * This is provided to access EbeanServer for databases other than the
161   * 'default' database. EbeanServer also provides more control over
162   * transactions and the ability to use transactions created externally to
163   * Ebean.
164   * </p>
165   * <pre>{@code
166   * // use the "hr" database
167   * EbeanServer hrDatabase = Ebean.getServer("hr");
168   *
169   * Person person = hrDatabase.find(Person.class, 10);
170   * }</pre>
171   *
172   * @param name the name of the server, can use null for the 'default server'
173   */
174  public static EbeanServer getServer(String name) {
175    return serverMgr.get(name);
176  }
177
178  /**
179   * Returns the default EbeanServer.
180   * <p>
181   * This is equivalent to <code>Ebean.getServer(null);</code>
182   * </p>
183   */
184  public static EbeanServer getDefaultServer() {
185    return serverMgr.getDefaultServer();
186  }
187
188  /**
189   * Return the ExpressionFactory from the default server.
190   * <p>
191   * The ExpressionFactory is used internally by the query and ExpressionList to
192   * build the WHERE and HAVING clauses. Alternatively you can use the
193   * ExpressionFactory directly to create expressions to add to the query where
194   * clause.
195   * </p>
196   * <p>
197   * Alternatively you can use the {@link Expr} as a shortcut to the
198   * ExpressionFactory of the 'Default' EbeanServer.
199   * </p>
200   * <p>
201   * You generally need to the an ExpressionFactory (or {@link Expr}) to build
202   * an expression that uses OR like Expression e = Expr.or(..., ...);
203   * </p>
204   */
205  public static ExpressionFactory getExpressionFactory() {
206    return serverMgr.getDefaultServer().getExpressionFactory();
207  }
208
209  /**
210   * Register the server with this Ebean singleton. Specify if the registered
211   * server is the primary/default server.
212   */
213  public static void register(EbeanServer server, boolean defaultServer) {
214    serverMgr.register(server, defaultServer);
215  }
216
217  /**
218   * Backdoor for registering a mock implementation of EbeanServer as the default server.
219   */
220  protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
221    EbeanServer originalPrimaryServer = serverMgr.defaultServer;
222    serverMgr.registerWithName(name, server, defaultServer);
223    return originalPrimaryServer;
224  }
225
226  /**
227   * Return the next identity value for a given bean type.
228   * <p>
229   * This will only work when a IdGenerator is on this bean type such as a DB
230   * sequence or UUID.
231   * </p>
232   * <p>
233   * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do
234   * not need to use this method generally. It is made available for more
235   * complex cases where it is useful to get an ID prior to some processing.
236   * </p>
237   */
238  public static Object nextId(Class<?> beanType) {
239    return serverMgr.getDefaultServer().nextId(beanType);
240  }
241
242  /**
243   * Start a transaction with 'REQUIRED' semantics.
244   * <p>
245   * With REQUIRED semantics if an active transaction already exists that transaction will be used.
246   * </p>
247   * <p>
248   * The transaction is stored in a ThreadLocal variable and typically you only
249   * need to use the returned Transaction <em>IF</em> you wish to do things like
250   * use batch mode, change the transaction isolation level, use savepoints or
251   * log comments to the transaction log.
252   * </p>
253   * <p>
254   * Example of using a transaction to span multiple calls to find(), save()
255   * etc.
256   * </p>
257   * <pre>{@code
258   *
259   *   // start a transaction (stored in a ThreadLocal)
260   *   Ebean.beginTransaction();
261   *   try {
262   *       Order order = Ebean.find(Order.class,10); ...
263   *
264   *       Ebean.save(order);
265   *
266   *       Ebean.commitTransaction();
267   *
268   *   } finally {
269   *       // rollback if we didn't commit
270   *       // i.e. an exception occurred before commitTransaction().
271   *       Ebean.endTransaction();
272   *   }
273   *
274   * }</pre>
275   * <p>
276   * If you want to externalise the transaction management then you should be
277   * able to do this via EbeanServer. Specifically with EbeanServer you can pass
278   * the transaction to the various find() and save() execute() methods. This
279   * gives you the ability to create the transactions yourself externally from
280   * Ebean and pass those transactions through to the various methods available
281   * on EbeanServer.
282   * </p>
283   */
284  public static Transaction beginTransaction() {
285    return serverMgr.getDefaultServer().beginTransaction();
286  }
287
288  /**
289   * Start a transaction additionally specifying the isolation level.
290   *
291   * @param isolation the Transaction isolation level
292   */
293  public static Transaction beginTransaction(TxIsolation isolation) {
294    return serverMgr.getDefaultServer().beginTransaction(isolation);
295  }
296
297  /**
298   * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
299   * <p>
300   * Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or
301   * {@link #execute(TxScope, Runnable)}.
302   * </p>
303   * <p>
304   * <h3>REQUIRES_NEW example:</h3>
305   * <pre>{@code
306   * // Start a new transaction. If there is a current transaction
307   * // suspend it until this transaction ends
308   * Transaction txn = Ebean.beginTransaction(TxScope.requiresNew());
309   * try {
310   *
311   *   ...
312   *
313   *   // commit the transaction
314   *   txn.commit();
315   *
316   * } finally {
317   *   // end this transaction which:
318   *   //  A) will rollback transaction if it has not been committed already
319   *   //  B) will restore a previously suspended transaction
320   *   txn.end();
321   * }
322   *
323   * }</pre>
324   * <h3>REQUIRED example:</h3>
325   * <pre>{@code
326   *
327   * // start a new transaction if there is not a current transaction
328   * Transaction txn = Ebean.beginTransaction(TxScope.required());
329   * try {
330   *
331   *   ...
332   *
333   *   // commit the transaction if it was created or
334   *   // do nothing if there was already a current transaction
335   *   txn.commit();
336   *
337   * } finally {
338   *   // end this transaction which will rollback the transaction
339   *   // if it was created for this try finally scope and has not
340   *   // already been committed
341   *   txn.end();
342   * }
343   *
344   * }</pre>
345   */
346  public static Transaction beginTransaction(TxScope scope) {
347    return serverMgr.getDefaultServer().beginTransaction(scope);
348  }
349
350  /**
351   * Returns the current transaction or null if there is no current transaction
352   * in scope.
353   */
354  public static Transaction currentTransaction() {
355    return serverMgr.getDefaultServer().currentTransaction();
356  }
357
358  /**
359   * The batch will be flushing automatically but you can use this to explicitly
360   * flush the batch if you like.
361   * <p>
362   * Flushing occurs automatically when:
363   * </p>
364   * <ul>
365   * <li>the batch size is reached</li>
366   * <li>A query is executed on the same transaction</li>
367   * <li>UpdateSql or CallableSql are mixed with bean save and delete</li>
368   * <li>Transaction commit occurs</li>
369   * <li>A getter method is called on a batched bean</li>
370   * </ul>
371   */
372  public static void flush() {
373    currentTransaction().flush();
374  }
375
376  /**
377   * Register a TransactionCallback on the currently active transaction.
378   * <p/>
379   * If there is no currently active transaction then a PersistenceException is thrown.
380   *
381   * @param transactionCallback the transaction callback to be registered with the current transaction
382   * @throws PersistenceException if there is no currently active transaction
383   */
384  public static void register(TransactionCallback transactionCallback) throws PersistenceException {
385    serverMgr.getDefaultServer().register(transactionCallback);
386  }
387
388  /**
389   * Commit the current transaction.
390   */
391  public static void commitTransaction() {
392    serverMgr.getDefaultServer().commitTransaction();
393  }
394
395  /**
396   * Rollback the current transaction.
397   */
398  public static void rollbackTransaction() {
399    serverMgr.getDefaultServer().rollbackTransaction();
400  }
401
402  /**
403   * If the current transaction has already been committed do nothing otherwise
404   * rollback the transaction.
405   * <p>
406   * Useful to put in a finally block to ensure the transaction is ended, rather
407   * than a rollbackTransaction() in each catch block.
408   * </p>
409   * <p>
410   * Code example:
411   * </p>
412   * <pre>{@code
413   *   Ebean.beginTransaction();
414   *   try {
415   *     // do some fetching and or persisting
416   *
417   *     // commit at the end
418   *     Ebean.commitTransaction();
419   *
420   *   } finally {
421   *     // if commit didn't occur then rollback the transaction
422   *     Ebean.endTransaction();
423   *   }
424   * }</pre>
425   */
426  public static void endTransaction() {
427    serverMgr.getDefaultServer().endTransaction();
428  }
429
430  /**
431   * Mark the current transaction as rollback only.
432   */
433  public static void setRollbackOnly() {
434    serverMgr.getDefaultServer().currentTransaction().setRollbackOnly();
435  }
436
437  /**
438   * Return a map of the differences between two objects of the same type.
439   * <p>
440   * When null is passed in for b, then the 'OldValues' of a is used for the
441   * difference comparison.
442   * </p>
443   */
444  public static Map<String, ValuePair> diff(Object a, Object b) {
445    return serverMgr.getDefaultServer().diff(a, b);
446  }
447
448  /**
449   * Either Insert or Update the bean depending on its state.
450   * <p>
451   * If there is no current transaction one will be created and committed for
452   * you automatically.
453   * </p>
454   * <p>
455   * Save can cascade along relationships. For this to happen you need to
456   * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the
457   * OneToMany, OneToOne or ManyToMany annotation.
458   * </p>
459   * <p>
460   * In this example below the details property has a CascadeType.ALL set so
461   * saving an order will also save all its details.
462   * </p>
463   * <pre>{@code
464   *   public class Order { ...
465   *
466   *       @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
467   *       List<OrderDetail> details;
468   *       ...
469   *   }
470   * }</pre>
471   * <p>
472   * When a save cascades via a OneToMany or ManyToMany Ebean will automatically
473   * set the 'parent' object to the 'detail' object. In the example below in
474   * saving the order and cascade saving the order details the 'parent' order
475   * will be set against each order detail when it is saved.
476   * </p>
477   */
478  public static void save(Object bean) throws OptimisticLockException {
479    serverMgr.getDefaultServer().save(bean);
480  }
481
482  /**
483   * Insert the bean. This is useful when you set the Id property on a bean and
484   * want to explicitly insert it.
485   */
486  public static void insert(Object bean) {
487    serverMgr.getDefaultServer().insert(bean);
488  }
489
490  /**
491   * Insert a collection of beans.
492   */
493  public static void insertAll(Collection<?> beans) {
494    serverMgr.getDefaultServer().insertAll(beans);
495  }
496
497  /**
498   * Marks the entity bean as dirty.
499   * <p>
500   * This is used so that when a bean that is otherwise unmodified is updated with the version
501   * property updated.
502   * <p>
503   * An unmodified bean that is saved or updated is normally skipped and this marks the bean as
504   * dirty so that it is not skipped.
505   * <pre>{@code
506   *
507   *   Customer customer = Ebean.find(Customer, id);
508   *
509   *   // mark the bean as dirty so that a save() or update() will
510   *   // increment the version property
511   *   Ebean.markAsDirty(customer);
512   *   Ebean.save(customer);
513   *
514   * }</pre>
515   */
516  public static void markAsDirty(Object bean) throws OptimisticLockException {
517    serverMgr.getDefaultServer().markAsDirty(bean);
518  }
519
520  /**
521   * Saves the bean using an update. If you know you are updating a bean then it is preferrable to
522   * use this update() method rather than save().
523   * <p>
524   * <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
525   * update().You can create a new instance and set some of its properties programmatically for via
526   * JSON/XML marshalling etc. This is described as a 'stateless update'.
527   * </p>
528   * <p>
529   * <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
530   * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
531   * </p>
532   * <p>
533   * <b>{@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
534   * OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
535   * that are in the database but are not in the collection are deleted.
536   * </p>
537   * <p>
538   * <b>{@link ServerConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
539   * controls if only the changed properties are included in the update or if all the loaded
540   * properties are included instead.
541   * </p>
542   * <pre>{@code
543   *
544   *   // A 'stateless update' example
545   *   Customer customer = new Customer();
546   *   customer.setId(7);
547   *   customer.setName("ModifiedNameNoOCC");
548   *
549   *   DB.update(customer);
550   *
551   * }</pre>
552   *
553   * @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
554   * @see ServerConfig#setUpdateChangesOnly(boolean)
555   */
556  public static void update(Object bean) throws OptimisticLockException {
557    serverMgr.getDefaultServer().update(bean);
558  }
559
560  /**
561   * Update the beans in the collection.
562   */
563  public static void updateAll(Collection<?> beans) throws OptimisticLockException {
564    serverMgr.getDefaultServer().updateAll(beans);
565  }
566
567  /**
568   * Merge the bean using the default merge options.
569   *
570   * @param bean The bean to merge
571   */
572  public static void merge(Object bean) {
573    serverMgr.getDefaultServer().merge(bean);
574  }
575
576  /**
577   * Merge the bean using the given merge options.
578   *
579   * @param bean    The bean to merge
580   * @param options The options to control the merge
581   */
582  public static void merge(Object bean, MergeOptions options) {
583    serverMgr.getDefaultServer().merge(bean, options);
584  }
585
586  /**
587   * Save all the beans from a Collection.
588   */
589  public static int saveAll(Collection<?> beans) throws OptimisticLockException {
590    return serverMgr.getDefaultServer().saveAll(beans);
591  }
592
593  /**
594   * This method checks the uniqueness of a bean. I.e. if the save will work. It will return the
595   * properties that violates an unique / primary key. This may be done in an UI save action to
596   * validate if the user has entered correct values.
597   * <p>
598   * Note: This method queries the DB for uniqueness of all indices, so do not use it in a batch update.
599   * <p>
600   * Note: This checks only the root bean!
601   * <p>
602   * <pre>{@code
603   *
604   *   // there is a unique constraint on title
605   *
606   *   Document doc = new Document();
607   *   doc.setTitle("One flew over the cuckoo's nest");
608   *   doc.setBody("clashes with doc1");
609   *
610   *   Set<Property> properties = server().checkUniqueness(doc);
611   *
612   *   if (properties.isEmpty()) {
613   *     // it is unique ... carry on
614   *
615   *   } else {
616   *     // build a user friendly message
617   *     // to return message back to user
618   *
619   *     String uniqueProperties = properties.toString();
620   *
621   *     StringBuilder msg = new StringBuilder();
622   *
623   *     properties.forEach((it)-> {
624   *       Object propertyValue = it.getVal(doc);
625   *       String propertyName = it.getName();
626   *       msg.append(" property["+propertyName+"] value["+propertyValue+"]");
627   *     });
628   *
629   *     // uniqueProperties > [title]
630   *     //       custom msg > property[title] value[One flew over the cuckoo's nest]
631   *
632   *  }
633   *
634   * }</pre>
635   *
636   * @param bean The entity bean to check uniqueness on
637   * @return a set of Properties if constraint validation was detected or empty list.
638   */
639  @Nonnull
640  public static Set<Property> checkUniqueness(Object bean) {
641    return serverMgr.getDefaultServer().checkUniqueness(bean);
642  }
643
644  /**
645   * Same as {@link #checkUniqueness(Object)}. but with given transaction.
646   */
647  @Nonnull
648  public static Set<Property> checkUniqueness(Object bean, Transaction transaction) {
649    return serverMgr.getDefaultServer().checkUniqueness(bean, transaction);
650  }
651
652  /**
653   * Delete the bean.
654   * <p>
655   * This will return true if the bean was deleted successfully or JDBC batch is being used.
656   * </p>
657   * <p>
658   * If there is no current transaction one will be created and committed for
659   * you automatically.
660   * </p>
661   * <p>
662   * If the bean is configured with <code>@SoftDelete</code> then this will perform a soft
663   * delete rather than a hard/permanent delete.
664   * </p>
665   * <p>
666   * If the Bean does not have a version property (or loaded version property) and
667   * the bean does not exist then this returns false indicating that nothing was
668   * deleted. Note that, if JDBC batch mode is used then this always returns true.
669   * </p>
670   */
671  public static boolean delete(Object bean) throws OptimisticLockException {
672    return serverMgr.getDefaultServer().delete(bean);
673  }
674
675  /**
676   * Delete the bean in permanent fashion (will not use soft delete).
677   */
678  public static boolean deletePermanent(Object bean) throws OptimisticLockException {
679    return serverMgr.getDefaultServer().deletePermanent(bean);
680  }
681
682  /**
683   * Delete the bean given its type and id.
684   */
685  public static int delete(Class<?> beanType, Object id) {
686    return serverMgr.getDefaultServer().delete(beanType, id);
687  }
688
689  /**
690   * Delete permanent the bean given its type and id.
691   */
692  public static int deletePermanent(Class<?> beanType, Object id) {
693    return serverMgr.getDefaultServer().deletePermanent(beanType, id);
694  }
695
696  /**
697   * Delete several beans given their type and id values.
698   */
699  public static int deleteAll(Class<?> beanType, Collection<?> ids) {
700    return serverMgr.getDefaultServer().deleteAll(beanType, ids);
701  }
702
703  /**
704   * Delete permanent several beans given their type and id values.
705   */
706  public static int deleteAllPermanent(Class<?> beanType, Collection<?> ids) {
707    return serverMgr.getDefaultServer().deleteAllPermanent(beanType, ids);
708  }
709
710  /**
711   * Delete all the beans in the Collection.
712   */
713  public static int deleteAll(Collection<?> beans) throws OptimisticLockException {
714    return serverMgr.getDefaultServer().deleteAll(beans);
715  }
716
717  /**
718   * Delete permanent all the beans in the Collection (will not use soft delete).
719   */
720  public static int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException {
721    return serverMgr.getDefaultServer().deleteAllPermanent(beans);
722  }
723
724  /**
725   * Refresh the values of a bean.
726   * <p>
727   * Note that this resets OneToMany and ManyToMany properties so that if they
728   * are accessed a lazy load will refresh the many property.
729   * </p>
730   */
731  public static void refresh(Object bean) {
732    serverMgr.getDefaultServer().refresh(bean);
733  }
734
735  /**
736   * Refresh a 'many' property of a bean.
737   * <pre>{@code
738   *
739   *   Order order = ...;
740   *   ...
741   *   // refresh the order details...
742   *   Ebean.refreshMany(order, "details");
743   *
744   * }</pre>
745   *
746   * @param bean             the entity bean containing the List Set or Map to refresh.
747   * @param manyPropertyName the property name of the List Set or Map to refresh.
748   */
749  public static void refreshMany(Object bean, String manyPropertyName) {
750    serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
751  }
752
753  /**
754   * Get a reference object.
755   * <p>
756   * This is sometimes described as a proxy (with lazy loading).
757   * </p>
758   * <pre>{@code
759   *
760   *   Product product = Ebean.getReference(Product.class, 1);
761   *
762   *   // You can get the id without causing a fetch/lazy load
763   *   Integer productId = product.getId();
764   *
765   *   // If you try to get any other property a fetch/lazy loading will occur
766   *   // This will cause a query to execute...
767   *   String name = product.getName();
768   *
769   * }</pre>
770   *
771   * @param beanType the type of entity bean
772   * @param id       the id value
773   */
774  public static <T> T getReference(Class<T> beanType, Object id) {
775    return serverMgr.getDefaultServer().getReference(beanType, id);
776  }
777
778  /**
779   * Sort the list using the sortByClause which can contain a comma delimited
780   * list of property names and keywords asc, desc, nullsHigh and nullsLow.
781   * <ul>
782   * <li>asc - ascending order (which is the default)</li>
783   * <li>desc - Descending order</li>
784   * <li>nullsHigh - Treat null values as high/large values (which is the
785   * default)</li>
786   * <li>nullsLow- Treat null values as low/very small values</li>
787   * </ul>
788   * <p>
789   * If you leave off any keywords the defaults are ascending order and treating
790   * nulls as high values.
791   * </p>
792   * <p>
793   * Note that the sorting uses a Comparator and Collections.sort(); and does
794   * not invoke a DB query.
795   * </p>
796   * <pre>{@code
797   *
798   *   // find orders and their customers
799   *   List<Order> list = Ebean.find(Order.class)
800   *     .fetch("customer")
801   *     .orderBy("id")
802   *     .findList();
803   *
804   *   // sort by customer name ascending, then by order shipDate
805   *   // ... then by the order status descending
806   *   Ebean.sort(list, "customer.name, shipDate, status desc");
807   *
808   *   // sort by customer name descending (with nulls low)
809   *   // ... then by the order id
810   *   Ebean.sort(list, "customer.name desc nullsLow, id");
811   *
812   * }</pre>
813   *
814   * @param list         the list of entity beans
815   * @param sortByClause the properties to sort the list by
816   */
817  public static <T> void sort(List<T> list, String sortByClause) {
818    serverMgr.getDefaultServer().sort(list, sortByClause);
819  }
820
821  /**
822   * Find a bean using its unique id. This will not use caching.
823   * <pre>{@code
824   *
825   *   // Fetch order 1
826   *   Order order = Ebean.find(Order.class, 1);
827   *
828   * }</pre>
829   * <p>
830   * If you want more control over the query then you can use createQuery() and
831   * Query.findOne();
832   * </p>
833   * <pre>{@code
834   *
835   *   // ... additionally fetching customer, customer shipping address,
836   *   // order details, and the product associated with each order detail.
837   *   // note: only product id and name is fetch (its a "partial object").
838   *   // note: all other objects use "*" and have all their properties fetched.
839   *
840   *   Query<Order> query = Ebean.find(Order.class)
841   *     .setId(1)
842   *     .fetch("customer")
843   *     .fetch("customer.shippingAddress")
844   *     .fetch("details")
845   *     .query();
846   *
847   *   // fetch associated products but only fetch their product id and name
848   *   query.fetch("details.product", "name");
849   *
850   *   // traverse the object graph...
851   *
852   *   Order order = query.findOne();
853   *
854   *   Customer customer = order.getCustomer();
855   *   Address shippingAddress = customer.getShippingAddress();
856   *   List<OrderDetail> details = order.getDetails();
857   *   OrderDetail detail0 = details.get(0);
858   *   Product product = detail0.getProduct();
859   *   String productName = product.getName();
860   *
861   * }</pre>
862   *
863   * @param beanType the type of entity bean to fetch
864   * @param id       the id value
865   */
866  @Nullable
867  public static <T> T find(Class<T> beanType, Object id) {
868    return serverMgr.getDefaultServer().find(beanType, id);
869  }
870
871  /**
872   * Create a SqlQuery for executing native sql
873   * query statements.
874   * <p>
875   * Note that you can use raw SQL with entity beans, refer to the SqlSelect
876   * annotation for examples.
877   * </p>
878   */
879  public static SqlQuery createSqlQuery(String sql) {
880    return serverMgr.getDefaultServer().createSqlQuery(sql);
881  }
882
883  /**
884   * Create a sql update for executing native dml statements.
885   * <p>
886   * Use this to execute a Insert Update or Delete statement. The statement will
887   * be native to the database and contain database table and column names.
888   * </p>
889   * <p>
890   * See {@link SqlUpdate} for example usage.
891   * </p>
892   */
893  public static SqlUpdate createSqlUpdate(String sql) {
894    return serverMgr.getDefaultServer().createSqlUpdate(sql);
895  }
896
897  /**
898   * Create a CallableSql to execute a given stored procedure.
899   *
900   * @see CallableSql
901   */
902  public static CallableSql createCallableSql(String sql) {
903    return serverMgr.getDefaultServer().createCallableSql(sql);
904  }
905
906  /**
907   * Create a orm update where you will supply the insert/update or delete
908   * statement (rather than using a named one that is already defined using the
909   * &#064;NamedUpdates annotation).
910   * <p>
911   * The orm update differs from the sql update in that it you can use the bean
912   * name and bean property names rather than table and column names.
913   * </p>
914   * <p>
915   * An example:
916   * </p>
917   * <pre>{@code
918   *
919   *   // The bean name and properties - "topic","postCount" and "id"
920   *
921   *   // will be converted into their associated table and column names
922   *   String updStatement = "update topic set postCount = :pc where id = :id";
923   *
924   *   Update<Topic> update = Ebean.createUpdate(Topic.class, updStatement);
925   *
926   *   update.set("pc", 9);
927   *   update.set("id", 3);
928   *
929   *   int rows = update.execute();
930   *   System.out.println("rows updated:" + rows);
931   *
932   * }</pre>
933   */
934  public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
935
936    return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate);
937  }
938
939  /**
940   * Create a CsvReader for a given beanType.
941   */
942  public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
943
944    return serverMgr.getDefaultServer().createCsvReader(beanType);
945  }
946
947  /**
948   * Create a named query.
949   * <p>
950   * For RawSql the named query is expected to be in ebean.xml.
951   * </p>
952   *
953   * @param beanType   The type of entity bean
954   * @param namedQuery The name of the query
955   * @param <T>        The type of entity bean
956   * @return The query
957   */
958  public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
959    return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
960  }
961
962  /**
963   * Create a query for a type of entity bean.
964   * <p>
965   * You can use the methods on the Query object to specify fetch paths,
966   * predicates, order by, limits etc.
967   * </p>
968   * <p>
969   * You then use findList(), findSet(), findMap() and findOne() to execute
970   * the query and return the collection or bean.
971   * </p>
972   * <p>
973   * Note that a query executed by {@link Query#findList()}
974   * {@link Query#findSet()} etc will execute against the same EbeanServer from
975   * which is was created.
976   * </p>
977   *
978   * @param beanType the class of entity to be fetched
979   * @return A ORM Query object for this beanType
980   */
981  public static <T> Query<T> createQuery(Class<T> beanType) {
982
983    return serverMgr.getDefaultServer().createQuery(beanType);
984  }
985
986  /**
987   * Parse the Ebean query language statement returning the query which can then
988   * be modified (add expressions, change order by clause, change maxRows, change
989   * fetch and select paths etc).
990   * <p>
991   * <h3>Example</h3>
992   * <pre>{@code
993   *
994   *   // Find order additionally fetching the customer, details and details.product name.
995   *
996   *   String eql = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
997   *
998   *   Query<Order> query = Ebean.createQuery(Order.class, eql);
999   *   query.setParameter("orderId", 2);
1000   *
1001   *   Order order = query.findOne();
1002   *
1003   *   // This is the same as:
1004   *
1005   *   Order order = Ebean.find(Order.class)
1006   *     .fetch("customer")
1007   *     .fetch("details")
1008   *     .fetch("detail.product", "name")
1009   *     .setId(2)
1010   *     .findOne();
1011   *
1012   * }</pre>
1013   *
1014   * @param beanType The type of bean to fetch
1015   * @param eql      The Ebean query
1016   * @param <T>      The type of the entity bean
1017   * @return The query with expressions defined as per the parsed query statement
1018   */
1019  public static <T> Query<T> createQuery(Class<T> beanType, String eql) {
1020
1021    return serverMgr.getDefaultServer().createQuery(beanType, eql);
1022  }
1023
1024  /**
1025   * Create a query for a type of entity bean.
1026   * <p>
1027   * This is actually the same as {@link #createQuery(Class)}. The reason it
1028   * exists is that people used to JPA will probably be looking for a
1029   * createQuery method (the same as entityManager).
1030   * </p>
1031   *
1032   * @param beanType the type of entity bean to find
1033   * @return A ORM Query object for this beanType
1034   */
1035  public static <T> Query<T> find(Class<T> beanType) {
1036
1037    return serverMgr.getDefaultServer().find(beanType);
1038  }
1039
1040  /**
1041   * Create a query using native SQL.
1042   * <p>
1043   * The native SQL can contain named parameters or positioned parameters.
1044   * </p>
1045   * <pre>{@code
1046   *
1047   *   String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
1048   *
1049   *   List<Customer> customers = DB.findNative(Customer.class, sql)
1050   *     .setParameter(1, "Rob%")
1051   *     .findList()
1052   *
1053   * }</pre>
1054   *
1055   * @param beanType  The type of entity bean to fetch
1056   * @param nativeSql The SQL that can contain named or positioned parameters
1057   * @return The query to set parameters and execute
1058   */
1059  public static <T> Query<T> findNative(Class<T> beanType, String nativeSql) {
1060    return serverMgr.getDefaultServer().findNative(beanType, nativeSql);
1061  }
1062
1063  /**
1064   * Create a Query for DTO beans.
1065   * <p>
1066   * DTO beans are just normal bean like classes with public constructor(s) and setters.
1067   * They do not need to be registered with Ebean before use.
1068   * </p>
1069   *
1070   * @param dtoType The type of the DTO bean the rows will be mapped into.
1071   * @param sql     The SQL query to execute.
1072   * @param <T>     The type of the DTO bean.
1073   */
1074  public static <T> DtoQuery<T> findDto(Class<T> dtoType, String sql) {
1075    return serverMgr.getDefaultServer().findDto(dtoType, sql);
1076  }
1077
1078  /**
1079   * Create an Update query to perform a bulk update.
1080   * <p>
1081   * <pre>{@code
1082   *
1083   *  int rows = Ebean.update(Customer.class)
1084   *      .set("status", Customer.Status.ACTIVE)
1085   *      .set("updtime", new Timestamp(System.currentTimeMillis()))
1086   *      .where()
1087   *        .gt("id", 1000)
1088   *        .update();
1089   *
1090   * }</pre>
1091   *
1092   * @param beanType The type of entity bean to update
1093   * @param <T>      The type of entity bean
1094   * @return The update query to use
1095   */
1096  public static <T> UpdateQuery<T> update(Class<T> beanType) {
1097    return serverMgr.getDefaultServer().update(beanType);
1098  }
1099
1100  /**
1101   * Create a filter for sorting and filtering lists of entities locally without
1102   * going back to the database.
1103   * <p>
1104   * This produces and returns a new list with the sort and filters applied.
1105   * </p>
1106   * <p>
1107   * Refer to {@link Filter} for an example of its use.
1108   * </p>
1109   */
1110  public static <T> Filter<T> filter(Class<T> beanType) {
1111    return serverMgr.getDefaultServer().filter(beanType);
1112  }
1113
1114  /**
1115   * Execute a Sql Update Delete or Insert statement. This returns the number of
1116   * rows that where updated, deleted or inserted. If is executed in batch then
1117   * this returns -1. You can get the actual rowCount after commit() from
1118   * updateSql.getRowCount().
1119   * <p>
1120   * If you wish to execute a Sql Select natively then you should use the
1121   * FindByNativeSql object.
1122   * </p>
1123   * <p>
1124   * Note that the table modification information is automatically deduced and
1125   * you do not need to call the Ebean.externalModification() method when you
1126   * use this method.
1127   * </p>
1128   * <p>
1129   * Example:
1130   * </p>
1131   * <pre>{@code
1132   *
1133   *   // example that uses 'named' parameters
1134   *   String s = "UPDATE f_topic set post_count = :count where id = :id"
1135   *
1136   *   SqlUpdate update = Ebean.createSqlUpdate(s);
1137   *
1138   *   update.setParameter("id", 1);
1139   *   update.setParameter("count", 50);
1140   *
1141   *   int modifiedCount = Ebean.execute(update);
1142   *
1143   *   String msg = "There where " + modifiedCount + "rows updated";
1144   *
1145   * }</pre>
1146   *
1147   * @param sqlUpdate the update sql potentially with bind values
1148   * @return the number of rows updated or deleted. -1 if executed in batch.
1149   * @see SqlUpdate
1150   * @see CallableSql
1151   * @see Ebean#execute(CallableSql)
1152   */
1153  public static int execute(SqlUpdate sqlUpdate) {
1154    return serverMgr.getDefaultServer().execute(sqlUpdate);
1155  }
1156
1157  /**
1158   * For making calls to stored procedures.
1159   * <p>
1160   * Example:
1161   * </p>
1162   * <pre>{@code
1163   *
1164   *   String sql = "{call sp_order_modify(?,?,?)}";
1165   *
1166   *   CallableSql cs = Ebean.createCallableSql(sql);
1167   *   cs.setParameter(1, 27);
1168   *   cs.setParameter(2, "SHIPPED");
1169   *   cs.registerOut(3, Types.INTEGER);
1170   *
1171   *   Ebean.execute(cs);
1172   *
1173   *   // read the out parameter
1174   *   Integer returnValue = (Integer) cs.getObject(3);
1175   *
1176   * }</pre>
1177   *
1178   * @see CallableSql
1179   * @see Ebean#execute(SqlUpdate)
1180   */
1181  public static int execute(CallableSql callableSql) {
1182    return serverMgr.getDefaultServer().execute(callableSql);
1183  }
1184
1185  /**
1186   * Execute a TxRunnable in a Transaction with an explicit scope.
1187   * <p>
1188   * The scope can control the transaction type, isolation and rollback
1189   * semantics.
1190   * </p>
1191   * <pre>{@code
1192   *
1193   *   // set specific transactional scope settings
1194   *   TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
1195   *
1196   *   Ebean.execute(scope, new TxRunnable() {
1197   *       public void run() {
1198   *               User u1 = Ebean.find(User.class, 1);
1199   *               ...
1200   *       }
1201   *   });
1202   *
1203   * }</pre>
1204   */
1205  public static void execute(TxScope scope, Runnable r) {
1206    serverMgr.getDefaultServer().execute(scope, r);
1207  }
1208
1209  /**
1210   * Execute a Runnable in a Transaction with the default scope.
1211   * <p>
1212   * The default scope runs with REQUIRED and by default will rollback on any
1213   * exception (checked or runtime).
1214   * </p>
1215   * <pre>{@code
1216   *
1217   *   Ebean.execute(() -> {
1218   *
1219   *       User u1 = Ebean.find(User.class, 1);
1220   *       User u2 = Ebean.find(User.class, 2);
1221   *
1222   *       u1.setName("u1 mod");
1223   *       u2.setName("u2 mod");
1224   *
1225   *       Ebean.save(u1);
1226   *       Ebean.save(u2);
1227   *
1228   *   });
1229   *
1230   * }</pre>
1231   */
1232  public static void execute(Runnable r) {
1233    serverMgr.getDefaultServer().execute(r);
1234  }
1235
1236  /**
1237   * Execute a Callable in a Transaction with an explicit scope.
1238   * <p>
1239   * The scope can control the transaction type, isolation and rollback
1240   * semantics.
1241   * </p>
1242   * <pre>{@code
1243   *
1244   *   // set specific transactional scope settings
1245   *   TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
1246   *
1247   *   Ebean.executeCall(scope, new Callable<String>() {
1248   *       public String call() {
1249   *               User u1 = Ebean.find(User.class, 1);
1250   *               ...
1251   *               return u1.getEmail();
1252   *       }
1253   *   });
1254   *
1255   * }</pre>
1256   */
1257  public static <T> T executeCall(TxScope scope, Callable<T> c) {
1258    return serverMgr.getDefaultServer().executeCall(scope, c);
1259  }
1260
1261  /**
1262   * Execute a Callable in a Transaction with the default scope.
1263   * <p>
1264   * The default scope runs with REQUIRED and by default will rollback on any
1265   * exception (checked or runtime).
1266   * </p>
1267   * <p>
1268   * This is basically the same as TxRunnable except that it returns an Object
1269   * (and you specify the return type via generics).
1270   * </p>
1271   * <pre>{@code
1272   *
1273   *   Ebean.executeCall(() -> {
1274   *
1275   *       User u1 = Ebean.find(User.class, 1);
1276   *       User u2 = Ebean.find(User.class, 2);
1277   *
1278   *       u1.setName("u1 mod");
1279   *       u2.setName("u2 mod");
1280   *
1281   *       Ebean.save(u1);
1282   *       Ebean.save(u2);
1283   *
1284   *       return u1.getEmail();
1285   *
1286   *   });
1287   *
1288   * }</pre>
1289   */
1290  public static <T> T executeCall(Callable<T> c) {
1291    return serverMgr.getDefaultServer().executeCall(c);
1292  }
1293
1294  /**
1295   * Inform Ebean that tables have been modified externally. These could be the
1296   * result of from calling a stored procedure, other JDBC calls or external
1297   * programs including other frameworks.
1298   * <p>
1299   * If you use Ebean.execute(UpdateSql) then the table modification information
1300   * is automatically deduced and you do not need to call this method yourself.
1301   * </p>
1302   * <p>
1303   * This information is used to invalidate objects out of the cache and
1304   * potentially text indexes. This information is also automatically broadcast
1305   * across the cluster.
1306   * </p>
1307   * <p>
1308   * If there is a transaction then this information is placed into the current
1309   * transactions event information. When the transaction is committed this
1310   * information is registered (with the transaction manager). If this
1311   * transaction is rolled back then none of the transaction event information
1312   * registers including the information you put in via this method.
1313   * </p>
1314   * <p>
1315   * If there is NO current transaction when you call this method then this
1316   * information is registered immediately (with the transaction manager).
1317   * </p>
1318   *
1319   * @param tableName the name of the table that was modified
1320   * @param inserts   true if rows where inserted into the table
1321   * @param updates   true if rows on the table where updated
1322   * @param deletes   true if rows on the table where deleted
1323   */
1324  public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
1325
1326    serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes);
1327  }
1328
1329  /**
1330   * Return the BeanState for a given entity bean.
1331   * <p>
1332   * This will return null if the bean is not an enhanced entity bean.
1333   * </p>
1334   */
1335  public static BeanState getBeanState(Object bean) {
1336    return serverMgr.getDefaultServer().getBeanState(bean);
1337  }
1338
1339  /**
1340   * Return the manager of the server cache ("L2" cache).
1341   */
1342  public static ServerCacheManager getServerCacheManager() {
1343    return serverMgr.getDefaultServer().getServerCacheManager();
1344  }
1345
1346  /**
1347   * Return the BackgroundExecutor service for asynchronous processing of
1348   * queries.
1349   */
1350  public static BackgroundExecutor getBackgroundExecutor() {
1351    return serverMgr.getDefaultServer().getBackgroundExecutor();
1352  }
1353
1354  /**
1355   * Return the JsonContext for reading/writing JSON.
1356   */
1357  public static JsonContext json() {
1358    return serverMgr.getDefaultServer().json();
1359  }
1360
1361}