From cc200e860728db3520b6dd8185069ebcf82287df Mon Sep 17 00:00:00 2001
From: rbygrave
- * This service is used internally by Ebean for executing background tasks such - * as the {@link Query#findFutureList()} and also for executing background tasks - * periodically. - *
- *- * This service has been made available so you can use it for your application - * code if you want. It can be useful for some server caching implementations - * (background population and trimming of the cache etc). - *
- * - * @author rbygrave - */ -public interface BackgroundExecutor { - - /** - * Execute a task in the background. - */ - public void execute(Runnable r); - - /** - * Execute a task periodically with a fixed delay between each execution. - *- * For example, execute a runnable every minute. - *
- *- * The delay is the time between executions no matter how long the task took. - * That is, this method has the same behaviour characteristics as - * {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)} - *
- */ - public void executePeriodically(Runnable r, long delay, TimeUnit unit); -} +package com.avaje.ebean; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Background thread pool service for executing of tasks asynchronously. + *+ * This service is used internally by Ebean for executing background tasks such + * as the {@link Query#findFutureList()} and also for executing background tasks + * periodically. + *
+ *+ * This service has been made available so you can use it for your application + * code if you want. It can be useful for some server caching implementations + * (background population and trimming of the cache etc). + *
+ * + * @author rbygrave + */ +public interface BackgroundExecutor { + + /** + * Execute a task in the background. + */ + void execute(Runnable r); + + /** + * Execute a task periodically with a fixed delay between each execution. + *+ * For example, execute a runnable every minute. + *
+ *+ * The delay is the time between executions no matter how long the task took. + * That is, this method has the same behaviour characteristics as + * {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)} + *
+ */ + void executePeriodically(Runnable r, long delay, TimeUnit unit); +} diff --git a/src/main/java/com/avaje/ebean/BeanState.java b/src/main/java/com/avaje/ebean/BeanState.java index ae290c37a..78017fb03 100644 --- a/src/main/java/com/avaje/ebean/BeanState.java +++ b/src/main/java/com/avaje/ebean/BeanState.java @@ -1,86 +1,86 @@ -package com.avaje.ebean; - -import java.beans.PropertyChangeListener; -import java.util.Map; -import java.util.Set; - -/** - * Provides access to the internal state of an entity bean. - */ -public interface BeanState { - - /** - * Return true if this is a lazy loading reference bean. - *- * If so the this bean only holds the Id property and will invoke lazy loading - * if any other property is get or set. - *
- */ - public boolean isReference(); - - /** - * Return true if the bean is new (and not yet saved). - */ - public boolean isNew(); - - /** - * Return true if the bean is new or dirty (and probably needs to be saved). - */ - public boolean isNewOrDirty(); - - /** - * Return true if the bean has been changed but not yet saved. - */ - public boolean isDirty(); - - /** - * For partially populated beans returns the properties that are loaded on the - * bean. - *- * Accessing another property will cause lazy loading to occur. - *
- */ - public Set- * If a setter is called on a readOnly bean it will throw an exception. - *
- */ - public boolean isReadOnly(); - - /** - * Set the readOnly status for the bean. - */ - public void setReadOnly(boolean readOnly); - - /** - * Add a propertyChangeListener. - */ - public void addPropertyChangeListener(PropertyChangeListener listener); - - /** - * Remove a propertyChangeListener. - */ - public void removePropertyChangeListener(PropertyChangeListener listener); - - /** - * Advanced - Used to programmatically build a partially or fully loaded - * entity bean. First create an entity bean via - * {@link EbeanServer#createEntityBean(Class)}, then populate its properties - * and then call this method specifying which properties where loaded or null - * for a fully loaded entity bean. - */ - public void setLoaded(); +package com.avaje.ebean; + +import java.beans.PropertyChangeListener; +import java.util.Map; +import java.util.Set; + +/** + * Provides access to the internal state of an entity bean. + */ +public interface BeanState { + + /** + * Return true if this is a lazy loading reference bean. + *+ * If so the this bean only holds the Id property and will invoke lazy loading + * if any other property is get or set. + *
+ */ + boolean isReference(); + + /** + * Return true if the bean is new (and not yet saved). + */ + boolean isNew(); + + /** + * Return true if the bean is new or dirty (and probably needs to be saved). + */ + boolean isNewOrDirty(); + + /** + * Return true if the bean has been changed but not yet saved. + */ + boolean isDirty(); + + /** + * For partially populated beans returns the properties that are loaded on the + * bean. + *+ * Accessing another property will cause lazy loading to occur. + *
+ */ + Set+ * If a setter is called on a readOnly bean it will throw an exception. + *
+ */ + boolean isReadOnly(); + + /** + * Set the readOnly status for the bean. + */ + void setReadOnly(boolean readOnly); + + /** + * Add a propertyChangeListener. + */ + void addPropertyChangeListener(PropertyChangeListener listener); + + /** + * Remove a propertyChangeListener. + */ + void removePropertyChangeListener(PropertyChangeListener listener); + + /** + * Advanced - Used to programmatically build a partially or fully loaded + * entity bean. First create an entity bean via + * {@link EbeanServer#createEntityBean(Class)}, then populate its properties + * and then call this method specifying which properties where loaded or null + * for a fully loaded entity bean. + */ + void setLoaded(); } \ No newline at end of file diff --git a/src/main/java/com/avaje/ebean/CallableSql.java b/src/main/java/com/avaje/ebean/CallableSql.java index d6e13f635..f29f22ee0 100644 --- a/src/main/java/com/avaje/ebean/CallableSql.java +++ b/src/main/java/com/avaje/ebean/CallableSql.java @@ -85,17 +85,17 @@ public interface CallableSql { /** * Set the label that is put in the transaction log. */ - public CallableSql setLabel(String label); + CallableSql setLabel(String label); /** * Return the statement execution timeout. */ - public int getTimeout(); + int getTimeout(); /** * Return the callable sql. */ - public String getSql(); + String getSql(); /** * Set the statement execution timeout. Zero implies unlimited time. @@ -103,12 +103,12 @@ public interface CallableSql { * This is set to the underlying CallableStatement. * */ - public CallableSql setTimeout(int secs); + CallableSql setTimeout(int secs); /** * Set the callable sql. */ - public CallableSql setSql(String sql); + CallableSql setSql(String sql); /** * Bind a parameter that is bound as a IN parameter. @@ -125,7 +125,7 @@ public interface CallableSql { * @param value * the value of the parameter. */ - public CallableSql bind(int position, Object value); + CallableSql bind(int position, Object value); /** * Bind a positioned parameter (same as bind method). @@ -135,7 +135,7 @@ public interface CallableSql { * @param value * the value of the parameter. */ - public CallableSql setParameter(int position, Object value); + CallableSql setParameter(int position, Object value); /** * Register an OUT parameter. @@ -153,7 +153,7 @@ public interface CallableSql { * @param type * the jdbc type of the OUT parameter that will be read. */ - public CallableSql registerOut(int position, int type); + CallableSql registerOut(int position, int type); /** * Return an OUT parameter value. @@ -165,7 +165,7 @@ public interface CallableSql { * in batch mode you effectively can't use this method. * */ - public Object getObject(int position); + Object getObject(int position); /** * @@ -173,7 +173,7 @@ public interface CallableSql { * stored procedure calls. This would be the case when ResultSets are returned * etc. */ - public boolean executeOverride(CallableStatement cstmt) throws SQLException; + boolean executeOverride(CallableStatement cstmt) throws SQLException; /** * Add table modification information to the TransactionEvent. @@ -188,7 +188,6 @@ public interface CallableSql { * delete. * */ - public CallableSql addModification(String tableName, boolean inserts, boolean updates, - boolean deletes); + CallableSql addModification(String tableName, boolean inserts, boolean updates, boolean deletes); } \ No newline at end of file diff --git a/src/main/java/com/avaje/ebean/Ebean.java b/src/main/java/com/avaje/ebean/Ebean.java index 006753624..cc6a42b31 100644 --- a/src/main/java/com/avaje/ebean/Ebean.java +++ b/src/main/java/com/avaje/ebean/Ebean.java @@ -1,1501 +1,1501 @@ -package com.avaje.ebean; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.persistence.OptimisticLockException; -import javax.persistence.PersistenceException; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.avaje.ebean.annotation.CacheStrategy; -import com.avaje.ebean.cache.ServerCacheManager; -import com.avaje.ebean.config.ServerConfig; -import com.avaje.ebean.text.csv.CsvReader; -import com.avaje.ebean.text.json.JsonContext; - -/** - * This Ebean object is effectively a singleton that holds a map of registered - * {@link EbeanServer}s. It additionally provides a convenient way to use the - * 'default/primary' EbeanServer. - *- * If you are using a Dependency Injection framework such as - * Spring or Guice you will probably - * NOT use this Ebean singleton object. Instead you will - * configure and construct EbeanServer instances using {@link ServerConfig} and - * {@link EbeanServerFactory} and inject those EbeanServer instances into your - * data access objects. - *
- *- * In documentation "Ebean singleton" refers to this object. - *
- *- * For developer convenience Ebean has static methods that proxy through to the - * methods on the 'default' EbeanServer. These methods are provided for - * developers who are mostly using a single database. Many developers will be - * able to use the methods on Ebean rather than get a EbeanServer. - *
- *- * EbeanServers can be created and used without ever needing or using the Ebean - * singleton. Refer to {@link ServerConfig#setRegister(boolean)}. - *
- *- * You can either programmatically create/register EbeanServers via - * {@link EbeanServerFactory} or they can automatically be created and - * registered when you first use the Ebean singleton. When EbeanServers are - * created automatically they are configured using information in the - * ebean.properties file. - *
- * - *{@code
- *
- * // fetch shipped orders (and also their customer)
- * List list = Ebean.find(Order.class)
- * .fetch("customer")
- * .where()
- * .eq("status.code", Order.Status.SHIPPED)
- * .findList();
- *
- * // read/use the order list ...
- * for (Order order : list) {
- * Customer customer = order.getCustomer();
- * ...
- * }
- *
- * }
- *
- * {@code
- *
- * // fetch order 10, modify and save
- * Order order = Ebean.find(Order.class, 10);
- *
- * OrderStatus shipped = Ebean.getReference(OrderStatus.class,"SHIPPED");
- * order.setStatus(shipped);
- * order.setShippedDate(shippedDate);
- * ...
- *
- * // implicitly creates a transaction and commits
- * Ebean.save(order);
- *
- * }
- *
- * - * When you have multiple databases and need access to a specific one the - * {@link #getServer(String)} method provides access to the EbeanServer for that - * specific database. - *
- * - * {@code
- *
- * // Get access to the Human Resources EbeanServer/Database
- * EbeanServer hrDb = Ebean.getServer("hr");
- *
- *
- * // fetch contact 3 from the HR database
- * Contact contact = hrDb.find(Contact.class, 3);
- *
- * contact.setName("I'm going to change");
- * ...
- *
- * // save the contact back to the HR database
- * hrDb.save(contact);
- *
- * }
- */
-public final class Ebean {
- private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
-
- /**
- * Manages creation and cache of EbeanServers.
- */
- private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager();
-
- /**
- * Helper class for managing fast and safe access and creation of
- * EbeanServers.
- */
- private static final class ServerManager {
-
- /**
- * Cache for fast concurrent read access.
- */
- private final ConcurrentHashMap- * This is provided to access EbeanServer for databases other than the - * 'default' database. EbeanServer also provides more control over - * transactions and the ability to use transactions created externally to - * Ebean. - *
- * - *{@code
- * // use the "hr" database
- * EbeanServer hrDatabase = Ebean.getServer("hr");
- *
- * Person person = hrDatabase.find(Person.class, 10);
- * }
- *
- * @param name
- * the name of the server, use null for the 'default server'
- */
- public static EbeanServer getServer(String name) {
- return serverMgr.get(name);
- }
-
- /**
- * Return the ExpressionFactory from the default server.
- * - * The ExpressionFactory is used internally by the query and ExpressionList to - * build the WHERE and HAVING clauses. Alternatively you can use the - * ExpressionFactory directly to create expressions to add to the query where - * clause. - *
- *- * Alternatively you can use the {@link Expr} as a shortcut to the - * ExpressionFactory of the 'Default' EbeanServer. - *
- *- * You generally need to the an ExpressionFactory (or {@link Expr}) to build - * an expression that uses OR like Expression e = Expr.or(..., ...); - *
- */ - public static ExpressionFactory getExpressionFactory() { - return serverMgr.getPrimaryServer().getExpressionFactory(); - } - - /** - * Register the server with this Ebean singleton. Specify if the registered - * server is the primary/default server. - */ - public static void register(EbeanServer server, boolean isPrimaryServer) { - serverMgr.register(server, isPrimaryServer); - } - - /** - * Backdoor for registering a mock implementation of EbeanServer as the default server. - */ - protected static EbeanServer mock(String name, EbeanServer server, boolean isPrimaryServer) { - EbeanServer originalPrimaryServer = serverMgr.primaryServer; - serverMgr.registerWithName(name, server, isPrimaryServer); - return originalPrimaryServer; - } - - /** - * Return the next identity value for a given bean type. - *- * This will only work when a IdGenerator is on this bean type such as a DB - * sequence or UUID. - *
- *- * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do - * not need to use this method generally. It is made available for more - * complex cases where it is useful to get an ID prior to some processing. - *
- */ - public static Object nextId(Class> beanType) { - return serverMgr.getPrimaryServer().nextId(beanType); - } - - /** - * Start a new explicit transaction. - *- * The transaction is stored in a ThreadLocal variable and typically you only - * need to use the returned Transaction IF you wish to do things like - * use batch mode, change the transaction isolation level, use savepoints or - * log comments to the transaction log. - *
- *- * Example of using a transaction to span multiple calls to find(), save() - * etc. - *
- * - *{@code
- *
- * // start a transaction (stored in a ThreadLocal)
- * Ebean.beginTransaction();
- * try {
- * Order order = Ebean.find(Order.class,10); ...
- *
- * Ebean.save(order);
- *
- * Ebean.commitTransaction();
- *
- * } finally {
- * // rollback if we didn't commit
- * // i.e. an exception occurred before commitTransaction().
- * Ebean.endTransaction();
- * }
- *
- * }
- *
- * - * If you want to externalise the transaction management then you should be - * able to do this via EbeanServer. Specifically with EbeanServer you can pass - * the transaction to the various find() and save() execute() methods. This - * gives you the ability to create the transactions yourself externally from - * Ebean and pass those transactions through to the various methods available - * on EbeanServer. - *
- */ - public static Transaction beginTransaction() { - return serverMgr.getPrimaryServer().beginTransaction(); - } - - /** - * Start a transaction additionally specifying the isolation level. - * - * @param isolation - * the Transaction isolation level - * - */ - public static Transaction beginTransaction(TxIsolation isolation) { - return serverMgr.getPrimaryServer().beginTransaction(isolation); - } - - /** - * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics. - * - *- * Note that this provides an try finally alternative to using {@link #execute(TxScope, TxCallable)} or - * {@link #execute(TxScope, TxRunnable)}. - *
- * - *{@code
- * // Start a new transaction. If there is a current transaction
- * // suspend it until this transaction ends
- * Transaction txn = Ebean.beginTransaction(TxScope.requiresNew());
- * try {
- *
- * ...
- *
- * // commit the transaction
- * txn.commit();
- *
- * } finally {
- * // end this transaction which:
- * // A) will rollback transaction if it has not been committed already
- * // B) will restore a previously suspended transaction
- * txn.end();
- * }
- *
- * }
- *
- * {@code
- *
- * // start a new transaction if there is not a current transaction
- * Transaction txn = Ebean.beginTransaction(TxScope.required());
- * try {
- *
- * ...
- *
- * // commit the transaction if it was created or
- * // do nothing if there was already a current transaction
- * txn.commit();
- *
- * } finally {
- * // end this transaction which will rollback the transaction
- * // if it was created for this try finally scope and has not
- * // already been committed
- * txn.end();
- * }
- *
- * }
- */
- public static Transaction beginTransaction(TxScope scope){
- return serverMgr.getPrimaryServer().beginTransaction(scope);
- }
-
- /**
- * Returns the current transaction or null if there is no current transaction
- * in scope.
- */
- public static Transaction currentTransaction() {
- return serverMgr.getPrimaryServer().currentTransaction();
- }
-
- /**
- * Register a TransactionCallback on the currently active transaction.
- *
- * If there is no currently active transaction then a PersistenceException is thrown.
- *
- * @param transactionCallback the transaction callback to be registered with the current transaction
- *
- * @throws PersistenceException if there is no currently active transaction
- */
- public static void register(TransactionCallback transactionCallback) throws PersistenceException {
- serverMgr.getPrimaryServer().register(transactionCallback);
- }
-
- /**
- * Commit the current transaction.
- */
- public static void commitTransaction() {
- serverMgr.getPrimaryServer().commitTransaction();
- }
-
- /**
- * Rollback the current transaction.
- */
- public static void rollbackTransaction() {
- serverMgr.getPrimaryServer().rollbackTransaction();
- }
-
- /**
- * If the current transaction has already been committed do nothing otherwise
- * rollback the transaction.
- * - * Useful to put in a finally block to ensure the transaction is ended, rather - * than a rollbackTransaction() in each catch block. - *
- *- * Code example: - *
- * - *{@code
- * Ebean.beginTransaction();
- * try {
- * // do some fetching and or persisting
- *
- * // commit at the end
- * Ebean.commitTransaction();
- *
- * } finally {
- * // if commit didn't occur then rollback the transaction
- * Ebean.endTransaction();
- * }
- * }
- */
- public static void endTransaction() {
- serverMgr.getPrimaryServer().endTransaction();
- }
-
- /**
- * Return a map of the differences between two objects of the same type.
- * - * When null is passed in for b, then the 'OldValues' of a is used for the - * difference comparison. - *
- */ - public static Map- * If there is no current transaction one will be created and committed for - * you automatically. - *
- *- * Save can cascade along relationships. For this to happen you need to - * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the - * OneToMany, OneToOne or ManyToMany annotation. - *
- *- * In this example below the details property has a CascadeType.ALL set so - * saving an order will also save all its details. - *
- * - *{@code
- * public class Order { ...
- *
- * @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
- * @JoinColumn(name="order_id")
- * List details;
- * ...
- * }
- * }
- *
- * - * When a save cascades via a OneToMany or ManyToMany Ebean will automatically - * set the 'parent' object to the 'detail' object. In the example below in - * saving the order and cascade saving the order details the 'parent' order - * will be set against each order detail when it is saved. - *
- */ - public static void save(Object bean) throws OptimisticLockException { - serverMgr.getPrimaryServer().save(bean); - } - - /** - * Insert the bean. This is useful when you set the Id property on a bean and - * want to explicitly insert it. - */ - public static void insert(Object bean) { - serverMgr.getPrimaryServer().insert(bean); - } - - /** - * Insert a collection of beans. - */ - public static void insert(Collection> beans) { - serverMgr.getPrimaryServer().insert(beans); - } - - /** - * Marks the entity bean as dirty. - *- * This is used so that when a bean that is otherwise unmodified is updated with the version - * property updated. - *
- * An unmodified bean that is saved or updated is normally skipped and this marks the bean as - * dirty so that it is not skipped. - * - *
{@code
- *
- * Customer customer = Ebean.find(Customer, id);
- *
- * // mark the bean as dirty so that a save() or update() will
- * // increment the version property
- * Ebean.markAsDirty(customer);
- * Ebean.save(customer);
- *
- * }
- */
- public static void markAsDirty(Object bean) throws OptimisticLockException {
- serverMgr.getPrimaryServer().markAsDirty(bean);
- }
-
- /**
- * Saves the bean using an update. If you know you are updating a bean then it is preferrable to
- * use this update() method rather than save().
- * - * Stateless updates: Note that the bean does not have to be previously fetched to call - * update().You can create a new instance and set some of its properties programmatically for via - * JSON/XML marshalling etc. This is described as a 'stateless update'. - *
- *- * Optimistic Locking: Note that if the version property is not set when update() is - * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used). - *
- *- * {@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: When cascade saving to a - * OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children - * that are in the database but are not in the collection are deleted. - *
- *- * {@link ServerConfig#setUpdateChangesOnly(boolean)}: The updateChangesOnly setting - * controls if only the changed properties are included in the update or if all the loaded - * properties are included instead. - *
- * - *{@code
- *
- * // A 'stateless update' example
- * Customer customer = new Customer();
- * customer.setId(7);
- * customer.setName("ModifiedNameNoOCC");
- * ebeanServer.update(customer);
- *
- * }
- *
- * @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
- * @see ServerConfig#setUpdateChangesOnly(boolean)
- */
- public static void update(Object bean) throws OptimisticLockException {
- serverMgr.getPrimaryServer().update(bean);
- }
-
- /**
- * Update the beans in the collection.
- */
- public static void update(Collection> beans) throws OptimisticLockException {
- serverMgr.getPrimaryServer().update(beans);
- }
-
- /**
- * Save all the beans from an Iterator.
- */
- public static int save(Iterator> iterator) throws OptimisticLockException {
- return serverMgr.getPrimaryServer().save(iterator);
- }
-
- /**
- * Save all the beans from a Collection.
- */
- public static int save(Collection> beans) throws OptimisticLockException {
- return serverMgr.getPrimaryServer().save(beans);
- }
-
- /**
- * Delete the associations (from the intersection table) of a ManyToMany given
- * the owner bean and the propertyName of the ManyToMany collection.
- * - * Typically these deletions occur automatically when persisting a ManyToMany - * collection and this provides a way to invoke those deletions directly. - *
- * - * @return the number of associations deleted (from the intersection table). - */ - public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) { - return serverMgr.getPrimaryServer().deleteManyToManyAssociations(ownerBean, propertyName); - } - - /** - * Save the associations of a ManyToMany given the owner bean and the - * propertyName of the ManyToMany collection. - *- * Typically the saving of these associations (inserting into the intersection - * table) occurs automatically when persisting a ManyToMany. This provides a - * way to invoke those insertions directly. - *
- *- * You can use this when the collection is new and in this case all the - * entries in the collection are treated as additions are result in inserts - * into the intersection table. - *
- */ - public static void saveManyToManyAssociations(Object ownerBean, String propertyName) { - serverMgr.getPrimaryServer().saveManyToManyAssociations(ownerBean, propertyName); - } - - /** - * Save the associated collection or bean given the property name. - *- * This is similar to performing a save cascade on a specific property - * manually/programmatically. - *
- *- * Note that you can turn on/off cascading for a transaction via - * {@link Transaction#setPersistCascade(boolean)} - *
- * - * @param ownerBean - * the bean instance holding the property we want to save - * @param propertyName - * the property we want to save - */ - public static void saveAssociation(Object ownerBean, String propertyName) { - serverMgr.getPrimaryServer().saveAssociation(ownerBean, propertyName); - } - - /** - * Delete the bean. - *- * If there is no current transaction one will be created and committed for - * you automatically. - *
- */ - public static void delete(Object bean) throws OptimisticLockException { - serverMgr.getPrimaryServer().delete(bean); - } - - /** - * Delete the bean given its type and id. - */ - public static int delete(Class> beanType, Object id) { - return serverMgr.getPrimaryServer().delete(beanType, id); - } - - /** - * Delete several beans given their type and id values. - */ - public static void delete(Class> beanType, Collection> ids) { - serverMgr.getPrimaryServer().delete(beanType, ids); - } - - /** - * Delete all the beans from an Iterator. - */ - public static int delete(Iterator> it) throws OptimisticLockException { - return serverMgr.getPrimaryServer().delete(it); - } - - /** - * Delete all the beans from a Collection. - */ - public static int delete(Collection> c) throws OptimisticLockException { - return delete(c.iterator()); - } - - /** - * Refresh the values of a bean. - *- * Note that this resets OneToMany and ManyToMany properties so that if they - * are accessed a lazy load will refresh the many property. - *
- */ - public static void refresh(Object bean) { - serverMgr.getPrimaryServer().refresh(bean); - } - - /** - * Refresh a 'many' property of a bean. - * - *{@code
- *
- * Order order = ...;
- * ...
- * // refresh the order details...
- * Ebean.refreshMany(order, "details");
- *
- * }
- *
- * @param bean
- * the entity bean containing the List Set or Map to refresh.
- * @param manyPropertyName
- * the property name of the List Set or Map to refresh.
- */
- public static void refreshMany(Object bean, String manyPropertyName) {
- serverMgr.getPrimaryServer().refreshMany(bean, manyPropertyName);
- }
-
- /**
- * Get a reference object.
- * - * This is sometimes described as a proxy (with lazy loading). - *
- * - *{@code
- *
- * Product product = Ebean.getReference(Product.class, 1);
- *
- * // You can get the id without causing a fetch/lazy load
- * Integer productId = product.getId();
- *
- * // If you try to get any other property a fetch/lazy loading will occur
- * // This will cause a query to execute...
- * String name = product.getName();
- *
- * }
- *
- * @param beanType
- * the type of entity bean
- * @param id
- * the id value
- */
- public static - * If you leave off any keywords the defaults are ascending order and treating - * nulls as high values. - *
- *- * Note that the sorting uses a Comparator and Collections.sort(); and does - * not invoke a DB query. - *
- * - *{@code
- *
- * // find orders and their customers
- * List list = Ebean.find(Order.class)
- * .fetch("customer")
- * .orderBy("id")
- * .findList();
- *
- * // sort by customer name ascending, then by order shipDate
- * // ... then by the order status descending
- * Ebean.sort(list, "customer.name, shipDate, status desc");
- *
- * // sort by customer name descending (with nulls low)
- * // ... then by the order id
- * Ebean.sort(list, "customer.name desc nullsLow, id");
- *
- * }
- *
- * @param list
- * the list of entity beans
- * @param sortByClause
- * the properties to sort the list by
- */
- public static {@code
- * // Fetch order 1
- * Order order = Ebean.find(Order.class, 1);
- * }
- *
- * - * If you want more control over the query then you can use createQuery() and - * Query.findUnique(); - *
- * - *{@code
- * // ... additionally fetching customer, customer shipping address,
- * // order details, and the product associated with each order detail.
- * // note: only product id and name is fetch (its a "partial object").
- * // note: all other objects use "*" and have all their properties fetched.
- *
- * Query query = Ebean.find(Order.class)
- * .setId(1)
- * .fetch("customer")
- * .fetch("customer.shippingAddress")
- * .fetch("details")
- * .query();
- *
- * // fetch associated products but only fetch their product id and name
- * query.fetch("details.product", "name");
- *
- * // traverse the object graph...
- *
- * Order order = query.findUnique();
- * Customer customer = order.getCustomer();
- * Address shippingAddress = customer.getShippingAddress();
- * List details = order.getDetails();
- * OrderDetail detail0 = details.get(0);
- * Product product = detail0.getProduct();
- * String productName = product.getName();
- *
- * }
- *
- * @param beanType
- * the type of entity bean to fetch
- * @param id
- * the id value
- */
- public static - * Note that you can use raw SQL with entity beans, refer to the SqlSelect - * annotation for examples. - *
- */ - public static SqlQuery createSqlQuery(String sql) { - return serverMgr.getPrimaryServer().createSqlQuery(sql); - } - - /** - * Create a named sql query. - *- * The query statement will be defined in a deployment orm xml file. - *
- * - * @param namedQuery - * the name of the query - */ - public static SqlQuery createNamedSqlQuery(String namedQuery) { - return serverMgr.getPrimaryServer().createNamedSqlQuery(namedQuery); - } - - /** - * Create a sql update for executing native dml statements. - *- * Use this to execute a Insert Update or Delete statement. The statement will - * be native to the database and contain database table and column names. - *
- *- * See {@link SqlUpdate} for example usage. - *
- *- * Where possible it would be expected practice to put the statement in a orm - * xml file (named update) and use {@link #createNamedSqlUpdate(String)} . - *
- */ - public static SqlUpdate createSqlUpdate(String sql) { - return serverMgr.getPrimaryServer().createSqlUpdate(sql); - } - - /** - * Create a CallableSql to execute a given stored procedure. - * - * @see CallableSql - */ - public static CallableSql createCallableSql(String sql) { - return serverMgr.getPrimaryServer().createCallableSql(sql); - } - - /** - * Create a named sql update. - *- * The statement (an Insert Update or Delete statement) will be defined in a - * deployment orm xml file. - *
- * - *{@code
- *
- * // Use a namedQuery
- * UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count");
- *
- * update.setParameter("count", 1);
- * update.setParameter("topicId", 50);
- *
- * int modifiedCount = update.execute();
- *
- * }
- */
- public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
- return serverMgr.getPrimaryServer().createNamedSqlUpdate(namedQuery);
- }
-
- /**
- * Return a named Query that will have defined fetch paths, predicates etc.
- * - * The query is created from a statement that will be defined in a deployment - * orm xml file or NamedQuery annotations. The query will typically already - * define fetch paths, predicates, order by clauses etc so often you will just - * need to bind required parameters and then execute the query. - *
- * - *{@code
- *
- * // example
- * Query query = Ebean.createNamedQuery(Order.class, "new.for.customer");
- * query.setParameter("customerId", 23);
- * List newOrders = query.findList();
- *
- * }
- *
- * @param beanType
- * the class of entity to be fetched
- * @param namedQuery
- * the name of the query
- */
- public static - * Note that you are allowed to add additional clauses using where() as well - * as use fetch() and setOrderBy() after the query has been created. - *
- *- * Note that this method signature used to map to named queries and that has - * moved to {@link #createNamedQuery(Class, String)}. - *
- * - *{@code
- *
- * String q = "find order fetch details where status = :st";
- *
- * List newOrders = Ebean.>findOrder.class, q)
- * .setParameter("st", Order.Status.NEW)
- * .findList();
- *
- * }
- *
- * @param query
- * the object query
- */
- public static - * The orm update differs from the SqlUpdate in that it uses the bean name and - * bean property names rather than table and column names. - *
- *- * Note that named update statements can be specified in raw sql (with column - * and table names) or using bean name and bean property names. This can be - * specified with the isSql flag. - *
- *- * Example named updates: - *
- * - *{@code
- * package app.data;
- *
- * import ...
- *
- * @NamedUpdates(value = {
- * @NamedUpdate( name = "setTitle",
- * isSql = false,
- * notifyCache = false,
- * update = "update topic set title = :title, postCount = :postCount where id = :id"),
- * @NamedUpdate( name = "setPostCount",
- * notifyCache = false,
- * update = "update f_topic set post_count = :postCount where id = :id"),
- * @NamedUpdate( name = "incrementPostCount",
- * notifyCache = false,
- * isSql = false,
- * update = "update Topic set postCount = postCount + 1 where id = :id") })
- * @Entity
- * @Table(name = "f_topic")
- * public class Topic { ...
- *
- * }
- *
- * - * Example using a named update: - *
- * - *{@code
- *
- * Update update = Ebean.createNamedUpdate(Topic.class, "setPostCount");
- * update.setParameter("postCount", 10);
- * update.setParameter("id", 3);
- *
- * int rows = update.execute();
- * System.out.println("rows updated: " + rows);
- *
- * }
- */
- public static - * The orm update differs from the sql update in that it you can use the bean - * name and bean property names rather than table and column names. - *
- *- * An example: - *
- * - *{@code
- *
- * // The bean name and properties - "topic","postCount" and "id"
- *
- * // will be converted into their associated table and column names
- * String updStatement = "update topic set postCount = :pc where id = :id";
- *
- * Update update = Ebean.createUpdate(Topic.class, updStatement);
- *
- * update.set("pc", 9);
- * update.set("id", 3);
- *
- * int rows = update.execute();
- * System.out.println("rows updated:" + rows);
- *
- * }
- */
- public static - * You can use the methods on the Query object to specify fetch paths, - * predicates, order by, limits etc. - *
- *- * You then use findList(), findSet(), findMap() and findUnique() to execute - * the query and return the collection or bean. - *
- *- * Note that a query executed by {@link Query#findList()} - * {@link Query#findSet()} etc will execute against the same EbeanServer from - * which is was created. - *
- * - *{@code
- * // Find order 2 additionally fetching the customer, details and details.product
- * // name.
- *
- * Order order = Ebean.find(Order.class)
- * .fetch("customer")
- * .fetch("details")
- * .fetch("detail.product", "name")
- * .setId(2)
- * .findUnique();
- *
- * // Find order 2 additionally fetching the customer, details and details.product
- * // name.
- * // Note: same query as above but using the query language
- * // Note: using a named query would be preferred practice
- *
- * String oql = "find order fetch customer fetch details fetch details.product (name) where id = :orderId ";
- *
- * Query query = Ebean.find(Order.class);
- * query.setQuery(oql);
- * query.setParameter("orderId", 2);
- *
- * Order order = query.findUnique();
- *
- * // Using a named query
- * Query query = Ebean.find(Order.class, "with.details");
- * query.setParameter("orderId", 2);
- *
- * Order order = query.findUnique();
- *
- * }
- *
- * @param beanType
- * the class of entity to be fetched
- * @return A ORM Query object for this beanType
- */
- public static - * This is actually the same as {@link #createQuery(Class)}. The reason it - * exists is that people used to JPA will probably be looking for a - * createQuery method (the same as entityManager). - *
- * - * @param beanType - * the type of entity bean to find - * @return A ORM Query object for this beanType - */ - public static- * This produces and returns a new list with the sort and filters applied. - *
- *- * Refer to {@link Filter} for an example of its use. - *
- */ - public static- * If you wish to execute a Sql Select natively then you should use the - * FindByNativeSql object. - *
- *- * Note that the table modification information is automatically deduced and - * you do not need to call the Ebean.externalModification() method when you - * use this method. - *
- *- * Example: - *
- * - *{@code
- *
- * // example that uses 'named' parameters
- * String s = "UPDATE f_topic set post_count = :count where id = :id"
- *
- * SqlUpdate update = Ebean.createSqlUpdate(s);
- *
- * update.setParameter("id", 1);
- * update.setParameter("count", 50);
- *
- * int modifiedCount = Ebean.execute(update);
- *
- * String msg = "There where " + modifiedCount + "rows updated";
- *
- * }
- *
- * @param sqlUpdate
- * the update sql potentially with bind values
- *
- * @return the number of rows updated or deleted. -1 if executed in batch.
- *
- * @see SqlUpdate
- * @see CallableSql
- * @see Ebean#execute(CallableSql)
- */
- public static int execute(SqlUpdate sqlUpdate) {
- return serverMgr.getPrimaryServer().execute(sqlUpdate);
- }
-
- /**
- * For making calls to stored procedures.
- * - * Example: - *
- * - *{@code
- *
- * String sql = "{call sp_order_modify(?,?,?)}";
- *
- * CallableSql cs = Ebean.createCallableSql(sql);
- * cs.setParameter(1, 27);
- * cs.setParameter(2, "SHIPPED");
- * cs.registerOut(3, Types.INTEGER);
- *
- * Ebean.execute(cs);
- *
- * // read the out parameter
- * Integer returnValue = (Integer) cs.getObject(3);
- *
- * }
- *
- * @see CallableSql
- * @see Ebean#execute(SqlUpdate)
- */
- public static int execute(CallableSql callableSql) {
- return serverMgr.getPrimaryServer().execute(callableSql);
- }
-
- /**
- * Execute a TxRunnable in a Transaction with an explicit scope.
- * - * The scope can control the transaction type, isolation and rollback - * semantics. - *
- * - *{@code
- *
- * // set specific transactional scope settings
- * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
- *
- * Ebean.execute(scope, new TxRunnable() {
- * public void run() {
- * User u1 = Ebean.find(User.class, 1);
- * ...
- * }
- * });
- *
- * }
- */
- public static void execute(TxScope scope, TxRunnable r) {
- serverMgr.getPrimaryServer().execute(scope, r);
- }
-
- /**
- * Execute a TxRunnable in a Transaction with the default scope.
- * - * The default scope runs with REQUIRED and by default will rollback on any - * exception (checked or runtime). - *
- * - *{@code
- *
- * Ebean.execute(new TxRunnable() {
- * public void run() {
- * User u1 = Ebean.find(User.class, 1);
- * User u2 = Ebean.find(User.class, 2);
- *
- * u1.setName("u1 mod");
- * u2.setName("u2 mod");
- *
- * Ebean.save(u1);
- * Ebean.save(u2);
- * }
- * });
- *
- * }
- */
- public static void execute(TxRunnable r) {
- serverMgr.getPrimaryServer().execute(r);
- }
-
- /**
- * Execute a TxCallable in a Transaction with an explicit scope.
- * - * The scope can control the transaction type, isolation and rollback - * semantics. - *
- * - *{@code
- *
- * // set specific transactional scope settings
- * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
- *
- * Ebean.execute(scope, new TxCallable() {
- * public String call() {
- * User u1 = Ebean.find(User.class, 1);
- * ...
- * return u1.getEmail();
- * }
- * });
- *
- * }
- *
- */
- public static - * The default scope runs with REQUIRED and by default will rollback on any - * exception (checked or runtime). - *
- *- * This is basically the same as TxRunnable except that it returns an Object - * (and you specify the return type via generics). - *
- * - *{@code
- *
- * Ebean.execute(new TxCallable() {
- * public String call() {
- * User u1 = Ebean.find(User.class, 1);
- * User u2 = Ebean.find(User.class, 2);
- *
- * u1.setName("u1 mod");
- * u2.setName("u2 mod");
- *
- * Ebean.save(u1);
- * Ebean.save(u2);
- *
- * return u1.getEmail();
- * }
- * });
- *
- * }
- */
- public static - * If you use Ebean.execute(UpdateSql) then the table modification information - * is automatically deduced and you do not need to call this method yourself. - *
- *- * This information is used to invalidate objects out of the cache and - * potentially text indexes. This information is also automatically broadcast - * across the cluster. - *
- *- * If there is a transaction then this information is placed into the current - * transactions event information. When the transaction is committed this - * information is registered (with the transaction manager). If this - * transaction is rolled back then none of the transaction event information - * registers including the information you put in via this method. - *
- *- * If there is NO current transaction when you call this method then this - * information is registered immediately (with the transaction manager). - *
- * - * @param tableName - * the name of the table that was modified - * @param inserts - * true if rows where inserted into the table - * @param updates - * true if rows on the table where updated - * @param deletes - * true if rows on the table where deleted - */ - public static void externalModification(String tableName, boolean inserts, boolean updates, - boolean deletes) { - - serverMgr.getPrimaryServer().externalModification(tableName, inserts, updates, deletes); - } - - /** - * Return the BeanState for a given entity bean. - *- * This will return null if the bean is not an enhanced entity bean. - *
- */ - public static BeanState getBeanState(Object bean) { - return serverMgr.getPrimaryServer().getBeanState(bean); - } - - /** - * Return the manager of the server cache ("L2" cache). - * - */ - public static ServerCacheManager getServerCacheManager() { - return serverMgr.getPrimaryServer().getServerCacheManager(); - } - - /** - * Return the BackgroundExecutor service for asynchronous processing of - * queries. - */ - public static BackgroundExecutor getBackgroundExecutor() { - return serverMgr.getPrimaryServer().getBackgroundExecutor(); - } - - /** - * Run the cache warming queries on all bean types that have one defined for - * the default/primary EbeanServer. - *- * A cache warming query can be defined via {@link CacheStrategy}. - *
- */ - public static void runCacheWarming() { - serverMgr.getPrimaryServer().runCacheWarming(); - } - - /** - * Run the cache warming query for a specific bean type for the - * default/primary EbeanServer. - *- * A cache warming query can be defined via {@link CacheStrategy}. - *
- */ - public static void runCacheWarming(Class> beanType) { - - serverMgr.getPrimaryServer().runCacheWarming(beanType); - } - - /** - * Return the JsonContext for reading/writing JSON. - */ - public static JsonContext json() { - return serverMgr.getPrimaryServer().json(); - } - - /** - * Return the JsonContext for reading/writing JSON. - * @deprecated Please use #json instead. - */ - public static JsonContext createJsonContext() { - return json(); - } - -} +package com.avaje.ebean; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.persistence.OptimisticLockException; +import javax.persistence.PersistenceException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.avaje.ebean.annotation.CacheStrategy; +import com.avaje.ebean.cache.ServerCacheManager; +import com.avaje.ebean.config.ServerConfig; +import com.avaje.ebean.text.csv.CsvReader; +import com.avaje.ebean.text.json.JsonContext; + +/** + * This Ebean object is effectively a singleton that holds a map of registered + * {@link EbeanServer}s. It additionally provides a convenient way to use the + * 'default/primary' EbeanServer. + *+ * If you are using a Dependency Injection framework such as + * Spring or Guice you will probably + * NOT use this Ebean singleton object. Instead you will + * configure and construct EbeanServer instances using {@link ServerConfig} and + * {@link EbeanServerFactory} and inject those EbeanServer instances into your + * data access objects. + *
+ *+ * In documentation "Ebean singleton" refers to this object. + *
+ *+ * For developer convenience Ebean has static methods that proxy through to the + * methods on the 'default' EbeanServer. These methods are provided for + * developers who are mostly using a single database. Many developers will be + * able to use the methods on Ebean rather than get a EbeanServer. + *
+ *+ * EbeanServers can be created and used without ever needing or using the Ebean + * singleton. Refer to {@link ServerConfig#setRegister(boolean)}. + *
+ *+ * You can either programmatically create/register EbeanServers via + * {@link EbeanServerFactory} or they can automatically be created and + * registered when you first use the Ebean singleton. When EbeanServers are + * created automatically they are configured using information in the + * ebean.properties file. + *
+ * + *{@code
+ *
+ * // fetch shipped orders (and also their customer)
+ * List list = Ebean.find(Order.class)
+ * .fetch("customer")
+ * .where()
+ * .eq("status.code", Order.Status.SHIPPED)
+ * .findList();
+ *
+ * // read/use the order list ...
+ * for (Order order : list) {
+ * Customer customer = order.getCustomer();
+ * ...
+ * }
+ *
+ * }
+ *
+ * {@code
+ *
+ * // fetch order 10, modify and save
+ * Order order = Ebean.find(Order.class, 10);
+ *
+ * OrderStatus shipped = Ebean.getReference(OrderStatus.class,"SHIPPED");
+ * order.setStatus(shipped);
+ * order.setShippedDate(shippedDate);
+ * ...
+ *
+ * // implicitly creates a transaction and commits
+ * Ebean.save(order);
+ *
+ * }
+ *
+ * + * When you have multiple databases and need access to a specific one the + * {@link #getServer(String)} method provides access to the EbeanServer for that + * specific database. + *
+ * + * {@code
+ *
+ * // Get access to the Human Resources EbeanServer/Database
+ * EbeanServer hrDb = Ebean.getServer("hr");
+ *
+ *
+ * // fetch contact 3 from the HR database
+ * Contact contact = hrDb.find(Contact.class, 3);
+ *
+ * contact.setName("I'm going to change");
+ * ...
+ *
+ * // save the contact back to the HR database
+ * hrDb.save(contact);
+ *
+ * }
+ */
+public final class Ebean {
+ private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
+
+ /**
+ * Manages creation and cache of EbeanServers.
+ */
+ private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager();
+
+ /**
+ * Helper class for managing fast and safe access and creation of
+ * EbeanServers.
+ */
+ private static final class ServerManager {
+
+ /**
+ * Cache for fast concurrent read access.
+ */
+ private final ConcurrentHashMap+ * This is provided to access EbeanServer for databases other than the + * 'default' database. EbeanServer also provides more control over + * transactions and the ability to use transactions created externally to + * Ebean. + *
+ * + *{@code
+ * // use the "hr" database
+ * EbeanServer hrDatabase = Ebean.getServer("hr");
+ *
+ * Person person = hrDatabase.find(Person.class, 10);
+ * }
+ *
+ * @param name
+ * the name of the server, use null for the 'default server'
+ */
+ public static EbeanServer getServer(String name) {
+ return serverMgr.get(name);
+ }
+
+ /**
+ * Return the ExpressionFactory from the default server.
+ * + * The ExpressionFactory is used internally by the query and ExpressionList to + * build the WHERE and HAVING clauses. Alternatively you can use the + * ExpressionFactory directly to create expressions to add to the query where + * clause. + *
+ *+ * Alternatively you can use the {@link Expr} as a shortcut to the + * ExpressionFactory of the 'Default' EbeanServer. + *
+ *+ * You generally need to the an ExpressionFactory (or {@link Expr}) to build + * an expression that uses OR like Expression e = Expr.or(..., ...); + *
+ */ + public static ExpressionFactory getExpressionFactory() { + return serverMgr.getPrimaryServer().getExpressionFactory(); + } + + /** + * Register the server with this Ebean singleton. Specify if the registered + * server is the primary/default server. + */ + public static void register(EbeanServer server, boolean isPrimaryServer) { + serverMgr.register(server, isPrimaryServer); + } + + /** + * Backdoor for registering a mock implementation of EbeanServer as the default server. + */ + protected static EbeanServer mock(String name, EbeanServer server, boolean isPrimaryServer) { + EbeanServer originalPrimaryServer = serverMgr.primaryServer; + serverMgr.registerWithName(name, server, isPrimaryServer); + return originalPrimaryServer; + } + + /** + * Return the next identity value for a given bean type. + *+ * This will only work when a IdGenerator is on this bean type such as a DB + * sequence or UUID. + *
+ *+ * For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do + * not need to use this method generally. It is made available for more + * complex cases where it is useful to get an ID prior to some processing. + *
+ */ + public static Object nextId(Class> beanType) { + return serverMgr.getPrimaryServer().nextId(beanType); + } + + /** + * Start a new explicit transaction. + *+ * The transaction is stored in a ThreadLocal variable and typically you only + * need to use the returned Transaction IF you wish to do things like + * use batch mode, change the transaction isolation level, use savepoints or + * log comments to the transaction log. + *
+ *+ * Example of using a transaction to span multiple calls to find(), save() + * etc. + *
+ * + *{@code
+ *
+ * // start a transaction (stored in a ThreadLocal)
+ * Ebean.beginTransaction();
+ * try {
+ * Order order = Ebean.find(Order.class,10); ...
+ *
+ * Ebean.save(order);
+ *
+ * Ebean.commitTransaction();
+ *
+ * } finally {
+ * // rollback if we didn't commit
+ * // i.e. an exception occurred before commitTransaction().
+ * Ebean.endTransaction();
+ * }
+ *
+ * }
+ *
+ * + * If you want to externalise the transaction management then you should be + * able to do this via EbeanServer. Specifically with EbeanServer you can pass + * the transaction to the various find() and save() execute() methods. This + * gives you the ability to create the transactions yourself externally from + * Ebean and pass those transactions through to the various methods available + * on EbeanServer. + *
+ */ + public static Transaction beginTransaction() { + return serverMgr.getPrimaryServer().beginTransaction(); + } + + /** + * Start a transaction additionally specifying the isolation level. + * + * @param isolation + * the Transaction isolation level + * + */ + public static Transaction beginTransaction(TxIsolation isolation) { + return serverMgr.getPrimaryServer().beginTransaction(isolation); + } + + /** + * Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics. + * + *+ * Note that this provides an try finally alternative to using {@link #execute(TxScope, TxCallable)} or + * {@link #execute(TxScope, TxRunnable)}. + *
+ * + *{@code
+ * // Start a new transaction. If there is a current transaction
+ * // suspend it until this transaction ends
+ * Transaction txn = Ebean.beginTransaction(TxScope.requiresNew());
+ * try {
+ *
+ * ...
+ *
+ * // commit the transaction
+ * txn.commit();
+ *
+ * } finally {
+ * // end this transaction which:
+ * // A) will rollback transaction if it has not been committed already
+ * // B) will restore a previously suspended transaction
+ * txn.end();
+ * }
+ *
+ * }
+ *
+ * {@code
+ *
+ * // start a new transaction if there is not a current transaction
+ * Transaction txn = Ebean.beginTransaction(TxScope.required());
+ * try {
+ *
+ * ...
+ *
+ * // commit the transaction if it was created or
+ * // do nothing if there was already a current transaction
+ * txn.commit();
+ *
+ * } finally {
+ * // end this transaction which will rollback the transaction
+ * // if it was created for this try finally scope and has not
+ * // already been committed
+ * txn.end();
+ * }
+ *
+ * }
+ */
+ public static Transaction beginTransaction(TxScope scope){
+ return serverMgr.getPrimaryServer().beginTransaction(scope);
+ }
+
+ /**
+ * Returns the current transaction or null if there is no current transaction
+ * in scope.
+ */
+ public static Transaction currentTransaction() {
+ return serverMgr.getPrimaryServer().currentTransaction();
+ }
+
+ /**
+ * Register a TransactionCallback on the currently active transaction.
+ *
+ * If there is no currently active transaction then a PersistenceException is thrown.
+ *
+ * @param transactionCallback the transaction callback to be registered with the current transaction
+ *
+ * @throws PersistenceException if there is no currently active transaction
+ */
+ public static void register(TransactionCallback transactionCallback) throws PersistenceException {
+ serverMgr.getPrimaryServer().register(transactionCallback);
+ }
+
+ /**
+ * Commit the current transaction.
+ */
+ public static void commitTransaction() {
+ serverMgr.getPrimaryServer().commitTransaction();
+ }
+
+ /**
+ * Rollback the current transaction.
+ */
+ public static void rollbackTransaction() {
+ serverMgr.getPrimaryServer().rollbackTransaction();
+ }
+
+ /**
+ * If the current transaction has already been committed do nothing otherwise
+ * rollback the transaction.
+ * + * Useful to put in a finally block to ensure the transaction is ended, rather + * than a rollbackTransaction() in each catch block. + *
+ *+ * Code example: + *
+ * + *{@code
+ * Ebean.beginTransaction();
+ * try {
+ * // do some fetching and or persisting
+ *
+ * // commit at the end
+ * Ebean.commitTransaction();
+ *
+ * } finally {
+ * // if commit didn't occur then rollback the transaction
+ * Ebean.endTransaction();
+ * }
+ * }
+ */
+ public static void endTransaction() {
+ serverMgr.getPrimaryServer().endTransaction();
+ }
+
+ /**
+ * Return a map of the differences between two objects of the same type.
+ * + * When null is passed in for b, then the 'OldValues' of a is used for the + * difference comparison. + *
+ */ + public static Map+ * If there is no current transaction one will be created and committed for + * you automatically. + *
+ *+ * Save can cascade along relationships. For this to happen you need to + * specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the + * OneToMany, OneToOne or ManyToMany annotation. + *
+ *+ * In this example below the details property has a CascadeType.ALL set so + * saving an order will also save all its details. + *
+ * + *{@code
+ * public class Order { ...
+ *
+ * @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
+ * @JoinColumn(name="order_id")
+ * List details;
+ * ...
+ * }
+ * }
+ *
+ * + * When a save cascades via a OneToMany or ManyToMany Ebean will automatically + * set the 'parent' object to the 'detail' object. In the example below in + * saving the order and cascade saving the order details the 'parent' order + * will be set against each order detail when it is saved. + *
+ */ + public static void save(Object bean) throws OptimisticLockException { + serverMgr.getPrimaryServer().save(bean); + } + + /** + * Insert the bean. This is useful when you set the Id property on a bean and + * want to explicitly insert it. + */ + public static void insert(Object bean) { + serverMgr.getPrimaryServer().insert(bean); + } + + /** + * Insert a collection of beans. + */ + public static void insert(Collection> beans) { + serverMgr.getPrimaryServer().insert(beans); + } + + /** + * Marks the entity bean as dirty. + *+ * This is used so that when a bean that is otherwise unmodified is updated with the version + * property updated. + *
+ * An unmodified bean that is saved or updated is normally skipped and this marks the bean as + * dirty so that it is not skipped. + * + *
{@code
+ *
+ * Customer customer = Ebean.find(Customer, id);
+ *
+ * // mark the bean as dirty so that a save() or update() will
+ * // increment the version property
+ * Ebean.markAsDirty(customer);
+ * Ebean.save(customer);
+ *
+ * }
+ */
+ public static void markAsDirty(Object bean) throws OptimisticLockException {
+ serverMgr.getPrimaryServer().markAsDirty(bean);
+ }
+
+ /**
+ * Saves the bean using an update. If you know you are updating a bean then it is preferrable to
+ * use this update() method rather than save().
+ * + * Stateless updates: Note that the bean does not have to be previously fetched to call + * update().You can create a new instance and set some of its properties programmatically for via + * JSON/XML marshalling etc. This is described as a 'stateless update'. + *
+ *+ * Optimistic Locking: Note that if the version property is not set when update() is + * called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used). + *
+ *+ * {@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: When cascade saving to a + * OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children + * that are in the database but are not in the collection are deleted. + *
+ *+ * {@link ServerConfig#setUpdateChangesOnly(boolean)}: The updateChangesOnly setting + * controls if only the changed properties are included in the update or if all the loaded + * properties are included instead. + *
+ * + *{@code
+ *
+ * // A 'stateless update' example
+ * Customer customer = new Customer();
+ * customer.setId(7);
+ * customer.setName("ModifiedNameNoOCC");
+ * ebeanServer.update(customer);
+ *
+ * }
+ *
+ * @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
+ * @see ServerConfig#setUpdateChangesOnly(boolean)
+ */
+ public static void update(Object bean) throws OptimisticLockException {
+ serverMgr.getPrimaryServer().update(bean);
+ }
+
+ /**
+ * Update the beans in the collection.
+ */
+ public static void update(Collection> beans) throws OptimisticLockException {
+ serverMgr.getPrimaryServer().update(beans);
+ }
+
+ /**
+ * Save all the beans from an Iterator.
+ */
+ public static int save(Iterator> iterator) throws OptimisticLockException {
+ return serverMgr.getPrimaryServer().save(iterator);
+ }
+
+ /**
+ * Save all the beans from a Collection.
+ */
+ public static int save(Collection> beans) throws OptimisticLockException {
+ return serverMgr.getPrimaryServer().save(beans);
+ }
+
+ /**
+ * Delete the associations (from the intersection table) of a ManyToMany given
+ * the owner bean and the propertyName of the ManyToMany collection.
+ * + * Typically these deletions occur automatically when persisting a ManyToMany + * collection and this provides a way to invoke those deletions directly. + *
+ * + * @return the number of associations deleted (from the intersection table). + */ + public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) { + return serverMgr.getPrimaryServer().deleteManyToManyAssociations(ownerBean, propertyName); + } + + /** + * Save the associations of a ManyToMany given the owner bean and the + * propertyName of the ManyToMany collection. + *+ * Typically the saving of these associations (inserting into the intersection + * table) occurs automatically when persisting a ManyToMany. This provides a + * way to invoke those insertions directly. + *
+ *+ * You can use this when the collection is new and in this case all the + * entries in the collection are treated as additions are result in inserts + * into the intersection table. + *
+ */ + public static void saveManyToManyAssociations(Object ownerBean, String propertyName) { + serverMgr.getPrimaryServer().saveManyToManyAssociations(ownerBean, propertyName); + } + + /** + * Save the associated collection or bean given the property name. + *+ * This is similar to performing a save cascade on a specific property + * manually/programmatically. + *
+ *+ * Note that you can turn on/off cascading for a transaction via + * {@link Transaction#setPersistCascade(boolean)} + *
+ * + * @param ownerBean + * the bean instance holding the property we want to save + * @param propertyName + * the property we want to save + */ + public static void saveAssociation(Object ownerBean, String propertyName) { + serverMgr.getPrimaryServer().saveAssociation(ownerBean, propertyName); + } + + /** + * Delete the bean. + *+ * If there is no current transaction one will be created and committed for + * you automatically. + *
+ */ + public static void delete(Object bean) throws OptimisticLockException { + serverMgr.getPrimaryServer().delete(bean); + } + + /** + * Delete the bean given its type and id. + */ + public static int delete(Class> beanType, Object id) { + return serverMgr.getPrimaryServer().delete(beanType, id); + } + + /** + * Delete several beans given their type and id values. + */ + public static void delete(Class> beanType, Collection> ids) { + serverMgr.getPrimaryServer().delete(beanType, ids); + } + + /** + * Delete all the beans from an Iterator. + */ + public static int delete(Iterator> it) throws OptimisticLockException { + return serverMgr.getPrimaryServer().delete(it); + } + + /** + * Delete all the beans from a Collection. + */ + public static int delete(Collection> c) throws OptimisticLockException { + return delete(c.iterator()); + } + + /** + * Refresh the values of a bean. + *+ * Note that this resets OneToMany and ManyToMany properties so that if they + * are accessed a lazy load will refresh the many property. + *
+ */ + public static void refresh(Object bean) { + serverMgr.getPrimaryServer().refresh(bean); + } + + /** + * Refresh a 'many' property of a bean. + * + *{@code
+ *
+ * Order order = ...;
+ * ...
+ * // refresh the order details...
+ * Ebean.refreshMany(order, "details");
+ *
+ * }
+ *
+ * @param bean
+ * the entity bean containing the List Set or Map to refresh.
+ * @param manyPropertyName
+ * the property name of the List Set or Map to refresh.
+ */
+ public static void refreshMany(Object bean, String manyPropertyName) {
+ serverMgr.getPrimaryServer().refreshMany(bean, manyPropertyName);
+ }
+
+ /**
+ * Get a reference object.
+ * + * This is sometimes described as a proxy (with lazy loading). + *
+ * + *{@code
+ *
+ * Product product = Ebean.getReference(Product.class, 1);
+ *
+ * // You can get the id without causing a fetch/lazy load
+ * Integer productId = product.getId();
+ *
+ * // If you try to get any other property a fetch/lazy loading will occur
+ * // This will cause a query to execute...
+ * String name = product.getName();
+ *
+ * }
+ *
+ * @param beanType
+ * the type of entity bean
+ * @param id
+ * the id value
+ */
+ public static + * If you leave off any keywords the defaults are ascending order and treating + * nulls as high values. + *
+ *+ * Note that the sorting uses a Comparator and Collections.sort(); and does + * not invoke a DB query. + *
+ * + *{@code
+ *
+ * // find orders and their customers
+ * List list = Ebean.find(Order.class)
+ * .fetch("customer")
+ * .orderBy("id")
+ * .findList();
+ *
+ * // sort by customer name ascending, then by order shipDate
+ * // ... then by the order status descending
+ * Ebean.sort(list, "customer.name, shipDate, status desc");
+ *
+ * // sort by customer name descending (with nulls low)
+ * // ... then by the order id
+ * Ebean.sort(list, "customer.name desc nullsLow, id");
+ *
+ * }
+ *
+ * @param list
+ * the list of entity beans
+ * @param sortByClause
+ * the properties to sort the list by
+ */
+ public static {@code
+ * // Fetch order 1
+ * Order order = Ebean.find(Order.class, 1);
+ * }
+ *
+ * + * If you want more control over the query then you can use createQuery() and + * Query.findUnique(); + *
+ * + *{@code
+ * // ... additionally fetching customer, customer shipping address,
+ * // order details, and the product associated with each order detail.
+ * // note: only product id and name is fetch (its a "partial object").
+ * // note: all other objects use "*" and have all their properties fetched.
+ *
+ * Query query = Ebean.find(Order.class)
+ * .setId(1)
+ * .fetch("customer")
+ * .fetch("customer.shippingAddress")
+ * .fetch("details")
+ * .query();
+ *
+ * // fetch associated products but only fetch their product id and name
+ * query.fetch("details.product", "name");
+ *
+ * // traverse the object graph...
+ *
+ * Order order = query.findUnique();
+ * Customer customer = order.getCustomer();
+ * Address shippingAddress = customer.getShippingAddress();
+ * List details = order.getDetails();
+ * OrderDetail detail0 = details.get(0);
+ * Product product = detail0.getProduct();
+ * String productName = product.getName();
+ *
+ * }
+ *
+ * @param beanType
+ * the type of entity bean to fetch
+ * @param id
+ * the id value
+ */
+ public static + * Note that you can use raw SQL with entity beans, refer to the SqlSelect + * annotation for examples. + *
+ */ + public static SqlQuery createSqlQuery(String sql) { + return serverMgr.getPrimaryServer().createSqlQuery(sql); + } + + /** + * Create a named sql query. + *+ * The query statement will be defined in a deployment orm xml file. + *
+ * + * @param namedQuery + * the name of the query + */ + public static SqlQuery createNamedSqlQuery(String namedQuery) { + return serverMgr.getPrimaryServer().createNamedSqlQuery(namedQuery); + } + + /** + * Create a sql update for executing native dml statements. + *+ * Use this to execute a Insert Update or Delete statement. The statement will + * be native to the database and contain database table and column names. + *
+ *+ * See {@link SqlUpdate} for example usage. + *
+ *+ * Where possible it would be expected practice to put the statement in a orm + * xml file (named update) and use {@link #createNamedSqlUpdate(String)} . + *
+ */ + public static SqlUpdate createSqlUpdate(String sql) { + return serverMgr.getPrimaryServer().createSqlUpdate(sql); + } + + /** + * Create a CallableSql to execute a given stored procedure. + * + * @see CallableSql + */ + public static CallableSql createCallableSql(String sql) { + return serverMgr.getPrimaryServer().createCallableSql(sql); + } + + /** + * Create a named sql update. + *+ * The statement (an Insert Update or Delete statement) will be defined in a + * deployment orm xml file. + *
+ * + *{@code
+ *
+ * // Use a namedQuery
+ * UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count");
+ *
+ * update.setParameter("count", 1);
+ * update.setParameter("topicId", 50);
+ *
+ * int modifiedCount = update.execute();
+ *
+ * }
+ */
+ public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
+ return serverMgr.getPrimaryServer().createNamedSqlUpdate(namedQuery);
+ }
+
+ /**
+ * Return a named Query that will have defined fetch paths, predicates etc.
+ * + * The query is created from a statement that will be defined in a deployment + * orm xml file or NamedQuery annotations. The query will typically already + * define fetch paths, predicates, order by clauses etc so often you will just + * need to bind required parameters and then execute the query. + *
+ * + *{@code
+ *
+ * // example
+ * Query query = Ebean.createNamedQuery(Order.class, "new.for.customer");
+ * query.setParameter("customerId", 23);
+ * List newOrders = query.findList();
+ *
+ * }
+ *
+ * @param beanType
+ * the class of entity to be fetched
+ * @param namedQuery
+ * the name of the query
+ */
+ public static + * Note that you are allowed to add additional clauses using where() as well + * as use fetch() and setOrderBy() after the query has been created. + *
+ *+ * Note that this method signature used to map to named queries and that has + * moved to {@link #createNamedQuery(Class, String)}. + *
+ * + *{@code
+ *
+ * String q = "find order fetch details where status = :st";
+ *
+ * List newOrders = Ebean.>findOrder.class, q)
+ * .setParameter("st", Order.Status.NEW)
+ * .findList();
+ *
+ * }
+ *
+ * @param query
+ * the object query
+ */
+ public static + * The orm update differs from the SqlUpdate in that it uses the bean name and + * bean property names rather than table and column names. + *
+ *+ * Note that named update statements can be specified in raw sql (with column + * and table names) or using bean name and bean property names. This can be + * specified with the isSql flag. + *
+ *+ * Example named updates: + *
+ * + *{@code
+ * package app.data;
+ *
+ * import ...
+ *
+ * @NamedUpdates(value = {
+ * @NamedUpdate( name = "setTitle",
+ * isSql = false,
+ * notifyCache = false,
+ * update = "update topic set title = :title, postCount = :postCount where id = :id"),
+ * @NamedUpdate( name = "setPostCount",
+ * notifyCache = false,
+ * update = "update f_topic set post_count = :postCount where id = :id"),
+ * @NamedUpdate( name = "incrementPostCount",
+ * notifyCache = false,
+ * isSql = false,
+ * update = "update Topic set postCount = postCount + 1 where id = :id") })
+ * @Entity
+ * @Table(name = "f_topic")
+ * public class Topic { ...
+ *
+ * }
+ *
+ * + * Example using a named update: + *
+ * + *{@code
+ *
+ * Update update = Ebean.createNamedUpdate(Topic.class, "setPostCount");
+ * update.setParameter("postCount", 10);
+ * update.setParameter("id", 3);
+ *
+ * int rows = update.execute();
+ * System.out.println("rows updated: " + rows);
+ *
+ * }
+ */
+ public static + * The orm update differs from the sql update in that it you can use the bean + * name and bean property names rather than table and column names. + *
+ *+ * An example: + *
+ * + *{@code
+ *
+ * // The bean name and properties - "topic","postCount" and "id"
+ *
+ * // will be converted into their associated table and column names
+ * String updStatement = "update topic set postCount = :pc where id = :id";
+ *
+ * Update update = Ebean.createUpdate(Topic.class, updStatement);
+ *
+ * update.set("pc", 9);
+ * update.set("id", 3);
+ *
+ * int rows = update.execute();
+ * System.out.println("rows updated:" + rows);
+ *
+ * }
+ */
+ public static + * You can use the methods on the Query object to specify fetch paths, + * predicates, order by, limits etc. + *
+ *+ * You then use findList(), findSet(), findMap() and findUnique() to execute + * the query and return the collection or bean. + *
+ *+ * Note that a query executed by {@link Query#findList()} + * {@link Query#findSet()} etc will execute against the same EbeanServer from + * which is was created. + *
+ * + *{@code
+ * // Find order 2 additionally fetching the customer, details and details.product
+ * // name.
+ *
+ * Order order = Ebean.find(Order.class)
+ * .fetch("customer")
+ * .fetch("details")
+ * .fetch("detail.product", "name")
+ * .setId(2)
+ * .findUnique();
+ *
+ * // Find order 2 additionally fetching the customer, details and details.product
+ * // name.
+ * // Note: same query as above but using the query language
+ * // Note: using a named query would be preferred practice
+ *
+ * String oql = "find order fetch customer fetch details fetch details.product (name) where id = :orderId ";
+ *
+ * Query query = Ebean.find(Order.class);
+ * query.setQuery(oql);
+ * query.setParameter("orderId", 2);
+ *
+ * Order order = query.findUnique();
+ *
+ * // Using a named query
+ * Query query = Ebean.find(Order.class, "with.details");
+ * query.setParameter("orderId", 2);
+ *
+ * Order order = query.findUnique();
+ *
+ * }
+ *
+ * @param beanType
+ * the class of entity to be fetched
+ * @return A ORM Query object for this beanType
+ */
+ public static + * This is actually the same as {@link #createQuery(Class)}. The reason it + * exists is that people used to JPA will probably be looking for a + * createQuery method (the same as entityManager). + *
+ * + * @param beanType + * the type of entity bean to find + * @return A ORM Query object for this beanType + */ + public static+ * This produces and returns a new list with the sort and filters applied. + *
+ *+ * Refer to {@link Filter} for an example of its use. + *
+ */ + public static+ * If you wish to execute a Sql Select natively then you should use the + * FindByNativeSql object. + *
+ *+ * Note that the table modification information is automatically deduced and + * you do not need to call the Ebean.externalModification() method when you + * use this method. + *
+ *+ * Example: + *
+ * + *{@code
+ *
+ * // example that uses 'named' parameters
+ * String s = "UPDATE f_topic set post_count = :count where id = :id"
+ *
+ * SqlUpdate update = Ebean.createSqlUpdate(s);
+ *
+ * update.setParameter("id", 1);
+ * update.setParameter("count", 50);
+ *
+ * int modifiedCount = Ebean.execute(update);
+ *
+ * String msg = "There where " + modifiedCount + "rows updated";
+ *
+ * }
+ *
+ * @param sqlUpdate
+ * the update sql potentially with bind values
+ *
+ * @return the number of rows updated or deleted. -1 if executed in batch.
+ *
+ * @see SqlUpdate
+ * @see CallableSql
+ * @see Ebean#execute(CallableSql)
+ */
+ public static int execute(SqlUpdate sqlUpdate) {
+ return serverMgr.getPrimaryServer().execute(sqlUpdate);
+ }
+
+ /**
+ * For making calls to stored procedures.
+ * + * Example: + *
+ * + *{@code
+ *
+ * String sql = "{call sp_order_modify(?,?,?)}";
+ *
+ * CallableSql cs = Ebean.createCallableSql(sql);
+ * cs.setParameter(1, 27);
+ * cs.setParameter(2, "SHIPPED");
+ * cs.registerOut(3, Types.INTEGER);
+ *
+ * Ebean.execute(cs);
+ *
+ * // read the out parameter
+ * Integer returnValue = (Integer) cs.getObject(3);
+ *
+ * }
+ *
+ * @see CallableSql
+ * @see Ebean#execute(SqlUpdate)
+ */
+ public static int execute(CallableSql callableSql) {
+ return serverMgr.getPrimaryServer().execute(callableSql);
+ }
+
+ /**
+ * Execute a TxRunnable in a Transaction with an explicit scope.
+ * + * The scope can control the transaction type, isolation and rollback + * semantics. + *
+ * + *{@code
+ *
+ * // set specific transactional scope settings
+ * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
+ *
+ * Ebean.execute(scope, new TxRunnable() {
+ * public void run() {
+ * User u1 = Ebean.find(User.class, 1);
+ * ...
+ * }
+ * });
+ *
+ * }
+ */
+ public static void execute(TxScope scope, TxRunnable r) {
+ serverMgr.getPrimaryServer().execute(scope, r);
+ }
+
+ /**
+ * Execute a TxRunnable in a Transaction with the default scope.
+ * + * The default scope runs with REQUIRED and by default will rollback on any + * exception (checked or runtime). + *
+ * + *{@code
+ *
+ * Ebean.execute(new TxRunnable() {
+ * public void run() {
+ * User u1 = Ebean.find(User.class, 1);
+ * User u2 = Ebean.find(User.class, 2);
+ *
+ * u1.setName("u1 mod");
+ * u2.setName("u2 mod");
+ *
+ * Ebean.save(u1);
+ * Ebean.save(u2);
+ * }
+ * });
+ *
+ * }
+ */
+ public static void execute(TxRunnable r) {
+ serverMgr.getPrimaryServer().execute(r);
+ }
+
+ /**
+ * Execute a TxCallable in a Transaction with an explicit scope.
+ * + * The scope can control the transaction type, isolation and rollback + * semantics. + *
+ * + *{@code
+ *
+ * // set specific transactional scope settings
+ * TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
+ *
+ * Ebean.execute(scope, new TxCallable() {
+ * public String call() {
+ * User u1 = Ebean.find(User.class, 1);
+ * ...
+ * return u1.getEmail();
+ * }
+ * });
+ *
+ * }
+ *
+ */
+ public static + * The default scope runs with REQUIRED and by default will rollback on any + * exception (checked or runtime). + *
+ *+ * This is basically the same as TxRunnable except that it returns an Object + * (and you specify the return type via generics). + *
+ * + *{@code
+ *
+ * Ebean.execute(new TxCallable() {
+ * public String call() {
+ * User u1 = Ebean.find(User.class, 1);
+ * User u2 = Ebean.find(User.class, 2);
+ *
+ * u1.setName("u1 mod");
+ * u2.setName("u2 mod");
+ *
+ * Ebean.save(u1);
+ * Ebean.save(u2);
+ *
+ * return u1.getEmail();
+ * }
+ * });
+ *
+ * }
+ */
+ public static + * If you use Ebean.execute(UpdateSql) then the table modification information + * is automatically deduced and you do not need to call this method yourself. + *
+ *+ * This information is used to invalidate objects out of the cache and + * potentially text indexes. This information is also automatically broadcast + * across the cluster. + *
+ *+ * If there is a transaction then this information is placed into the current + * transactions event information. When the transaction is committed this + * information is registered (with the transaction manager). If this + * transaction is rolled back then none of the transaction event information + * registers including the information you put in via this method. + *
+ *+ * If there is NO current transaction when you call this method then this + * information is registered immediately (with the transaction manager). + *
+ * + * @param tableName + * the name of the table that was modified + * @param inserts + * true if rows where inserted into the table + * @param updates + * true if rows on the table where updated + * @param deletes + * true if rows on the table where deleted + */ + public static void externalModification(String tableName, boolean inserts, boolean updates, + boolean deletes) { + + serverMgr.getPrimaryServer().externalModification(tableName, inserts, updates, deletes); + } + + /** + * Return the BeanState for a given entity bean. + *+ * This will return null if the bean is not an enhanced entity bean. + *
+ */ + public static BeanState getBeanState(Object bean) { + return serverMgr.getPrimaryServer().getBeanState(bean); + } + + /** + * Return the manager of the server cache ("L2" cache). + * + */ + public static ServerCacheManager getServerCacheManager() { + return serverMgr.getPrimaryServer().getServerCacheManager(); + } + + /** + * Return the BackgroundExecutor service for asynchronous processing of + * queries. + */ + public static BackgroundExecutor getBackgroundExecutor() { + return serverMgr.getPrimaryServer().getBackgroundExecutor(); + } + + /** + * Run the cache warming queries on all bean types that have one defined for + * the default/primary EbeanServer. + *+ * A cache warming query can be defined via {@link CacheStrategy}. + *
+ */ + public static void runCacheWarming() { + serverMgr.getPrimaryServer().runCacheWarming(); + } + + /** + * Run the cache warming query for a specific bean type for the + * default/primary EbeanServer. + *+ * A cache warming query can be defined via {@link CacheStrategy}. + *
+ */ + public static void runCacheWarming(Class> beanType) { + + serverMgr.getPrimaryServer().runCacheWarming(beanType); + } + + /** + * Return the JsonContext for reading/writing JSON. + */ + public static JsonContext json() { + return serverMgr.getPrimaryServer().json(); + } + + /** + * Return the JsonContext for reading/writing JSON. + * @deprecated Please use #json instead. + */ + public static JsonContext createJsonContext() { + return json(); + } + +} diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index 32712f8b4..ba0cbd8b5 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -103,30 +103,30 @@ public interface EbeanServer { * if true then deregister the JDBC driver if it is the EbeanORM * DataSource implementation. */ - public void shutdown(boolean shutdownDataSource, boolean deregisterDriver); + void shutdown(boolean shutdownDataSource, boolean deregisterDriver); /** * Return the AdminAutofetch which is used to control and configure the * Autofetch service at runtime. */ - public AdminAutofetch getAdminAutofetch(); + AdminAutofetch getAdminAutofetch(); /** * Return the name. This is used with {@link Ebean#getServer(String)} to get a * EbeanServer that was registered with the Ebean singleton. */ - public String getName(); + String getName(); /** * Return the ExpressionFactory for this server. */ - public ExpressionFactory getExpressionFactory(); + ExpressionFactory getExpressionFactory(); /** * Return the MetaInfoManager which is used to get meta data from the EbeanServer * such as query execution statistics. */ - public MetaInfoManager getMetaInfoManager(); + MetaInfoManager getMetaInfoManager(); /** * Return the BeanState for a given entity bean. @@ -134,12 +134,12 @@ public interface EbeanServer { * This will return null if the bean is not an enhanced entity bean. * */ - public BeanState getBeanState(Object bean); + BeanState getBeanState(Object bean); /** * Return the value of the Id property for a given bean. */ - public Object getBeanId(Object bean); + Object getBeanId(Object bean); /** * Return a map of the differences between two objects of the same type. @@ -148,7 +148,7 @@ public interface EbeanServer { * difference comparison. * */ - public Map