From 6c7074e2883998ec40c20c25ee256c3c6ac7abb2 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Mon, 23 May 2016 22:24:07 +1200 Subject: [PATCH] #120 - ENH: Add support for using where() on bulk Update statements --- src/main/java/com/avaje/ebean/Ebean.java | 22 ++ .../java/com/avaje/ebean/EbeanServer.java | 333 ++++++++---------- .../java/com/avaje/ebean/ExpressionList.java | 10 +- src/main/java/com/avaje/ebean/Query.java | 5 + .../java/com/avaje/ebean/UpdateQuery.java | 160 +++++++++ .../com/avaje/ebeaninternal/api/SpiQuery.java | 11 + .../server/core/DefaultServer.java | 19 +- .../server/core/OrmQueryEngine.java | 5 + .../server/core/OrmQueryRequest.java | 7 + .../server/core/SpiOrmQueryRequest.java | 5 + .../server/deploy/BeanDescriptor.java | 11 +- .../expression/DefaultExpressionList.java | 5 + .../server/expression/JunctionExpression.java | 5 + .../server/query/CQueryBuilder.java | 60 ++-- .../server/query/CQueryEngine.java | 12 +- .../server/query/CQueryPredicates.java | 32 +- .../server/query/CQueryRowCount.java | 30 +- .../{CQueryDelete.java => CQueryUpdate.java} | 32 +- .../server/query/DefaultOrmQueryEngine.java | 6 + .../ebeaninternal/server/query/UtilJdbc.java | 34 ++ .../server/querydefn/DefaultOrmQuery.java | 18 +- .../server/querydefn/DefaultUpdateQuery.java | 48 +++ .../server/querydefn/OrmQueryPlanKey.java | 8 +- .../server/querydefn/OrmUpdateProperties.java | 209 +++++++++++ .../java/com/avaje/ebean/UpdateQueryTest.java | 168 +++++++++ .../ebeaninternal/api/TDSpiEbeanServer.java | 10 + .../server/querydefn/OrmQueryPlanKeyTest.java | 176 ++++----- 27 files changed, 1093 insertions(+), 348 deletions(-) create mode 100644 src/main/java/com/avaje/ebean/UpdateQuery.java rename src/main/java/com/avaje/ebeaninternal/server/query/{CQueryDelete.java => CQueryUpdate.java} (77%) create mode 100644 src/main/java/com/avaje/ebeaninternal/server/query/UtilJdbc.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultUpdateQuery.java create mode 100644 src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmUpdateProperties.java create mode 100644 src/test/java/com/avaje/ebean/UpdateQueryTest.java diff --git a/src/main/java/com/avaje/ebean/Ebean.java b/src/main/java/com/avaje/ebean/Ebean.java index 438547dfe..5e52c9298 100644 --- a/src/main/java/com/avaje/ebean/Ebean.java +++ b/src/main/java/com/avaje/ebean/Ebean.java @@ -1019,6 +1019,28 @@ public final class Ebean { return serverMgr.getDefaultServer().find(beanType); } + /** + * Create an Update query to perform a bulk update. + *

+ *

{@code
+   *
+   *  int rows = Ebean.update(Customer.class)
+   *      .set("status", Customer.Status.ACTIVE)
+   *      .set("updtime", new Timestamp(System.currentTimeMillis()))
+   *      .where()
+   *        .gt("id", 1000)
+   *        .update();
+   *
+   * }
+ * + * @param beanType The type of entity bean to update + * @param The type of entity bean + * @return The update query to use + */ + public static UpdateQuery update(Class beanType) { + return serverMgr.getDefaultServer().update(beanType); + } + /** * Create a filter for sorting and filtering lists of entities locally without * going back to the database. diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index e48eaa15c..ebb69a62a 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -48,20 +48,20 @@ import java.util.Set; *

* Example: Get a EbeanServer *

- * + *

*

{@code
  * // Get access to the Human Resources EbeanServer/Database
  * EbeanServer hrServer = Ebean.getServer("HR");
- * 
- * 
+ *
+ *
  * // fetch contact 3 from the HR database Contact contact =
  * hrServer.find(Contact.class, new Integer(3));
- * 
+ *
  * contact.setStatus("INACTIVE"); ...
- * 
+ *
  * // save the contact back to the HR database hrServer.save(contact);
  * }
- * + *

*

* EbeanServer has more API than Ebean
* EbeanServer provides additional API compared with Ebean. For example it @@ -78,7 +78,7 @@ import java.util.Set; * ThreadLocal transaction management you can use the createTransaction() * method. Example: a single thread requires more than one transaction. *

- * + * * @see Ebean * @see EbeanServerFactory * @see ServerConfig @@ -95,16 +95,14 @@ public interface EbeanServer { * also have the option of shutting down the DataSource and deregistering the * JDBC driver. *

- * - * @param shutdownDataSource - * if true then shutdown the underlying DataSource if it is the EbeanORM - * DataSource implementation. - * @param deregisterDriver - * if true then deregister the JDBC driver if it is the EbeanORM - * DataSource implementation. + * + * @param shutdownDataSource if true then shutdown the underlying DataSource if it is the EbeanORM + * DataSource implementation. + * @param deregisterDriver if true then deregister the JDBC driver if it is the EbeanORM + * DataSource implementation. */ void shutdown(boolean shutdownDataSource, boolean deregisterDriver); - + /** * Return AutoTune which is used to control the AutoTune service at runtime. */ @@ -151,7 +149,8 @@ public interface EbeanServer { * For example, if the id value passed in is a String but ought to be a Long or UUID etc * then it will automatically be converted. *

- * @param bean The entity bean to set the id value on. + * + * @param bean The entity bean to set the id value on. * @param id The id value to set. */ Object setBeanId(Object bean, Object id); @@ -179,6 +178,27 @@ public interface EbeanServer { */ CsvReader createCsvReader(Class beanType); + /** + * Create an Update query to perform a bulk update. + *

+ *

{@code
+   *
+   *  int rows = ebeanServer
+   *      .update(Customer.class)
+   *      .set("status", Customer.Status.ACTIVE)
+   *      .set("updtime", new Timestamp(System.currentTimeMillis()))
+   *      .where()
+   *        .gt("id", 1000)
+   *        .update();
+   *
+   * }
+ * + * @param beanType The type of entity bean to update + * @param The type of entity bean + * @return The update query to use + */ + UpdateQuery update(Class beanType); + /** * Create a query for an entity bean and synonym for {@link #find(Class)}. * @@ -201,7 +221,7 @@ public interface EbeanServer { * {@link Query#findSet()} etc will execute against the same EbeanServer from * which is was created. *

- * + *

*

{@code
    *
    *   // Find order 2 specifying explicitly the parts of the object graph to
@@ -224,7 +244,6 @@ public interface EbeanServer {
    *       .findList();
    *
    * }
- * */ Query find(Class beanType); @@ -272,7 +291,7 @@ public interface EbeanServer { * Note that the sorting uses a Comparator and Collections.sort(); and does * not invoke a DB query. *

- * + *

*

{@code
    *
    *   // find orders and their customers
@@ -291,10 +310,8 @@ public interface EbeanServer {
    *
    * }
* - * @param list - * the list of entity beans - * @param sortByClause - * the properties to sort the list by + * @param list the list of entity beans + * @param sortByClause the properties to sort the list by */ void sort(List list, String sortByClause); @@ -309,7 +326,7 @@ public interface EbeanServer { *

* An example: *

- * + *

*

{@code
    *
    *   // The bean name and properties - "topic","postCount" and "id"
@@ -362,7 +379,6 @@ public interface EbeanServer {
    * 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
    */
   void register(TransactionCallback transactionCallback) throws PersistenceException;
@@ -400,7 +416,7 @@ public interface EbeanServer {
    * Example of using a transaction to span multiple calls to find(), save()
    * etc.
    * 

- * + *

*

{@code
    *
    *    // start a transaction (stored in a ThreadLocal)
@@ -419,7 +435,7 @@ public interface EbeanServer {
    *    }
    *
    * }
- * + *

*

Transaction options:

*
{@code
    *
@@ -452,7 +468,7 @@ public interface EbeanServer {
    *    }
    *
    * }
- * + *

*

* If you want to externalise the transaction management then you use * createTransaction() and pass the transaction around to the various methods on @@ -468,12 +484,12 @@ public interface EbeanServer { /** * 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)}. *

- * + *

*

REQUIRES_NEW example:

*
{@code
    * // Start a new transaction. If there is a current transaction
@@ -494,7 +510,7 @@ public interface EbeanServer {
    * }
    *
    * }
- * + *

*

REQUIRED example:

*
{@code
    *
@@ -543,25 +559,24 @@ public interface EbeanServer {
    * 

*

* Code example: - * + *

*

{@code
    *
    *   ebeanServer.beginTransaction();
    *   try {
    *     // do some fetching and or persisting ...
-   * 
+   *
    *     // commit at the end
    *     ebeanServer.commitTransaction();
-   * 
+   *
    *   } finally {
    *     // if commit didn't occur then rollback the transaction
    *     ebeanServer.endTransaction();
    *   }
    *
    * }
- * + *

*

- * */ void endTransaction(); @@ -576,28 +591,25 @@ public interface EbeanServer { /** * Refresh a many property of an entity bean. - * - * @param bean - * the entity bean containing the 'many' property - * @param propertyName - * the 'many' property to be refreshed * + * @param bean the entity bean containing the 'many' property + * @param propertyName the 'many' property to be refreshed */ void refreshMany(Object bean, String propertyName); /** * Find a bean using its unique id. - * + *

*

{@code
    *   // Fetch order 1
    *   Order order = ebeanServer.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.
@@ -628,10 +640,8 @@ public interface EbeanServer {
    *
    * }
* - * @param beanType - * the type of entity bean to fetch - * @param id - * the id value + * @param beanType the type of entity bean to fetch + * @param id the id value */ T find(Class beanType, Object id); @@ -658,7 +668,7 @@ public interface EbeanServer { * * * }
- * + *

*

Lazy loading characteristics

*
{@code
    *
@@ -673,10 +683,8 @@ public interface EbeanServer {
    *
    * }
* - * @param beanType - * the type of entity bean - * @param id - * the id value + * @param beanType the type of entity bean + * @param id the id value */ T getReference(Class beanType, Object id); @@ -707,7 +715,7 @@ public interface EbeanServer { * Internally this query using a PersistenceContext scoped to each bean (and the * beans associated object graph). *

- * + *

*

{@code
    *
    *     ebeanServer.find(Order.class)
@@ -741,7 +749,7 @@ public interface EbeanServer {
    * Internally this query using a PersistenceContext scoped to each bean (and the
    * beans associated object graph).
    * 

- * + *

*

{@code
    *
    *     ebeanServer.find(Order.class)
@@ -766,8 +774,8 @@ public interface EbeanServer {
   /**
    * Return versions of a @History entity bean.
    * 

- * Generally this query is expected to be a find by id or unique predicates query. - * It will execute the query against the history returning the versions of the bean. + * Generally this query is expected to be a find by id or unique predicates query. + * It will execute the query against the history returning the versions of the bean. *

*/ List> findVersions(Query query, Transaction transaction); @@ -779,7 +787,7 @@ public interface EbeanServer { * explicitly calling this method. You could use this method if you wish to * explicitly control the transaction used for the query. *

- * + *

*

{@code
    *
    * List customers =
@@ -789,14 +797,10 @@ public interface EbeanServer {
    *
    * }
* - * @param - * the type of entity bean to fetch. - * @param query - * the query to execute. - * @param transaction - * the transaction to use (can be null). + * @param the type of entity bean to fetch. + * @param query the query to execute. + * @param transaction the transaction to use (can be null). * @return the list of fetched beans. - * * @see Query#findList() */ List findList(Query query, Transaction transaction); @@ -808,13 +812,10 @@ public interface EbeanServer { * execution status (isDone etc) and get the value (with or without a * timeout). *

- * - * @param query - * the query to execute the row count on - * @param transaction - * the transaction (can be null). - * @return a Future object for the row count query * + * @param query the query to execute the row count on + * @param transaction the transaction (can be null). + * @return a Future object for the row count query * @see com.avaje.ebean.Query#findFutureRowCount() */ FutureRowCount findFutureRowCount(Query query, Transaction transaction); @@ -826,13 +827,10 @@ public interface EbeanServer { * execution status (isDone etc) and get the value (with or without a * timeout). *

- * - * @param query - * the query to execute the fetch Id's on - * @param transaction - * the transaction (can be null). - * @return a Future object for the list of Id's * + * @param query the query to execute the fetch Id's on + * @param transaction the transaction (can be null). + * @return a Future object for the list of Id's * @see com.avaje.ebean.Query#findFutureIds() */ FutureIds findFutureIds(Query query, Transaction transaction); @@ -846,13 +844,9 @@ public interface EbeanServer { * This query will execute in it's own PersistenceContext and using its own transaction. * What that means is that it will not share any bean instances with other queries. * - * - * @param query - * the query to execute in the background - * @param transaction - * the transaction (can be null). + * @param query the query to execute in the background + * @param transaction the transaction (can be null). * @return a Future object for the list result of the query - * * @see Query#findFutureList() */ FutureList findFutureList(Query query, Transaction transaction); @@ -867,7 +861,7 @@ public interface EbeanServer { * If maxRows is not set on the query prior to calling findPagedList() then a * PersistenceException is thrown. *

- * + *

*

{@code
    *
    *  PagedList pagedList = Ebean.find(Order.class)
@@ -884,7 +878,6 @@ public interface EbeanServer {
    * }
* * @return The PagedList - * * @see Query#findPagedList() */ PagedList findPagedList(Query query, Transaction transaction); @@ -896,7 +889,7 @@ public interface EbeanServer { * explicitly calling this method. You could use this method if you wish to * explicitly control the transaction used for the query. *

- * + *

*

{@code
    *
    * Set customers =
@@ -905,15 +898,11 @@ public interface EbeanServer {
    *     .findSet();
    *
    * }
- * - * @param - * the type of entity bean to fetch. - * @param query - * the query to execute - * @param transaction - * the transaction to use (can be null). - * @return the set of fetched beans. * + * @param the type of entity bean to fetch. + * @param query the query to execute + * @param transaction the transaction to use (can be null). + * @return the set of fetched beans. * @see Query#findSet() */ Set findSet(Query query, Transaction transaction); @@ -925,15 +914,11 @@ public interface EbeanServer { * explicitly calling this method. You could use this method if you wish to * explicitly control the transaction used for the query. *

- * - * @param - * the type of entity bean to fetch. - * @param query - * the query to execute. - * @param transaction - * the transaction to use (can be null). - * @return the map of fetched beans. * + * @param the type of entity bean to fetch. + * @param query the query to execute. + * @param transaction the transaction to use (can be null). + * @return the map of fetched beans. * @see Query#findMap() */ Map findMap(Query query, Transaction transaction); @@ -950,15 +935,11 @@ public interface EbeanServer { * explicitly control the transaction used for the query. *

* - * @param - * the type of entity bean to fetch. - * @param query - * the query to execute. - * @param transaction - * the transaction to use (can be null). + * @param the type of entity bean to fetch. + * @param query the query to execute. + * @param transaction the transaction to use (can be null). * @return the list of fetched beans. * @throws NonUniqueResultException if more than one result was found - * * @see Query#findUnique() */ @Nullable @@ -979,6 +960,19 @@ public interface EbeanServer { */ int delete(Query query, Transaction transaction); + /** + * Execute the update query returning the number of rows updated. + *

+ * The update query must be created using {@link #update(Class)}. + *

+ * + * @param query the update query to execute + * @param transaction the optional transaction to use for the update (can be null) + * @param the type of entity bean + * @return The number of rows updated + */ + int update(Query query, Transaction transaction); + /** * Execute the sql query returning a list of MapBean. *

@@ -986,13 +980,10 @@ public interface EbeanServer { * explicitly calling this method. You could use this method if you wish to * explicitly control the transaction used for the query. *

- * - * @param query - * the query to execute. - * @param transaction - * the transaction to use (can be null). - * @return the list of fetched MapBean. * + * @param query the query to execute. + * @param transaction the transaction to use (can be null). + * @return the list of fetched MapBean. * @see SqlQuery#findList() */ List findList(SqlQuery query, Transaction transaction); @@ -1027,13 +1018,10 @@ public interface EbeanServer { * explicitly calling this method. You could use this method if you wish to * explicitly control the transaction used for the query. *

- * - * @param query - * the query to execute. - * @param transaction - * the transaction to use (can be null). - * @return the fetched MapBean or null if none was found. * + * @param query the query to execute. + * @param transaction the transaction to use (can be null). + * @return the fetched MapBean or null if none was found. * @see SqlQuery#findUnique() */ @Nullable @@ -1054,7 +1042,7 @@ public interface EbeanServer { * 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 { ...
    *
@@ -1063,7 +1051,7 @@ public interface EbeanServer {
    * 	   ...
    *   }
    * }
- * + *

*

* 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 @@ -1195,7 +1183,7 @@ public interface EbeanServer { *

* Example: *

- * + *

*

{@code
    *
    *   // example that uses 'named' parameters
@@ -1212,11 +1200,8 @@ public interface EbeanServer {
    *
    * }
* - * @param sqlUpdate - * the update sql potentially with bind values - * + * @param sqlUpdate the update sql potentially with bind values * @return the number of rows updated or deleted. -1 if executed in batch. - * * @see CallableSql */ int execute(SqlUpdate sqlUpdate); @@ -1241,7 +1226,7 @@ public interface EbeanServer { *

* Example: *

- * + *

*

{@code
    *
    *   String sql = "{call sp_order_modify(?,?,?)}";
@@ -1288,28 +1273,20 @@ public interface EbeanServer {
    * information is registered immediately (with the transaction manager).
    * 

* - * @param tableName - * the name of the table that was modified - * @param inserted - * true if rows where inserted into the table - * @param updated - * true if rows on the table where updated - * @param deleted - * true if rows on the table where deleted + * @param tableName the name of the table that was modified + * @param inserted true if rows where inserted into the table + * @param updated true if rows on the table where updated + * @param deleted true if rows on the table where deleted */ void externalModification(String tableName, boolean inserted, boolean updated, boolean deleted); /** * Find a entity bean with an explicit transaction. - * - * @param - * the type of entity bean to find - * @param beanType - * the type of entity bean to find - * @param id - * the bean id value - * @param transaction - * the transaction to use (can be null) + * + * @param the type of entity bean to find + * @param beanType the type of entity bean to find + * @param id the bean id value + * @param transaction the transaction to use (can be null) */ T find(Class beanType, Object id, Transaction transaction); @@ -1331,20 +1308,20 @@ public interface EbeanServer { *

* 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 = ebeanServer.find(Customer, id);
-   * 
+   *
    * // mark the bean as dirty so that a save() or update() will
    * // increment the version property
    * ebeanServer.markAsDirty(customer);
    * ebeanServer.save(customer);
-   * 
+   *
    * }
*/ void markAsDirty(Object bean); - + /** * Saves the bean using an update. If you know you are updating a bean then it is preferable to * use this update() method rather than save(). @@ -1367,17 +1344,17 @@ public interface EbeanServer { * 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) */ @@ -1390,14 +1367,11 @@ public interface EbeanServer { /** * Update a bean additionally specifying a transaction and the deleteMissingChildren setting. - * - * @param bean - * the bean to update - * @param transaction - * the transaction to use (can be null). - * @param deleteMissingChildren - * specify false if you do not want 'missing children' of a OneToMany - * or ManyToMany to be automatically deleted. + * + * @param bean the bean to update + * @param transaction the transaction to use (can be null). + * @param deleteMissingChildren specify false if you do not want 'missing children' of a OneToMany + * or ManyToMany to be automatically deleted. */ void update(Object bean, Transaction transaction, boolean deleteMissingChildren) throws OptimisticLockException; @@ -1454,7 +1428,7 @@ public interface EbeanServer { * The scope can control the transaction type, isolation and rollback * semantics. *

- * + *

*

{@code
    *
    *   // set specific transactional scope settings
@@ -1477,7 +1451,7 @@ public interface EbeanServer {
    * The default scope runs with REQUIRED and by default will rollback on any
    * exception (checked or runtime).
    * 

- * + *

*

{@code
    *
    *    ebeanServer.execute(new TxRunnable() {
@@ -1503,7 +1477,7 @@ public interface EbeanServer {
    * The scope can control the transaction type, isolation and rollback
    * semantics.
    * 

- * + *

*

{@code
    *
    *   // set specific transactional scope settings
@@ -1531,7 +1505,7 @@ public interface EbeanServer {
    * This is basically the same as TxRunnable except that it returns an Object
    * (and you specify the return type via generics).
    * 

- * + *

*

{@code
    *
    *   ebeanServer.execute(new TxCallable() {
@@ -1555,7 +1529,6 @@ public interface EbeanServer {
 
   /**
    * Return the manager of the server cache ("L2" cache).
-   * 
    */
   ServerCacheManager getServerCacheManager();
 
@@ -1571,7 +1544,7 @@ public interface EbeanServer {
    * This instance is safe to be used concurrently by multiple threads and this
    * method is cheap to call.
    * 

- * + *

*

Simple example:

*
{@code
    *
@@ -1580,7 +1553,7 @@ public interface EbeanServer {
    *     System.out.println(jsonOutput);
    *
    * }
- * + *

*

Using PathProperties:

*
{@code
    *
@@ -1630,9 +1603,9 @@ public interface EbeanServer {
    * The values are published from the draft to the live bean.
    * 

* - * @param the type of the entity bean - * @param beanType the type of the entity bean - * @param id the id of the entity bean + * @param the type of the entity bean + * @param beanType the type of the entity bean + * @param id the id of the entity bean */ T publish(Class beanType, Object id); @@ -1655,8 +1628,8 @@ public interface EbeanServer { * The values are published from the draft beans to the live beans. *

* - * @param the type of the entity bean - * @param query the query used to select the draft beans to publish + * @param the type of the entity bean + * @param query the query used to select the draft beans to publish */ List publish(Query query); @@ -1681,9 +1654,9 @@ public interface EbeanServer { * @DraftDirty and @DraftReset properties are reset. *

* - * @param the type of the entity bean - * @param beanType the type of the entity bean - * @param id the id of the entity bean to restore + * @param the type of the entity bean + * @param beanType the type of the entity bean + * @param id the id of the entity bean to restore */ T draftRestore(Class beanType, Object id); @@ -1707,8 +1680,8 @@ public interface EbeanServer { * @DraftDirty and @DraftReset properties are reset. *

* - * @param the type of the entity bean - * @param query the query used to select the draft beans to restore + * @param the type of the entity bean + * @param query the query used to select the draft beans to restore */ List draftRestore(Query query); diff --git a/src/main/java/com/avaje/ebean/ExpressionList.java b/src/main/java/com/avaje/ebean/ExpressionList.java index d5cc62bc6..31cbfdc49 100644 --- a/src/main/java/com/avaje/ebean/ExpressionList.java +++ b/src/main/java/com/avaje/ebean/ExpressionList.java @@ -135,10 +135,18 @@ public interface ExpressionList { * optimal depending on the database platform. *

* - * @return the number of beans/rows that were deleted. + * @return the number of rows that were deleted. */ int delete(); + /** + * Execute as a update query. + * + * @return the number of rows that were updated. + * @see UpdateQuery + */ + int update(); + /** * Execute the query process the beans one at a time. * diff --git a/src/main/java/com/avaje/ebean/Query.java b/src/main/java/com/avaje/ebean/Query.java index f4f205018..c75a5ba0d 100644 --- a/src/main/java/com/avaje/ebean/Query.java +++ b/src/main/java/com/avaje/ebean/Query.java @@ -763,6 +763,11 @@ public interface Query { */ int delete(); + /** + * Execute the UpdateQuery returning the number of rows updated. + */ + int update(); + /** * Return the count of entities this query should return. *

diff --git a/src/main/java/com/avaje/ebean/UpdateQuery.java b/src/main/java/com/avaje/ebean/UpdateQuery.java new file mode 100644 index 000000000..0006f608e --- /dev/null +++ b/src/main/java/com/avaje/ebean/UpdateQuery.java @@ -0,0 +1,160 @@ +package com.avaje.ebean; + +/** + * An update query typically intended to perform a bulk update of many rows that match the query. + *

+ * Also note that you can also just use a raw SQL update via {@link SqlUpdate} which is pretty light and simple. + * This UpdateQuery is more for the cases where we want to build the where expression of the update using the + * {@link ExpressionList} "Criteria API" that is used with a normal ORM query. + *

+ * + *

Example: Simple update

+ * + *
{@code
+ *
+ *  int rows = ebeanServer
+ *      .update(Customer.class)
+ *      .set("status", Customer.Status.ACTIVE)
+ *      .set("updtime", new Timestamp(System.currentTimeMillis()))
+ *      .where()
+ *      .gt("id", 1000)
+ *      .update();
+ *
+ * }
+ *
{@code sql
+ *
+ *   update o_customer set status=?, updtime=? where id > ?
+ *
+ * }
+ * + *

+ * Note that if the where() clause contains a join then the SQL update changes to use a + * WHERE ID IN () form. + *

+ * + *

Example: Update with a JOIN

+ *

+ * In this example the expression .eq("billingAddress.country", nz) requires a join + * to the address table. + *

+ * + *
{@code
+ *
+ *   int rows = ebeanServer
+ *       .update(Customer.class)
+ *       .set("status", Customer.Status.ACTIVE)
+ *       .set("updtime", new Timestamp(System.currentTimeMillis()))
+ *       .where()
+ *         .eq("status", Customer.Status.NEW)
+ *         .eq("billingAddress.country", nz)
+ *         .gt("id", 1000)
+ *         .update();
+ * }
+ * + *
{@code sql
+ *
+ *   update o_customer set status=?, updtime=?
+ *   where id in (
+ *     select t0.id c0
+ *     from o_customer t0
+ *     left outer join o_address t1 on t1.id = t0.billing_address_id
+ *     where t0.status = ?
+ *       and t1.country_code = ?
+ *       and t0.id > ? )
+ *
+ * }
+ * + * @param The type of entity bean being updated + * + * @see SqlUpdate + */ +public interface UpdateQuery { + + /** + * Set the value of a property. + * + * + *
{@code
+   *
+   *   int rows = ebeanServer
+   *      .update(Customer.class)
+   *      .set("status", Customer.Status.ACTIVE)
+   *      .set("updtime", new Timestamp(System.currentTimeMillis()))
+   *      .where()
+   *      .gt("id", 1000)
+   *      .update();
+   *
+   * }
+ * + * @param property The bean property to be set + * @param value The value to set the property to + */ + UpdateQuery set(String property, Object value); + + /** + * Set the property to be null. + * + *
{@code
+   *
+   *   int rows = ebeanServer
+   *      .update(Customer.class)
+   *      .setNull("notes")
+   *      .where()
+   *      .gt("id", 1000)
+   *      .update();
+   *
+   * }
+ * + * @param property The property to be set to null. + */ + UpdateQuery setNull(String property); + + /** + * + * Set using a property expression that does not need any bind values. + *

+ * The property expression typically contains database functions. + *

+ * + *
{@code
+   *
+   *   int rows = ebeanServer
+   *      .update(Customer.class)
+   *      .setRaw("status = coalesce(status, 'A')")
+   *      .where()
+   *      .gt("id", 1000)
+   *      .update();
+   *
+   * }
+ * + * @param propertyExpression A property expression + */ + UpdateQuery setRaw(String propertyExpression); + + /** + * Set using a property expression that can contain ? bind value placeholders. + *

+ * For each ? in the property expression there should be a matching bind value supplied. + *

+ *
{@code
+   *
+   *   int rows = ebeanServer
+   *      .update(Customer.class)
+   *      .setRaw("status = coalesce(status, ?)", Customer.Status.ACTIVE)
+   *      .where()
+   *      .gt("id", 1000)
+   *      .update();
+   *
+   * }
+ * + * @param propertyExpression A raw property expression + * @param values The values to bind with the property expression + */ + UpdateQuery setRaw(String propertyExpression, Object... values); + + /** + * Return the query expression list to add predicates to. + */ + ExpressionList where(); + +} diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java index a74fcc50e..67a0f4e95 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java @@ -18,6 +18,7 @@ import com.avaje.ebeaninternal.server.deploy.TableJoin; import com.avaje.ebeaninternal.server.query.CancelableQuery; import com.avaje.ebeaninternal.server.querydefn.NaturalKeyBindParam; import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail; +import com.avaje.ebeaninternal.server.querydefn.OrmUpdateProperties; import java.sql.Timestamp; import java.util.List; @@ -91,6 +92,11 @@ public interface SpiQuery extends Query { * Delete query. */ DELETE, + + /** + * Update query. + */ + UPDATE, } enum TemporalMode { @@ -677,4 +683,9 @@ public interface SpiQuery extends Query { */ Set validate(BeanType desc); + /** + * Return the properties for an update query. + */ + OrmUpdateProperties getUpdateProperties(); + } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index 024f02b9c..1546a2428 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -53,6 +53,7 @@ import com.avaje.ebeaninternal.server.query.QueryFutureRowCount; import com.avaje.ebeaninternal.server.querydefn.DefaultOrmQuery; import com.avaje.ebeaninternal.server.querydefn.DefaultOrmUpdate; import com.avaje.ebeaninternal.server.querydefn.DefaultRelationalQuery; +import com.avaje.ebeaninternal.server.querydefn.DefaultUpdateQuery; import com.avaje.ebeaninternal.server.text.csv.TCsvReader; import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext; import com.avaje.ebeaninternal.server.transaction.RemoteTransactionEvent; @@ -875,11 +876,15 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { return new TCsvReader(this, descriptor); } + public UpdateQuery update(Class beanType) { + return new DefaultUpdateQuery(createQuery(beanType)); + } + public Query find(Class beanType) { return createQuery(beanType); } - public Query createQuery(Class beanType) { + public DefaultOrmQuery createQuery(Class beanType) { BeanDescriptor desc = getBeanDescriptor(beanType); if (desc == null) { throw new PersistenceException(beanType.getName() + " is NOT an Entity Bean registered with this server?"); @@ -1159,6 +1164,18 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } } + public int update(Query query, Transaction t) { + + SpiOrmQueryRequest request = createQueryRequest(Type.UPDATE, query, t); + try { + request.initTransIfRequired(); + request.markNotQueryOnly(); + return request.update(); + } finally { + request.endTransIfRequired(); + } + } + public FutureRowCount findFutureRowCount(Query q, Transaction t) { SpiQuery copy = ((SpiQuery) q).copy(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java index 8223af5a3..02464b5bc 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryEngine.java @@ -42,4 +42,9 @@ public interface OrmQueryEngine { * Execute the query as a delete statement. */ int delete(OrmQueryRequest request); + + /** + * Execute the query as a update statement. + */ + int update(OrmQueryRequest request); } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java index f6ed671f6..754637407 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java @@ -286,6 +286,13 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe return queryEngine.delete(this); } + /** + * Execute the query as a update. + */ + public int update() { + return queryEngine.update(this); + } + /** * Execute the query as findById. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java index b36cd132b..b5f22603a 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/SpiOrmQueryRequest.java @@ -52,6 +52,11 @@ public interface SpiOrmQueryRequest extends DocQueryRequest { */ int delete(); + /** + * Execute the query as a update. + */ + int update(); + /** * Execute the query as findById. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java index f08c3d3ee..6671e8e78 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java +++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java @@ -367,6 +367,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { private String deleteByIdSql; private String deleteByIdInSql; + private String whereIdInSql; private String softDeleteByIdSql; private String softDeleteByIdInSql; @@ -687,7 +688,8 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { String idEqualsSql = idBinder.getBindIdSql(null); deleteByIdSql = "delete from " + baseTable + " where " + idEqualsSql; - deleteByIdInSql = "delete from " + baseTable + " where " + idBinderInLHSSqlNoAlias + " "; + whereIdInSql = " where " + idBinderInLHSSqlNoAlias + " "; + deleteByIdInSql = "delete from " + baseTable + whereIdInSql; if (softDelete) { softDeleteByIdSql = "update " + baseTable + " set " + getSoftDeleteDbSet() + " where " + idEqualsSql; @@ -796,6 +798,13 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType { } } + /** + * Return the "where id in" sql (for use with UpdateQuery). + */ + public String getWhereIdInSql() { + return whereIdInSql; + } + /** * Return the "delete by id" sql. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java index cf711dcc0..d6fd82fa4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/DefaultExpressionList.java @@ -277,6 +277,11 @@ public class DefaultExpressionList implements SpiExpressionList { return query.delete(); } + @Override + public int update() { + return query.update(); + } + @Override public FutureIds findFutureIds() { return query.findFutureIds(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java index e7d3502de..b1541b3f8 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java +++ b/src/main/java/com/avaje/ebeaninternal/server/expression/JunctionExpression.java @@ -279,6 +279,11 @@ class JunctionExpression implements SpiJunction, SpiExpression, Expression return exprList.delete(); } + @Override + public int update() { + return exprList.update(); + } + @Override public Query asOf(Timestamp asOf) { return exprList.asOf(asOf); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java index e9dde50d5..cc0de5c46 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryBuilder.java @@ -88,7 +88,7 @@ public class CQueryBuilder { /** * Build the delete query. */ - public CQueryDelete buildDeleteQuery(OrmQueryRequest request) { + public CQueryUpdate buildUpdateQuery(String type, OrmQueryRequest request) { SpiQuery query = request.getQuery(); String rootTableAlias = query.getAlias(); @@ -99,33 +99,54 @@ public class CQueryBuilder { if (queryPlan != null) { // skip building the SqlTree and Sql string predicates.prepare(false); - String sql = queryPlan.getSql(); - return new CQueryDelete(request, predicates, sql); + return new CQueryUpdate(type, request, predicates, queryPlan.getSql()); } predicates.prepare(true); SqlTree sqlTree = createSqlTree(request, predicates, getHistorySupport(query), getDraftSupport(query)); - boolean includeJoins = sqlTree.isIncludeJoins(); - String sql; - if (!includeJoins) { - // simple - delete from table ... - sql = aliasStrip(buildSql("delete", request, predicates, sqlTree).getSql()); + if (type.equals("Delete")) { + sql = buildDeleteSql(request, rootTableAlias, predicates, sqlTree); } else { - // wrap as - delete from table where id in (select id ...) - sql = buildSql(null, request, predicates, sqlTree).getSql(); - sql = request.getBeanDescriptor().getDeleteByIdInSql() + "in (" + sql + ")"; - String alias = (rootTableAlias == null) ? "t0" : rootTableAlias; - sql = aliasReplace(sql, alias); + sql = buildUpdateSql(request, rootTableAlias, predicates, sqlTree); } // cache the query plan queryPlan = new CQueryPlan(request, sql, sqlTree, false, false, predicates.getLogWhereSql()); - request.putQueryPlan(queryPlan); - return new CQueryDelete(request, predicates, sql); + return new CQueryUpdate(type, request, predicates, sql); + } + + private String buildDeleteSql(OrmQueryRequest request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) { + + if (!sqlTree.isIncludeJoins()) { + // simple - delete from table ... + return aliasStrip(buildSql("delete", request, predicates, sqlTree).getSql()); + } + // wrap as - delete from table where id in (select id ...) + String sql = buildSql(null, request, predicates, sqlTree).getSql(); + sql = request.getBeanDescriptor().getDeleteByIdInSql() + "in (" + sql + ")"; + String alias = (rootTableAlias == null) ? "t0" : rootTableAlias; + sql = aliasReplace(sql, alias); + return sql; + } + + private String buildUpdateSql(OrmQueryRequest request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) { + + String updateClause = "update "+request.getBeanDescriptor().getBaseTable()+" set "+predicates.getDbUpdateClause(); + + if (!sqlTree.isIncludeJoins()) { + // simple - update table set ... where ... + return aliasStrip(buildSql(updateClause, request, predicates, sqlTree).getSql()); + } + // wrap as - update table set ... where id in (select id ...) + String sql = buildSql(null, request, predicates, sqlTree).getSql(); + sql = updateClause + " " + request.getBeanDescriptor().getWhereIdInSql() + "in (" + sql + ")"; + String alias = (rootTableAlias == null) ? "t0" : rootTableAlias; + sql = aliasReplace(sql, alias); + return sql; } /** @@ -423,11 +444,10 @@ public class CQueryBuilder { } } - sb.append(" from "); - - // build the from clause potentially with joins - // required only for the predicates - sb.append(select.getFromSql()); + if (selectClause == null || !selectClause.startsWith("update")) { + sb.append(" from "); + sb.append(select.getFromSql()); + } String inheritanceWhere = select.getInheritanceWhereSql(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java index 72a9d3e0c..43f793e14 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryEngine.java @@ -51,10 +51,18 @@ public class CQueryEngine { } public int delete(OrmQueryRequest request) { + CQueryUpdate query = queryBuilder.buildUpdateQuery("Delete", request); + return executeUpdate(request, query); + } - CQueryDelete query = queryBuilder.buildDeleteQuery(request); + public int update(OrmQueryRequest request) { + CQueryUpdate query = queryBuilder.buildUpdateQuery("Update", request); + return executeUpdate(request, query); + } + + private int executeUpdate(OrmQueryRequest request, CQueryUpdate query) { try { - int rows = query.delete(); + int rows = query.execute(); if (request.isLogSql()) { String logSql = query.getGeneratedSql(); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java index 4b69efc4b..645221b6e 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryPredicates.java @@ -9,11 +9,12 @@ import com.avaje.ebeaninternal.server.core.OrmQueryRequest; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany; import com.avaje.ebeaninternal.server.deploy.DeployParser; +import com.avaje.ebeaninternal.server.expression.DefaultExpressionRequest; import com.avaje.ebeaninternal.server.persist.Binder; import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties; +import com.avaje.ebeaninternal.server.querydefn.OrmUpdateProperties; import com.avaje.ebeaninternal.server.type.DataBind; import com.avaje.ebeaninternal.server.util.BindParamsParser; -import com.avaje.ebeaninternal.server.expression.DefaultExpressionRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -112,6 +113,8 @@ public class CQueryPredicates { private String dbOrderBy; + private String dbUpdateClause; + /** * Includes from where and order by clauses. */ @@ -133,6 +136,12 @@ public class CQueryPredicates { public String bind(DataBind dataBind) throws SQLException { + OrmUpdateProperties updateProperties = query.getUpdateProperties(); + if (updateProperties != null) { + // bind the update set clause + updateProperties.bind(binder, dataBind); + } + if (query.isVersionsBetween() && binder.isBindAsOfWithFromClause()) { // sql2011 based versions between timestamp syntax Timestamp start = query.getVersionStart(); @@ -196,6 +205,15 @@ public class CQueryPredicates { return dataBind.log().toString(); } + private void buildUpdateClause(boolean buildSql, DeployParser deployParser) { + if (buildSql) { + OrmUpdateProperties updateProperties = query.getUpdateProperties(); + if (updateProperties != null) { + dbUpdateClause = updateProperties.buildSetClause(deployParser); + } + } + } + private void buildBindHavingRawSql(boolean buildSql, boolean parseRaw, DeployParser deployParser) { if (buildSql || bindParams != null) { // having clause with named parameters... @@ -266,15 +284,12 @@ public class CQueryPredicates { prepare(buildSql, true, deployParser); } - public void prepareRawSql(DeployParser deployParser) { - prepare(true, false, deployParser); - } - /** * This combines the sql from named/positioned parameters and expressions. */ private void prepare(boolean buildSql, boolean parseRaw, DeployParser deployParser) { + buildUpdateClause(buildSql, deployParser); buildBindWhereRawSql(buildSql, parseRaw, deployParser); buildBindHavingRawSql(buildSql, parseRaw, deployParser); @@ -473,6 +488,13 @@ public class CQueryPredicates { return where.getBindValues(); } + /** + * Return the db update set clause for an UpdateQuery. + */ + public String getDbUpdateClause() { + return dbUpdateClause; + } + /** * Return the db column version of the combined where clause. */ diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryRowCount.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryRowCount.java index 9a8d81da1..8949b4868 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryRowCount.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryRowCount.java @@ -4,9 +4,6 @@ import com.avaje.ebeaninternal.api.SpiQuery; import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.server.core.OrmQueryRequest; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.type.DataBind; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.persistence.PersistenceException; import java.sql.Connection; @@ -19,8 +16,6 @@ import java.sql.SQLException; */ public class CQueryRowCount { - private static final Logger logger = LoggerFactory.getLogger(CQueryRowCount.class); - /** * The overall find request wrapper object. */ @@ -137,29 +132,12 @@ public class CQueryRowCount { /** * Close the resources. - *

- * The jdbc resultSet and statement need to be closed. Its important that - * this method is called. - *

*/ private void close() { - try { - if (rset != null) { - rset.close(); - rset = null; - } - } catch (SQLException e) { - logger.error(null, e); - } - try { - if (pstmt != null) { - pstmt.close(); - pstmt = null; - } - } catch (SQLException e) { - logger.error(null, e); - } + UtilJdbc.close(rset); + UtilJdbc.close(pstmt); + rset = null; + pstmt = null; } - } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryDelete.java b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryUpdate.java similarity index 77% rename from src/main/java/com/avaje/ebeaninternal/server/query/CQueryDelete.java rename to src/main/java/com/avaje/ebeaninternal/server/query/CQueryUpdate.java index 5f005ad33..e8a012af4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/CQueryDelete.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/CQueryUpdate.java @@ -4,9 +4,6 @@ import com.avaje.ebeaninternal.api.SpiQuery; import com.avaje.ebeaninternal.api.SpiTransaction; import com.avaje.ebeaninternal.server.core.OrmQueryRequest; import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; -import com.avaje.ebeaninternal.server.type.DataBind; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.sql.Connection; import java.sql.PreparedStatement; @@ -15,9 +12,7 @@ import java.sql.SQLException; /** * Executes the delete query. */ -public class CQueryDelete { - - private static final Logger logger = LoggerFactory.getLogger(CQueryDelete.class); +public class CQueryUpdate { private final OrmQueryRequest request; @@ -35,6 +30,8 @@ public class CQueryDelete { */ private final String sql; + private final String type; + /** * The statement used to create the resultSet. */ @@ -49,8 +46,8 @@ public class CQueryDelete { /** * Create the Sql select based on the request. */ - public CQueryDelete(OrmQueryRequest request, CQueryPredicates predicates, String sql) { - + public CQueryUpdate(String type, OrmQueryRequest request, CQueryPredicates predicates, String sql) { + this.type = type; this.request = request; this.query = request.getQuery(); this.sql = sql; @@ -63,14 +60,12 @@ public class CQueryDelete { * Return a summary description of this query. */ public String getSummary() { - //noinspection StringBufferReplaceableByString StringBuilder sb = new StringBuilder(80); - sb.append("Delete exeMicros[").append(executionTimeMicros) + sb.append(type).append(" exeMicros[").append(executionTimeMicros) .append("] rows[").append(rowCount) .append("] type[").append(desc.getName()) .append("] predicates[").append(predicates.getLogWhereSql()) .append("] bind[").append(bindLog).append("]"); - return sb.toString(); } @@ -89,12 +84,11 @@ public class CQueryDelete { } /** - * Execute the query returning the row count. + * Execute the update or delete statement returning the row count. */ - public int delete() throws SQLException { + public int execute() throws SQLException { long startNano = System.nanoTime(); - try { SpiTransaction t = request.getTransaction(); @@ -122,14 +116,8 @@ public class CQueryDelete { * Close the resources. */ private void close() { - try { - if (pstmt != null) { - pstmt.close(); - pstmt = null; - } - } catch (SQLException e) { - logger.error(null, e); - } + UtilJdbc.close(pstmt); + pstmt = null; } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java b/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java index f32c791da..3342637d4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java +++ b/src/main/java/com/avaje/ebeaninternal/server/query/DefaultOrmQueryEngine.java @@ -53,6 +53,12 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine { return queryEngine.delete(request); } + public int update(OrmQueryRequest request) { + + flushJdbcBatchOnQuery(request); + return queryEngine.update(request); + } + public int findRowCount(OrmQueryRequest request) { flushJdbcBatchOnQuery(request); diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/UtilJdbc.java b/src/main/java/com/avaje/ebeaninternal/server/query/UtilJdbc.java new file mode 100644 index 000000000..824e0f0d5 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/query/UtilJdbc.java @@ -0,0 +1,34 @@ +package com.avaje.ebeaninternal.server.query; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +public class UtilJdbc { + + private static final Logger logger = LoggerFactory.getLogger(UtilJdbc.class); + + public static void close(ResultSet resultSet) { + try { + if (resultSet != null) { + resultSet.close(); + } + } catch (SQLException e) { + logger.error("Error closing ResultSet", e); + } + } + + public static void close(PreparedStatement statement) { + try { + if (statement != null) { + statement.close(); + } + } catch (SQLException e) { + logger.error("Error closing PreparedStatement", e); + } + } + +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 2d343c0cf..472b1a698 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -230,6 +230,8 @@ public class DefaultOrmQuery implements SpiQuery { private boolean useDocStore; + private OrmUpdateProperties updateProperties; + public DefaultOrmQuery(BeanDescriptor desc, EbeanServer server, ExpressionFactory expressionFactory) { this.beanDescriptor = desc; this.beanType = desc.getBeanType(); @@ -831,7 +833,7 @@ public class DefaultOrmQuery implements SpiQuery { queryPlanKey = new OrmQueryPlanKey(includeTableJoin, type, detail, maxRows, firstRow, disableLazyLoading, rawWhereClause, orderBy, query, additionalWhere, additionalHaving, distinct, sqlDistinct, mapKey, id, bindParams, whereExpressions, havingExpressions, - temporalMode, forUpdate, rootTableAlias, rawSql); + temporalMode, forUpdate, rootTableAlias, rawSql, updateProperties); return queryPlanKey; } @@ -1036,6 +1038,11 @@ public class DefaultOrmQuery implements SpiQuery { return server.delete(this, null); } + @Override + public int update() { + return server.update(this, null); + } + @Override public List findIds() { // a copy of this query is made in the server @@ -1528,4 +1535,13 @@ public class DefaultOrmQuery implements SpiQuery { } return validation.getUnknownProperties(); } + + public void setUpdateProperties(OrmUpdateProperties updateProperties) { + this.updateProperties = updateProperties; + } + + @Override + public OrmUpdateProperties getUpdateProperties() { + return updateProperties; + } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultUpdateQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultUpdateQuery.java new file mode 100644 index 000000000..b58636ed3 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultUpdateQuery.java @@ -0,0 +1,48 @@ +package com.avaje.ebeaninternal.server.querydefn; + +import com.avaje.ebean.ExpressionList; +import com.avaje.ebean.UpdateQuery; + +/** + * Default implementation of UpdateQuery. + */ +public class DefaultUpdateQuery implements UpdateQuery { + + private final OrmUpdateProperties values = new OrmUpdateProperties(); + + private final DefaultOrmQuery query; + + public DefaultUpdateQuery(DefaultOrmQuery query) { + this.query = query; + query.setUpdateProperties(values); + } + + @Override + public UpdateQuery set(String property, Object value) { + values.set(property, value); + return this; + } + + @Override + public UpdateQuery setNull(String property) { + values.set(property, null); + return this; + } + + @Override + public UpdateQuery setRaw(String propertyExpression) { + values.setRaw(propertyExpression); + return this; + } + + @Override + public UpdateQuery setRaw(String propertyExpression, Object... vals) { + values.setRaw(propertyExpression, vals); + return this; + } + + @Override + public ExpressionList where() { + return query.where(); + } +} diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKey.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKey.java index 616d8b962..7565262fd 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKey.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKey.java @@ -35,11 +35,12 @@ public class OrmQueryPlanKey implements CQueryPlanKey { private final SpiQuery.TemporalMode temporalMode; private final boolean forUpdate; private final String rootTableAlias; + private final OrmUpdateProperties updateProperties; private final int planHash; private final int bindCount; - public OrmQueryPlanKey(TableJoin includeTableJoin, SpiQuery.Type type, OrmQueryDetail detail, int maxRows, int firstRow, boolean disableLazyLoading, String rawWhereClause, OrderBy orderBy, String query, String additionalWhere, String additionalHaving, boolean distinct, boolean sqlDistinct, String mapKey, Object id, BindParams bindParams, SpiExpression whereExpressions, SpiExpression havingExpressions, SpiQuery.TemporalMode temporalMode, boolean forUpdate, String rootTableAlias, RawSql rawSql) { + public OrmQueryPlanKey(TableJoin includeTableJoin, SpiQuery.Type type, OrmQueryDetail detail, int maxRows, int firstRow, boolean disableLazyLoading, String rawWhereClause, OrderBy orderBy, String query, String additionalWhere, String additionalHaving, boolean distinct, boolean sqlDistinct, String mapKey, Object id, BindParams bindParams, SpiExpression whereExpressions, SpiExpression havingExpressions, SpiQuery.TemporalMode temporalMode, boolean forUpdate, String rootTableAlias, RawSql rawSql, OrmUpdateProperties updateProperties) { this.includeTableJoin = includeTableJoin; this.type = type; @@ -61,6 +62,7 @@ public class OrmQueryPlanKey implements CQueryPlanKey { this.temporalMode = temporalMode; this.forUpdate = forUpdate; this.rootTableAlias = rootTableAlias; + this.updateProperties = updateProperties; this.rawSqlKey = (rawSql == null) ? null : rawSql.getKey(); // exclude bind values and things unrelated to the sql being generated @@ -91,6 +93,9 @@ public class OrmQueryPlanKey implements CQueryPlanKey { if (having != null) { having.queryPlanHash(builder); } + if (updateProperties != null) { + updateProperties.buildQueryPlanHash(builder); + } this.planHash = builder.getPlanHash(); this.bindCount = builder.getBindCount(); @@ -128,6 +133,7 @@ public class OrmQueryPlanKey implements CQueryPlanKey { if (orderByAsSting != null ? !orderByAsSting.equals(that.orderByAsSting) : that.orderByAsSting != null) return false; if (where != null ? !where.isSameByPlan(that.where) : that.where != null) return false; if (having != null ? !having.isSameByPlan(that.having) : that.having != null) return false; + if (updateProperties != null ? !updateProperties.isSameByPlan(that.updateProperties) : that.updateProperties != null) return false; if (rawSqlKey != null ? !rawSqlKey.equals(that.rawSqlKey) : that.rawSqlKey != null) return false; // if (detail != null ? !detail.equals(that.detail) : that.detail != null) return false; diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmUpdateProperties.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmUpdateProperties.java new file mode 100644 index 000000000..ab1f9cf21 --- /dev/null +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmUpdateProperties.java @@ -0,0 +1,209 @@ +package com.avaje.ebeaninternal.server.querydefn; + +import com.avaje.ebeaninternal.api.HashQueryPlanBuilder; +import com.avaje.ebeaninternal.server.deploy.DeployParser; +import com.avaje.ebeaninternal.server.persist.Binder; +import com.avaje.ebeaninternal.server.type.DataBind; + +import java.sql.SQLException; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +/** + * Set properties for a UpdateQuery. + */ +public class OrmUpdateProperties { + + private static final NullValue NULL_VALUE = new NullValue(); + + private static final NoneValue NONE_VALUE = new NoneValue(); + + /** + * Bind value used in the set clause for update query. + * It may/may not have bind values etc. + */ + public static abstract class Value { + + public void bind(Binder binder, DataBind dataBind) throws SQLException { + // default to no bind values + } + + public String bindClause() { + return ""; + } + + public int getBindCount() { + return 0; + } + } + + /** + * Set property to null. + */ + static class NullValue extends Value { + @Override + public String bindClause() { + return "=null"; + } + } + + /** + * Set property to a simple value. + */ + static class SimpleValue extends Value { + + final Object value; + + SimpleValue(Object value) { + this.value = value; + } + + @Override + public int getBindCount() { + return 1; + } + + @Override + public String bindClause() { + return "=?"; + } + + @Override + public void bind(Binder binder, DataBind dataBind) throws SQLException { + binder.bindObject(dataBind, value); + } + } + + /** + * Set using an expression with no bind value. + */ + static class NoneValue extends Value { + @Override + public String bindClause() { + return ""; + } + } + + /** + * Set using an expression with many bind values. + */ + static class RawArrayValue extends Value { + + final Object[] bindValues; + + public RawArrayValue(Object[] bindValues) { + this.bindValues = bindValues; + } + + @Override + public int getBindCount() { + return bindValues.length; + } + + @Override + public void bind(Binder binder, DataBind dataBind) throws SQLException { + for (Object val : bindValues) { + binder.bindObject(dataBind, val); + } + } + } + + /** + * The set properties/expressions and their bind values. + */ + private LinkedHashMap values = new LinkedHashMap(); + + /** + * Normal set property. + */ + public void set(String propertyName, Object value) { + if (value == null) { + values.put(propertyName, NULL_VALUE); + + } else { + values.put(propertyName, new SimpleValue(value)); + } + } + + /** + * Set a raw expression with no bind values. + */ + public void setRaw(String propertyName) { + values.put(propertyName, NONE_VALUE); + } + + /** + * Set a raw expression with many bind values. + */ + public void setRaw(String propertyExpression, Object... vals) { + if (vals.length == 0) { + setRaw(propertyExpression); + } else { + values.put(propertyExpression, new RawArrayValue(vals)); + } + } + + /** + * Return true if this update has the same logical set clause. + */ + public boolean isSameByPlan(OrmUpdateProperties that) { + return that.values.size() == values.size() + && logicalSetClause().equals(that.logicalSetClause()); + } + + /** + * Build the hash for the query plan caching. + */ + public void buildQueryPlanHash(HashQueryPlanBuilder builder) { + builder.add(OrmUpdateProperties.class); + Set> entries = values.entrySet(); + for (Map.Entry entry : entries) { + builder.add(entry.getKey()); + builder.bind(entry.getValue().getBindCount()); + } + } + + /** + * Bind all the bind values for the update set clause. + */ + public void bind(Binder binder, DataBind dataBind) throws SQLException { + for (Value bindValue : values.values()) { + bindValue.bind(binder, dataBind); + } + } + + /** + * Build the actual set clause converting logical property names to db columns etc. + */ + public String buildSetClause(DeployParser deployParser) { + + int setCount = 0; + StringBuilder sb = new StringBuilder(); + + for (Map.Entry entry : values.entrySet()) { + String property = entry.getKey(); + if (setCount++ > 0) { + sb.append(", "); + } + // translate to db columns and remove table alias placeholders + sb.append(deployParser.parse(property).replace("${}", "")); + sb.append(entry.getValue().bindClause()); + } + return sb.toString(); + } + + /** + * Return a logical set clause to use for isSameByPlan() use. + */ + private String logicalSetClause() { + + StringBuilder sb = new StringBuilder(); + for (Map.Entry entry : values.entrySet()) { + sb.append(", "); + sb.append(entry.getKey()).append(entry.getValue().bindClause()); + } + return sb.toString(); + } + +} diff --git a/src/test/java/com/avaje/ebean/UpdateQueryTest.java b/src/test/java/com/avaje/ebean/UpdateQueryTest.java new file mode 100644 index 000000000..98e3e6535 --- /dev/null +++ b/src/test/java/com/avaje/ebean/UpdateQueryTest.java @@ -0,0 +1,168 @@ +package com.avaje.ebean; + +import com.avaje.tests.model.basic.Country; +import com.avaje.tests.model.basic.Customer; +import org.junit.Test; + +import java.sql.Timestamp; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class UpdateQueryTest extends BaseTestCase { + + @Test + public void basic() { + + EbeanServer server = server(); + UpdateQuery update = server.update(Customer.class); + Query query = update + .set("status", Customer.Status.ACTIVE) + .set("updtime", new Timestamp(System.currentTimeMillis())) + .where() + .eq("status", Customer.Status.NEW) + .gt("id", 1000) + .query(); + + query.update(); + + assertThat(query.getGeneratedSql()).contains("update o_customer set status=?, updtime=? where status = ? and id > ?"); + } + + + @Test + public void withJoin() { + + EbeanServer server = server(); + + Country nz = server.getReference(Country.class, "NZ"); + + UpdateQuery update = server.update(Customer.class); + Query query = update + .set("status", Customer.Status.ACTIVE) + .set("updtime", new Timestamp(System.currentTimeMillis())) + .where() + .eq("status", Customer.Status.NEW) + .eq("billingAddress.country", nz) + //.isEmpty("contacts") + .gt("id", 1000) + .query(); + + query.update(); + + assertThat(query.getGeneratedSql()).contains("update o_customer set status=?, updtime=? where id in (select t0.id c0 from o_customer t0 left outer join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and t1.country_code = ? and t0.id > ? )"); + } + + @Test + public void whereIsEmpty() { + + EbeanServer server = server(); + + Query updateQuery = server + .update(Customer.class) + .set("status", Customer.Status.ACTIVE) + .where() + .isEmpty("contacts") + .gt("id", 1000) + .query(); + + updateQuery.update(); + + assertThat(updateQuery.getGeneratedSql()).contains("update o_customer set status=? where not exists (select 1 from contact where customer_id = id) and id > ?"); + } + + @Test + public void setNull() { + + EbeanServer server = server(); + + Query updateQuery = server + .update(Customer.class) + .setNull("status") + .where() + .gt("id", 1000) + .query(); + + updateQuery.update(); + + assertThat(updateQuery.getGeneratedSql()).contains("update o_customer set status=null where id > ?"); + } + + @Test + public void set_whenValueIsNull_expectNull() { + + EbeanServer server = server(); + + Query updateQuery = server + .update(Customer.class) + .set("status", null) + .where() + .gt("id", 1000) + .query(); + + updateQuery.update(); + + assertThat(updateQuery.getGeneratedSql()).contains("update o_customer set status=null where id > ?"); + } + + @Test + public void setExpression() { + + EbeanServer server = server(); + + Query updateQuery = server + .update(Customer.class) + .setRaw("status = coalesce(status, 'A')") + .where() + .gt("id", 1000) + .query(); + + updateQuery.update(); + + assertThat(updateQuery.getGeneratedSql()).contains("update o_customer set status = coalesce(status, 'A') where id > ?"); + } + + @Test + public void setExpression_withBind() { + + EbeanServer server = server(); + + Query updateQuery = server + .update(Customer.class) + .setRaw("status = coalesce(status, ?)", Customer.Status.ACTIVE) + .where() + .gt("id", 1000) + .query(); + + updateQuery.update(); + + assertThat(updateQuery.getGeneratedSql()).contains("update o_customer set status = coalesce(status, ?) where id > ?"); + } + + @Test + public void fluidSyntax() { + + EbeanServer server = server(); + + int rows = server + .update(Customer.class) + .setRaw("status = coalesce(status, ?)", Customer.Status.ACTIVE) + .where() + .gt("id", 10000) + .update(); + + assertThat(rows).isEqualTo(0); + } + + @Test + public void useViaEbean() { + + int rows = Ebean.update(Customer.class) + .setRaw("status = coalesce(status, ?)", Customer.Status.ACTIVE) + .where() + .gt("id", 10000) + .update(); + + assertThat(rows).isEqualTo(0); + } +} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java index adab60645..15408af46 100644 --- a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java +++ b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java @@ -170,6 +170,16 @@ public class TDSpiEbeanServer implements SpiEbeanServer { return 0; } + @Override + public UpdateQuery update(Class beanType) { + return null; + } + + @Override + public int update(Query query, Transaction transaction) { + return 0; + } + @Override public List> findVersions(Query query, Transaction transaction) { return null; diff --git a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKeyTest.java b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKeyTest.java index ae1af12d8..41d8c7084 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKeyTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPlanKeyTest.java @@ -21,8 +21,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_defaults() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -32,8 +32,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { TableJoin tableJoin = tableJoin("id", "customer_id"); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -44,8 +44,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { TableJoin tableJoin1 = tableJoin("id", "customer_id"); TableJoin tableJoin2 = tableJoin("id", "other_customer_id"); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -56,8 +56,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { TableJoin tableJoin1 = tableJoin("id", "customer_id"); TableJoin tableJoin2 = tableJoin("id", "customer_id"); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(tableJoin1, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(tableJoin2, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -73,8 +73,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_diffQueryType() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.LIST, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.LIST, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -82,8 +82,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_firstRowsDifferent() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 10, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 10, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -91,8 +91,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_maxRowsDifferent() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -100,8 +100,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_firstRowsMaxRowsSame() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 10, 20, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -109,8 +109,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_diffDisableLazyLoading() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, true, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, true, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -118,8 +118,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_diffRawWhereNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -127,8 +127,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_diffRawWhere() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawDiff", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawWhere", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, "rawDiff", null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -137,8 +137,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { public void equals_when_diffOrderByNull() { OrderBy o1 = new OrderBy("id"); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -148,8 +148,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { OrderBy o1 = new OrderBy("id, name"); OrderBy o2 = new OrderBy("id, name"); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o2, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o1, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, o2, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -157,164 +157,164 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { @Test public void equals_when_diffQueryNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffQuery() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "queryDiff", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "queryDiff", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_querySame() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, "query", null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffAddWhereNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffAddWhere() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "diff", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "diff", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameAddWhere() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, "addWhere", null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffAddHavingNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffAddHaving() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "diff", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "diff", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameAddHaving() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, "addHaving", false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffDistinct() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameDistinct() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, true, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffSqlDistinct() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameSqlDistinct() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, true, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffMapKeyNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffMapKey() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "diff", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "diff", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameMapKey() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, "mapKey", null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffIdNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_idBothGiven() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 23, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 42, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, 23, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @Test public void equals_when_diffTemporalMode() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.DRAFT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.DRAFT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffForUpdate() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, true, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, true, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffRootAliasNull() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @Test public void equals_when_diffRootAlias() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "diff", null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "diff", null, null); assertDifferent(key1, key2); } @Test public void equals_when_sameRootAlias() { - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, "rootAlias", null, null); assertSame(key1, key2); } @@ -341,8 +341,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpressionList list1 = list_id_eq_42(); SpiExpressionList list2 = list_id_eq_43(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list2, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list2, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -353,8 +353,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpressionList where1 = list_id_eq_42(); SpiExpressionList where2 = list_id_eq_42_and_name_eq_rob(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where1, null, SpiQuery.TemporalMode.DRAFT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where2, null, SpiQuery.TemporalMode.DRAFT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where1, null, SpiQuery.TemporalMode.DRAFT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, where2, null, SpiQuery.TemporalMode.DRAFT, false, null, null, null); assertDifferent(key1, key2); } @@ -363,8 +363,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpressionList list1 = list_id_eq_42(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -373,8 +373,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpressionList list1 = list_id_eq_42(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, list1, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -384,8 +384,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpression having1 = list_id_eq_42().copyForPlanKey(); SpiExpression having2 = list_id_eq_42_and_name_eq_rob().copyForPlanKey(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -395,8 +395,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpression having1 = list_id_eq_42().copyForPlanKey(); SpiExpression having2 = list_id_eq_42().copyForPlanKey(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having2, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertSame(key1, key2); } @@ -405,8 +405,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpression having1 = list_id_eq_42().copyForPlanKey(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); } @@ -415,8 +415,8 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest { SpiExpression having1 = list_id_eq_42().copyForPlanKey(); - OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null); - OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null); + OrmQueryPlanKey key1 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, null, SpiQuery.TemporalMode.CURRENT, false, null, null, null); + OrmQueryPlanKey key2 = new OrmQueryPlanKey(null, SpiQuery.Type.BEAN, null, 0, 0, false, null, null, null, null, null, false, false, null, null, null, null, having1, SpiQuery.TemporalMode.CURRENT, false, null, null, null); assertDifferent(key1, key2); }