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