mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
54
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
923828ce87 | ||
|
|
e195f20981 | ||
|
|
86d0216159 | ||
|
|
a4698ea1b6 | ||
|
|
888384f7db | ||
|
|
817c946eeb | ||
|
|
1749c2cb4c | ||
|
|
3afd3c4530 | ||
|
|
e5f98f1b7a | ||
|
|
2e496c9e1e | ||
|
|
5975694538 | ||
|
|
03a42f7f6e | ||
|
|
84f1e05eb4 | ||
|
|
da20ced1ed | ||
|
|
1f1a6e2c04 | ||
|
|
6b83800a83 | ||
|
|
c344551e4d | ||
|
|
6b4aff7191 | ||
|
|
fc7fae35c9 | ||
|
|
7929d8c0b8 | ||
|
|
058766dd92 | ||
|
|
4fdb8a77b4 | ||
|
|
56be1fc047 | ||
|
|
192a946cf6 | ||
|
|
aa7b15fd6e | ||
|
|
cb74ef01e0 | ||
|
|
829dfcb013 | ||
|
|
25b6d2a5a0 | ||
|
|
14fbc3a955 | ||
|
|
e41da2f995 | ||
|
|
ea60e42a4d | ||
|
|
efce6b57e1 | ||
|
|
988e4c7386 | ||
|
|
9e1d7ab722 | ||
|
|
0c03a8b925 | ||
|
|
37a66f1ee2 | ||
|
|
a02673359d | ||
|
|
f9d13cbba7 | ||
|
|
f787483e30 | ||
|
|
9e33f36808 | ||
|
|
6a7e6caa66 | ||
|
|
5a4a0e3886 | ||
|
|
c3f586c461 | ||
|
|
99f7243d6c | ||
|
|
7026c00290 | ||
|
|
448d94a335 | ||
|
|
961a7ef7ea | ||
|
|
5cef1ad017 | ||
|
|
b814ca6e81 | ||
|
|
a24e6b6064 | ||
|
|
b751823abb | ||
|
|
f3cb7e2cfd | ||
|
|
31d7c6fed8 | ||
|
|
c5fb1dbe23 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.33.2</version>
|
||||
<version>11.35.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.33.2</tag>
|
||||
<tag>ebean-11.35.2</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -120,10 +120,16 @@
|
||||
<version>4.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-types</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>4.3.2</version>
|
||||
<version>4.5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -135,7 +141,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>11.13.1</version>
|
||||
<version>11.14.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -188,6 +194,21 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope to compile with java 11 -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.4.0-b180830.0438</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope for Postgres JSON/JSONB support -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
@@ -222,7 +243,7 @@
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-agentloader</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<version>3.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -259,7 +280,7 @@
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>6.4.0.jre8</version>
|
||||
<version>7.2.0.jre8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -327,9 +348,10 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>2.22.1</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<failIfNoTests>false</failIfNoTests>
|
||||
<includes>
|
||||
<include>**/Test*.java</include>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.config.ContainerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
|
||||
/**
|
||||
* Creates Database instances.
|
||||
* <p>
|
||||
* This uses either DatabaseConfig or properties in the application.properties file to
|
||||
* configure and create a Database instance.
|
||||
* </p>
|
||||
* <p>
|
||||
* The Database instance can either be registered with the DB singleton or
|
||||
* not. The DB singleton effectively holds a map of Database by a name.
|
||||
* If the Database is registered with the DB singleton you can retrieve it
|
||||
* later via {@link DB#byName(String)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* One Database can be nominated as the 'default/primary' Database. Many
|
||||
* methods on the DB singleton such as {@link DB#find(Class)} are just a
|
||||
* convenient way of using the 'default/primary' Database.
|
||||
* </p>
|
||||
*/
|
||||
public class DatabaseFactory {
|
||||
|
||||
/**
|
||||
* Initialise the container with clustering configuration.
|
||||
* <p>
|
||||
* Call this prior to creating any Database instances or alternatively set the
|
||||
* ContainerConfig on the ServerConfig when creating the first Database instance.
|
||||
*/
|
||||
public static synchronized void initialiseContainer(ContainerConfig containerConfig) {
|
||||
EbeanServerFactory.initialiseContainer(containerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using ebean.properties to configure the server.
|
||||
*/
|
||||
public static synchronized Database create(String name) {
|
||||
return EbeanServerFactory.create(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the ServerConfig object to configure the server.
|
||||
*/
|
||||
public static synchronized Database create(DatabaseConfig config) {
|
||||
return EbeanServerFactory.create(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
|
||||
*/
|
||||
public static synchronized Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
|
||||
return EbeanServerFactory.createWithContextClassLoader(config, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown gracefully all EbeanServers cleaning up any resources as required.
|
||||
* <p>
|
||||
* This is typically invoked via JVM shutdown hook and not explicitly called.
|
||||
* </p>
|
||||
*/
|
||||
public static synchronized void shutdown() {
|
||||
EbeanServerFactory.shutdown();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public final class Ebean {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
|
||||
|
||||
static {
|
||||
EbeanVersion.getVersion(); // initalizes the version class and logs the version.
|
||||
EbeanVersion.getVersion(); // initialises the version class and logs the version.
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -71,7 +71,6 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
|
||||
return Ebean.getExpressionFactory().inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
@@ -79,7 +78,6 @@ public class Expr {
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
public static Expression between(String propertyName, Object value1, Object value2) {
|
||||
|
||||
return Ebean.getExpressionFactory().between(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
@@ -87,7 +85,6 @@ public class Expr {
|
||||
* Between - value between two given properties.
|
||||
*/
|
||||
public static Expression between(String lowProperty, String highProperty, Object value) {
|
||||
|
||||
return Ebean.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
@@ -253,6 +250,43 @@ public class Expr {
|
||||
return Ebean.getExpressionFactory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* In where null or empty values means that no predicate is added to the query.
|
||||
* <p>
|
||||
* That is, only add the IN predicate if the values are not null or empty.
|
||||
* <p>
|
||||
* Without this we typically need to code an <code>if</code> block to only add
|
||||
* the IN predicate if the collection is not empty like:
|
||||
* </p>
|
||||
*
|
||||
* <h3>Without inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where() // add some predicates
|
||||
* .eq("status", Status.NEW);
|
||||
*
|
||||
* if (ids != null && !ids.isEmpty()) {
|
||||
* query.where().in("customer.id", ids);
|
||||
* }
|
||||
*
|
||||
* query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Using inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where()
|
||||
* .eq("status", Status.NEW)
|
||||
* .inOrEmpty("customer.id", ids)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return Ebean.getExpressionFactory().inOrEmpty(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Id Equal to - ID property is equal to the value.
|
||||
*/
|
||||
|
||||
@@ -122,6 +122,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression eq(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Equal To or Null - property equal to the given value or null.
|
||||
*/
|
||||
Expression eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -157,6 +162,25 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression inRange(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
* Value in Range between 2 properties.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* .startDate.inRangeWith(endDate, now)
|
||||
*
|
||||
* // which equates to
|
||||
* startDate <= now and (endDate > now or endDate is null)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This is a convenience expression combining a number of simple expressions.
|
||||
* The most common use of this could be called "effective dating" where 2 date or
|
||||
* timestamp columns represent the date range in which
|
||||
*/
|
||||
Expression inRangeWith(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
@@ -167,6 +191,14 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression betweenProperties(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than Or Null - property greater than the given value or null.
|
||||
* <p>
|
||||
* A convenient expression combining GT and Is Null. Most often useful for range
|
||||
* expressions where the top range value is nullable.
|
||||
*/
|
||||
Expression gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
@@ -178,6 +210,14 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression ge(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Null - property less than the given value or null.
|
||||
* <p>
|
||||
* A convenient expression combining LT and Is Null. Most often useful for range
|
||||
* expressions where the bottom range value is nullable.
|
||||
*/
|
||||
Expression ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
@@ -285,6 +325,41 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression in(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* In where null or empty values means that no predicate is added to the query.
|
||||
* <p>
|
||||
* That is, only add the IN predicate if the values are not null or empty.
|
||||
* <p>
|
||||
* Without this we typically need to code an <code>if</code> block to only add
|
||||
* the IN predicate if the collection is not empty like:
|
||||
* </p>
|
||||
*
|
||||
* <h3>Without inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where() // add some predicates
|
||||
* .eq("status", Status.NEW);
|
||||
*
|
||||
* if (ids != null && !ids.isEmpty()) {
|
||||
* query.where().in("customer.id", ids);
|
||||
* }
|
||||
*
|
||||
* query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Using inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where()
|
||||
* .eq("status", Status.NEW)
|
||||
* .inOrEmpty("customer.id", ids)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Expression inOrEmpty(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
|
||||
@@ -785,6 +785,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> eq(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Equal To or Null - property is equal to a given value or null.
|
||||
*/
|
||||
ExpressionList<T> eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -802,6 +807,25 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> ine(String propertyName, String value);
|
||||
|
||||
/**
|
||||
* Value in Range between 2 properties.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* .startDate.inRangeWith(endDate, now)
|
||||
*
|
||||
* // which equates to
|
||||
* startDate <= now and (endDate > now or endDate is null)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This is a convenience expression combining a number of simple expressions.
|
||||
* The most common use of this could be called "effective dating" where 2 date or
|
||||
* timestamp columns represent the date range in which
|
||||
*/
|
||||
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* <p>
|
||||
@@ -825,6 +849,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> gt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Null - property greater than the given value or null.
|
||||
*/
|
||||
ExpressionList<T> gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
@@ -836,6 +865,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> lt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Null - property less than the given value or null.
|
||||
*/
|
||||
ExpressionList<T> ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
@@ -969,6 +1003,41 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> in(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* In where null or empty values means that no predicate is added to the query.
|
||||
* <p>
|
||||
* That is, only add the IN predicate if the values are not null or empty.
|
||||
* <p>
|
||||
* Without this we typically need to code an <code>if</code> block to only add
|
||||
* the IN predicate if the collection is not empty like:
|
||||
* </p>
|
||||
*
|
||||
* <h3>Without inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where() // add some predicates
|
||||
* .eq("status", Status.NEW);
|
||||
*
|
||||
* if (ids != null && !ids.isEmpty()) {
|
||||
* query.where().in("customer.id", ids);
|
||||
* }
|
||||
*
|
||||
* query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Using inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where()
|
||||
* .eq("status", Status.NEW)
|
||||
* .inOrEmpty("customer.id", ids)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
* <p>
|
||||
@@ -1213,6 +1282,68 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> raw(String raw);
|
||||
|
||||
/**
|
||||
* Only add the raw expression if the values is not null or empty.
|
||||
* <p>
|
||||
* This is a pure convenience expression to make it nicer to deal with the pattern where we use
|
||||
* raw() expression with a subquery and only want to add the subquery predicate when the collection
|
||||
* of values is not empty.
|
||||
* </p>
|
||||
* <h3>Without inOrEmpty()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where() // add some predicates
|
||||
* .eq("status", Status.NEW);
|
||||
*
|
||||
* // common pattern - we can use rawOrEmpty() instead
|
||||
* if (orderIds != null && !orderIds.isEmpty()) {
|
||||
* query.where().raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
|
||||
* }
|
||||
*
|
||||
* query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Using rawOrEmpty()</h3>
|
||||
* Note that in the example below we use the <code>?1</code> bind parameter to get "parameter expansion"
|
||||
* for each element in the collection.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where()
|
||||
* .eq("status", Status.NEW)
|
||||
* // only add the expression if orderIds is not empty
|
||||
* .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Postgres ANY</h3>
|
||||
* With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
|
||||
* rather than <code>IN</code>.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* query.where()
|
||||
* .eq("status", Status.NEW)
|
||||
* .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Note that we need to cast the Postgres array for UUID types like:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* " ... = any(?::uuid[])"
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param raw The raw expression that is typically a subquery
|
||||
* @param values The values which is typically a list or set of id values.
|
||||
*/
|
||||
ExpressionList<T> rawOrEmpty(String raw, Collection<Object> values);
|
||||
|
||||
/**
|
||||
* Add a match expression.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -112,26 +111,26 @@ public class Finder<I, T> {
|
||||
* <p>
|
||||
* This provides full access to the API such as explicit transaction demarcation etc.
|
||||
*/
|
||||
public EbeanServer db() {
|
||||
return Ebean.getServer(serverName);
|
||||
public Database db() {
|
||||
return DB.byName(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return typically a different EbeanServer to the default.
|
||||
* Return typically a different Database to the default.
|
||||
* <p>
|
||||
* This is equivalent to {@link Ebean#getServer(String)}
|
||||
* This is equivalent to {@link DB#byName(String)}
|
||||
*
|
||||
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is
|
||||
* @param server The name of the Database. If this is null then the default EbeanServer is
|
||||
* returned.
|
||||
*/
|
||||
public EbeanServer db(String server) {
|
||||
return Ebean.getServer(server);
|
||||
public Database db(String server) {
|
||||
return DB.byName(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entity reference for this ID.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
|
||||
* Equivalent to {@link Database#getReference(Class, Object)}
|
||||
*/
|
||||
@Nonnull
|
||||
public T ref(I id) {
|
||||
@@ -141,7 +140,7 @@ public class Finder<I, T> {
|
||||
/**
|
||||
* Retrieves an entity by ID.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
* Equivalent to {@link Database#find(Class, Object)}
|
||||
*/
|
||||
@Nullable
|
||||
public T byId(I id) {
|
||||
@@ -151,7 +150,7 @@ public class Finder<I, T> {
|
||||
/**
|
||||
* Delete a bean by Id.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#delete(Class, Object)}
|
||||
* Equivalent to {@link Database#delete(Class, Object)}
|
||||
*/
|
||||
public void deleteById(I id) {
|
||||
db().delete(type, id);
|
||||
@@ -181,7 +180,7 @@ public class Finder<I, T> {
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#update(Class)}
|
||||
* Equivalent to {@link Database#update(Class)}
|
||||
*/
|
||||
public UpdateQuery<T> update() {
|
||||
return db().update(type);
|
||||
@@ -190,7 +189,7 @@ public class Finder<I, T> {
|
||||
/**
|
||||
* Creates a query.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class)}
|
||||
* Equivalent to {@link Database#find(Class)}
|
||||
*/
|
||||
public Query<T> query() {
|
||||
return db().find(type);
|
||||
|
||||
@@ -76,15 +76,14 @@ import io.ebean.bean.EntityBean;
|
||||
public abstract class Model {
|
||||
|
||||
/**
|
||||
* Return the underlying 'default' EbeanServer.
|
||||
* Return the underlying 'default' Database.
|
||||
* <p>
|
||||
* This provides full access to the API such as explicit transaction demarcation etc.
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>{@code
|
||||
*
|
||||
* Transaction transaction = Customer.db().beginTransaction();
|
||||
* try {
|
||||
* try (Transaction transaction = Customer.db().beginTransaction()) {
|
||||
*
|
||||
* // turn off cascade persist for this transaction
|
||||
* transaction.setPersistCascade(false);
|
||||
@@ -104,26 +103,21 @@ public abstract class Model {
|
||||
*
|
||||
* transaction.commit();
|
||||
*
|
||||
* } finally {
|
||||
* transaction.end();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static EbeanServer db() {
|
||||
return Ebean.getDefaultServer();
|
||||
public static Database db() {
|
||||
return DB.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a named EbeanServer that is typically different to the default server.
|
||||
* <p>
|
||||
* If you are using multiple databases then each database has a name and maps to a single
|
||||
* EbeanServer. You can use this method to get an EbeanServer for another database.
|
||||
* Return a named Database that is typically different to the default database.
|
||||
*
|
||||
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is returned.
|
||||
* @param server The name of the Database. If this is null then the default Database is returned.
|
||||
*/
|
||||
public static EbeanServer db(String server) {
|
||||
return Ebean.getServer(server);
|
||||
public static Database db(String server) {
|
||||
return DB.byName(server);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +140,7 @@ public abstract class Model {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see EbeanServer#markAsDirty(Object)
|
||||
* @see Database#markAsDirty(Object)
|
||||
*/
|
||||
public void markAsDirty() {
|
||||
db().markAsDirty(this);
|
||||
@@ -182,7 +176,7 @@ public abstract class Model {
|
||||
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
|
||||
* insert or an update based on that.
|
||||
*
|
||||
* @see EbeanServer#save(Object)
|
||||
* @see Database#save(Object)
|
||||
*/
|
||||
public void save() {
|
||||
db().save(this);
|
||||
@@ -202,7 +196,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Update this entity.
|
||||
*
|
||||
* @see EbeanServer#update(Object)
|
||||
* @see Database#update(Object)
|
||||
*/
|
||||
public void update() {
|
||||
db().update(this);
|
||||
@@ -211,7 +205,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Insert this entity.
|
||||
*
|
||||
* @see EbeanServer#insert(Object)
|
||||
* @see Database#insert(Object)
|
||||
*/
|
||||
public void insert() {
|
||||
db().insert(this);
|
||||
@@ -232,7 +226,7 @@ public abstract class Model {
|
||||
* deleted. Note that, if JDBC batch mode is used then this always returns true.
|
||||
* </p>
|
||||
*
|
||||
* @see EbeanServer#delete(Object)
|
||||
* @see Database#delete(Object)
|
||||
*/
|
||||
public boolean delete() {
|
||||
return db().delete(this);
|
||||
@@ -245,7 +239,7 @@ public abstract class Model {
|
||||
* want to perform a hard/permanent delete.
|
||||
* </p>
|
||||
*
|
||||
* @see EbeanServer#deletePermanent(Object)
|
||||
* @see Database#deletePermanent(Object)
|
||||
*/
|
||||
public boolean deletePermanent() {
|
||||
return db().deletePermanent(this);
|
||||
@@ -275,7 +269,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Refreshes this entity from the database.
|
||||
*
|
||||
* @see EbeanServer#refresh(Object)
|
||||
* @see Database#refresh(Object)
|
||||
*/
|
||||
public void refresh() {
|
||||
db().refresh(this);
|
||||
|
||||
@@ -10,34 +10,30 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Query object for performing native SQL queries that return SqlRow's.
|
||||
* <p>
|
||||
* Firstly note that you can use your own sql queries with <em>entity beans</em>
|
||||
* by using the SqlSelect annotation. This should be your first approach when
|
||||
* wanting to use your own SQL queries.
|
||||
* </p>
|
||||
* <p>
|
||||
* If ORM Mapping is too tight and constraining for your problem then SqlQuery
|
||||
* could be a good approach.
|
||||
* </p>
|
||||
* Query object for performing native SQL queries that return SqlRow or directly read
|
||||
* ResultSet using a RowMapper.
|
||||
* <p>
|
||||
* The returned SqlRow objects are similar to a LinkedHashMap with some type
|
||||
* conversion support added.
|
||||
* </p>
|
||||
* <p>
|
||||
* Refer to {@link DtoQuery} for native sql queries returning DTO beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* Refer to {@link Database#findNative(Class, String)} for native sql queries returning entity beans.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // its typically a good idea to use a named query
|
||||
* // and put the sql in the orm.xml instead of in your code
|
||||
* // example using named parameters
|
||||
*
|
||||
* String sql = "select id, name from customer where name like :name and status_code = :status";
|
||||
*
|
||||
* SqlQuery sqlQuery = Ebean.createSqlQuery(sql);
|
||||
* sqlQuery.setParameter("name", "Acme%");
|
||||
* sqlQuery.setParameter("status", "ACTIVE");
|
||||
*
|
||||
* // execute the query returning a List of MapBean objects
|
||||
* List<SqlRow> list = sqlQuery.findList();
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setParameter("name", "Acme%")
|
||||
* .setParameter("status", "ACTIVE")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -104,7 +100,7 @@ public interface SqlQuery extends Serializable {
|
||||
*
|
||||
* String sql = "select id, name, status from customer order by name desc";
|
||||
*
|
||||
* Ebean.createSqlQuery(sql)
|
||||
* DB.sqlQuery(sql)
|
||||
* .findEachRow((resultSet, rowNum) -> {
|
||||
*
|
||||
* // read directly from ResultSet
|
||||
@@ -134,7 +130,7 @@ public interface SqlQuery extends Serializable {
|
||||
*
|
||||
* String sql = "select max(unit_price) from o_order_detail where order_qty > ?";
|
||||
*
|
||||
* BigDecimal maxPrice = Ebean.createSqlQuery(sql)
|
||||
* BigDecimal maxPrice = DB.sqlQuery(sql)
|
||||
* .setParameter(1, 2)
|
||||
* .findSingleAttribute(BigDecimal.class);
|
||||
*
|
||||
@@ -176,9 +172,10 @@ public interface SqlQuery extends Serializable {
|
||||
* " order by (unit_price * order_qty) desc";
|
||||
*
|
||||
* //
|
||||
* List<BigDecimal> lineAmounts = Ebean.createSqlQuery(sql)
|
||||
* .setParameter(1, 3)
|
||||
* .findSingleAttributeList(BigDecimal.class);
|
||||
* List<BigDecimal> lineAmounts =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setParameter(1, 3)
|
||||
* .findSingleAttributeList(BigDecimal.class);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
@@ -195,6 +192,33 @@ public interface SqlQuery extends Serializable {
|
||||
*/
|
||||
SqlQuery setParameter(String name, Object value);
|
||||
|
||||
/**
|
||||
* Set one of more positioned parameters.
|
||||
* <p>
|
||||
* This is a convenient alternative to multiple calls setParameter().
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select id, name from customer where name like ? and status = ?";
|
||||
*
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setParams("Rob", Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
*
|
||||
* // is the same as ...
|
||||
*
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setParameter(1, "Rob")
|
||||
* .setParameter(2, "Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SqlQuery setParams(Object... values);
|
||||
|
||||
/**
|
||||
* The same as bind for positioned parameters.
|
||||
*/
|
||||
|
||||
@@ -16,20 +16,33 @@ package io.ebean;
|
||||
* notify Ebean of external changes and enable Ebean to maintain it's "L2"
|
||||
* server cache.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example that uses 'named' parameters
|
||||
* // example using 'positioned' parameters
|
||||
*
|
||||
* String s = "UPDATE f_topic set post_count = :count where id = :id";
|
||||
* String sql = "insert into audit_log (group, title, description) values (?, ?, ?);
|
||||
*
|
||||
* SqlUpdate update = Ebean.createSqlUpdate(s);
|
||||
* update.setParameter("id", 1);
|
||||
* update.setParameter("count", 50);
|
||||
* int rows =
|
||||
* DB.sqlUpdate(sql)
|
||||
* .setParams("login", "new user", "user rob was created")
|
||||
* .executeNow();
|
||||
*
|
||||
* int modifiedCount = update.execute();
|
||||
* }</pre>
|
||||
*
|
||||
* String msg = "There were " + modifiedCount + " rows updated";
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example using 'named' parameters
|
||||
*
|
||||
* String sql = "update topic set post_count = :count where id = :id";
|
||||
*
|
||||
* int rows =
|
||||
* DB.sqlUpdate(sql)
|
||||
* .setParameter("id", 1)
|
||||
* .setParameter("count", 50)
|
||||
* .execute();
|
||||
*
|
||||
* String msg = "There were " + rows + " rows updated";
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -37,9 +50,10 @@ package io.ebean;
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
|
||||
* SqlUpdate insert = Ebean.createSqlUpdate(sql);
|
||||
*
|
||||
* try (Transaction txn = Ebean.beginTransaction()) {
|
||||
* SqlUpdate insert = DB.sqlUpdate(sql);
|
||||
*
|
||||
* try (Transaction txn = DB.beginTransaction()) {
|
||||
* txn.setBatchMode(true);
|
||||
*
|
||||
* insert.setNextParameter(10000);
|
||||
@@ -65,7 +79,7 @@ package io.ebean;
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction txn = Ebean.beginTransaction()) {
|
||||
* try (Transaction txn = DB.beginTransaction()) {
|
||||
*
|
||||
* insert.setNextParameter(10000);
|
||||
* insert.setNextParameter("hello");
|
||||
@@ -217,6 +231,33 @@ public interface SqlUpdate {
|
||||
*/
|
||||
SqlUpdate setTimeout(int secs);
|
||||
|
||||
/**
|
||||
* Set one of more positioned parameters.
|
||||
* <p>
|
||||
* This is a convenient alternative to multiple setParameter() calls.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "insert into audit_log (id, name, version) values (?,?,?)";
|
||||
*
|
||||
* DB.sqlUpdate(sql)
|
||||
* .setParams(UUID.randomUUID(), "Hello", 1)
|
||||
* .executeNow();
|
||||
*
|
||||
*
|
||||
* // is the same as ...
|
||||
*
|
||||
* DB.sqlUpdate(sql)
|
||||
* .setParameter(1, UUID.randomUUID())
|
||||
* .setParameter(2, "Hello")
|
||||
* .setParameter(3, 1)
|
||||
* .executeNow();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*/
|
||||
SqlUpdate setParams(Object... values);
|
||||
|
||||
/**
|
||||
* Set the next positioned parameter.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.DatabaseFactory;
|
||||
|
||||
/**
|
||||
* The configuration used for creating a Database.
|
||||
* <p>
|
||||
* Used to programmatically construct an Database and optionally register it
|
||||
* with the DB singleton.
|
||||
* </p>
|
||||
* <p>
|
||||
* If you just use DB thout this programmatic configuration Ebean will read
|
||||
* the application.properties file and take the configuration from there. This usually
|
||||
* includes searching the class path and automatically registering any entity
|
||||
* classes and listeners etc.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* DatabaseConfig config = new DatabaseConfig();
|
||||
*
|
||||
* // read the ebean.properties and load
|
||||
* // those settings into this serverConfig object
|
||||
* config.loadFromProperties();
|
||||
*
|
||||
* // explicitly register the entity beans to avoid classpath scanning
|
||||
* config.addClass(Customer.class);
|
||||
* config.addClass(User.class);
|
||||
*
|
||||
* Database db = DatabaseFactory.create(config);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Note that ServerConfigProvider provides a standard Java ServiceLoader mechanism that can
|
||||
* be used to apply configuration to the DatabaseConfig.
|
||||
* </p>
|
||||
*
|
||||
* @author emcgreal
|
||||
* @author rbygrave
|
||||
* @see DatabaseFactory
|
||||
*/
|
||||
public class DatabaseConfig extends ServerConfig {
|
||||
|
||||
}
|
||||
@@ -47,6 +47,11 @@ public class PlatformConfig {
|
||||
*/
|
||||
private DbUuid dbUuid = DbUuid.AUTO_VARCHAR;
|
||||
|
||||
/**
|
||||
* Set to true to force InetAddress to map to Varchar (for Postgres rather than INET)
|
||||
*/
|
||||
private boolean databaseInetAddressVarchar;
|
||||
|
||||
/**
|
||||
* Modify the default mapping of standard types such as default precision for DECIMAL etc.
|
||||
*/
|
||||
@@ -181,6 +186,20 @@ public class PlatformConfig {
|
||||
this.idType = idType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if InetAddress should map to varchar column (rather than Postgres INET).
|
||||
*/
|
||||
public boolean isDatabaseInetAddressVarchar() {
|
||||
return databaseInetAddressVarchar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to force InetAddress to map to varchar column.
|
||||
*/
|
||||
public void setDatabaseInetAddressVarchar(boolean databaseInetAddressVarchar) {
|
||||
this.databaseInetAddressVarchar = databaseInetAddressVarchar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom type mapping.
|
||||
* <p>
|
||||
@@ -235,6 +254,7 @@ public class PlatformConfig {
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar);
|
||||
|
||||
DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null);
|
||||
if (dbUuid != null) {
|
||||
|
||||
@@ -27,6 +27,9 @@ public class DbPlatformTypeMapping {
|
||||
|
||||
private static final DbPlatformType BOOLEAN_LOGICAL = new BooleanLogicalType();
|
||||
|
||||
private static final DbPlatformType INET_NATIVE = new DbPlatformType("inet", false);
|
||||
private static final DbPlatformType INET_VARCHAR = new DbPlatformType("varchar", 50);
|
||||
|
||||
private static final DbPlatformType UUID_NATIVE = new DbPlatformType("uuid", false);
|
||||
@SuppressWarnings("unused")
|
||||
private static final DbPlatformType UUID_PLACEHOLDER = new DbPlatformType("uuidPlaceholder");
|
||||
@@ -106,6 +109,7 @@ public class DbPlatformTypeMapping {
|
||||
put(DbType.JSONBLOB, new DbPlatformType("jsonblob"));
|
||||
put(DbType.JSONVARCHAR, new DbPlatformType("jsonvarchar", 1000));
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
put(DbType.INET, INET_NATIVE);
|
||||
|
||||
} else {
|
||||
put(DbType.VARCHAR, new DbPlatformType("varchar", 255));
|
||||
@@ -121,6 +125,7 @@ public class DbPlatformTypeMapping {
|
||||
put(DbType.JSONVARCHAR, JSON_VARCHAR_PLACEHOLDER);
|
||||
// default to native UUID and override on platform configure()
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
put(DbType.INET, INET_VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ public enum DbType {
|
||||
ARRAY(Types.ARRAY),
|
||||
|
||||
UUID(ExtraDbTypes.UUID),
|
||||
INET(ExtraDbTypes.INET),
|
||||
CDIR(ExtraDbTypes.CDIR),
|
||||
|
||||
POINT(ExtraDbTypes.POINT),
|
||||
POLYGON(ExtraDbTypes.POLYGON),
|
||||
|
||||
@@ -40,6 +40,9 @@ public interface ExtraDbTypes {
|
||||
*/
|
||||
int JSONBlob = 5005;
|
||||
|
||||
int INET = 5020;
|
||||
int CDIR = 5021;
|
||||
|
||||
/**
|
||||
* Geo Point
|
||||
*/
|
||||
|
||||
@@ -60,6 +60,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
DbPlatformType dbBytea = new DbPlatformType("bytea", false);
|
||||
|
||||
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
|
||||
dbTypeMap.put(DbType.INET, new DbPlatformType("inet", false));
|
||||
dbTypeMap.put(DbType.HSTORE, new DbPlatformType("hstore", false));
|
||||
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbPlatformType("jsonb", false));
|
||||
|
||||
@@ -97,6 +97,8 @@ class Loader {
|
||||
if (fileName != null) {
|
||||
loadWithExtensionCheck(fileName);
|
||||
}
|
||||
} else {
|
||||
loadWithExtensionCheck(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,14 @@ public class BindParams implements Serializable {
|
||||
public BindParams() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset positioned parameters (usually due to bind parameter expansion).
|
||||
*/
|
||||
public void reset() {
|
||||
bindHash = null;
|
||||
positionedParameters.clear();
|
||||
}
|
||||
|
||||
public int queryBindHash() {
|
||||
int hc = namedParameters.hashCode();
|
||||
for (Param positionedParameter : positionedParameters) {
|
||||
@@ -171,8 +179,7 @@ public class BindParams implements Serializable {
|
||||
}
|
||||
|
||||
private Param getParam(String name) {
|
||||
Param p = namedParameters.computeIfAbsent(name, k -> new Param());
|
||||
return p;
|
||||
return namedParameters.computeIfAbsent(name, k -> new Param());
|
||||
}
|
||||
|
||||
private Param getParam(int position) {
|
||||
|
||||
@@ -4,6 +4,11 @@ import io.ebean.SqlUpdate;
|
||||
|
||||
public interface SpiSqlUpdate extends SqlUpdate {
|
||||
|
||||
/**
|
||||
* Return the sql taking into account bind parameter expansion.
|
||||
*/
|
||||
String getBaseSql();
|
||||
|
||||
/**
|
||||
* Return the Bind parameters.
|
||||
*/
|
||||
|
||||
@@ -33,12 +33,12 @@ class LastMigration {
|
||||
*/
|
||||
static String lastVersion(File migDirectory, File modelDir) {
|
||||
|
||||
List<String> fileNames = new ArrayList<>();
|
||||
List<MigrationVersion> versions = new ArrayList<>();
|
||||
|
||||
File[] sqlFiles = migDirectory.listFiles(pathname -> includeSqlFile(pathname.getName().toLowerCase()));
|
||||
if (sqlFiles != null) {
|
||||
for (File file : sqlFiles) {
|
||||
fileNames.add(trim(file.getName()));
|
||||
versions.add(trimAndParse(file.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,14 +46,14 @@ class LastMigration {
|
||||
File[] xmlFiles = modelDir.listFiles(pathname -> includeModelFile(pathname.getName().toLowerCase()));
|
||||
if (xmlFiles != null) {
|
||||
for (File file : xmlFiles) {
|
||||
fileNames.add(trim(file.getName()));
|
||||
versions.add(trimAndParse(file.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collections.sort(fileNames);
|
||||
if (!fileNames.isEmpty()) {
|
||||
return fileNames.get(fileNames.size() - 1);
|
||||
Collections.sort(versions);
|
||||
if (!versions.isEmpty()) {
|
||||
return versions.get(versions.size() - 1).asString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -69,23 +69,14 @@ class LastMigration {
|
||||
return lowerFileName.endsWith(MODEL_XML);
|
||||
}
|
||||
|
||||
private static String trim(String name) {
|
||||
name = name.toLowerCase();
|
||||
char c = name.charAt(0);
|
||||
if (c == 'v') {
|
||||
name = name.substring(1);
|
||||
}
|
||||
int p = name.indexOf("__");
|
||||
if (p > -1) {
|
||||
name = name.substring(0, p);
|
||||
}
|
||||
private static MigrationVersion trimAndParse(String name) {
|
||||
if (name.endsWith(SQL)) {
|
||||
name = name.substring(0, name.length() - 4);
|
||||
}
|
||||
if (name.endsWith(MODEL_XML)) {
|
||||
name = name.substring(0, name.length() - 10);
|
||||
}
|
||||
return name;
|
||||
return MigrationVersion.parse(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1083,15 +1083,25 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery createSqlQuery(String sql) {
|
||||
public SqlQuery sqlQuery(String sql) {
|
||||
return new DefaultRelationalQuery(this, sql.trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate createSqlUpdate(String sql) {
|
||||
public SqlQuery createSqlQuery(String sql) {
|
||||
return sqlQuery(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate sqlUpdate(String sql) {
|
||||
return new DefaultSqlUpdate(this, sql.trim());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate createSqlUpdate(String sql) {
|
||||
return sqlUpdate(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallableSql createCallableSql(String sql) {
|
||||
return new DefaultCallableSql(this, sql.trim());
|
||||
|
||||
@@ -9,6 +9,7 @@ import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A SQL Update Delete or Insert statement that can be executed. For the times
|
||||
@@ -35,9 +36,14 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
|
||||
private final BindParams bindParams;
|
||||
|
||||
/**
|
||||
* The sql update or delete statement.
|
||||
* The original sql update or delete statement.
|
||||
*/
|
||||
private final String sql;
|
||||
private final String origSql;
|
||||
|
||||
/**
|
||||
* The sql taking into account bind parameter expansion.
|
||||
*/
|
||||
private String baseSql;
|
||||
|
||||
/**
|
||||
* The actual sql with named parameters converted.
|
||||
@@ -66,6 +72,8 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
|
||||
*/
|
||||
private int addPos;
|
||||
|
||||
private int bindExpansion;
|
||||
|
||||
private boolean getGeneratedKeys;
|
||||
|
||||
private Object generatedKey;
|
||||
@@ -89,7 +97,8 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
|
||||
*/
|
||||
public DefaultSqlUpdate(SpiEbeanServer server, String sql, BindParams bindParams) {
|
||||
this.server = server;
|
||||
this.sql = sql;
|
||||
this.origSql = sql;
|
||||
this.baseSql = sql;
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@@ -221,11 +230,21 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
|
||||
@Override
|
||||
public void setGeneratedSql(String generatedSql) {
|
||||
this.generatedSql = generatedSql;
|
||||
this.baseSql = origSql;
|
||||
if (bindExpansion > 0) {
|
||||
bindParams.reset();
|
||||
bindExpansion = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return sql;
|
||||
return origSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBaseSql() {
|
||||
return baseSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -239,27 +258,61 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate setParams(Object... values) {
|
||||
for (Object value : values) {
|
||||
setParameter(++addPos, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate setNextParameter(Object value) {
|
||||
setParameter(++addPos, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
private SqlUpdate setParamWithBindExpansion(int position, Collection values, String bindLiteral) {
|
||||
|
||||
StringBuilder sqlExpand = new StringBuilder(values.size() * 2);
|
||||
position = position + bindExpansion;
|
||||
int offset = 0;
|
||||
for (Object val : values) {
|
||||
if (offset > 0) {
|
||||
sqlExpand.append(",");
|
||||
}
|
||||
sqlExpand.append("?");
|
||||
bindParams.setParameter(position + offset++, val);
|
||||
}
|
||||
bindExpansion += (offset - 1);
|
||||
baseSql = baseSql.replace(bindLiteral, sqlExpand.toString());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate setParameter(int position, Object value) {
|
||||
bindParams.setParameter(position, value);
|
||||
|
||||
if (value instanceof Collection) {
|
||||
String bindLiteral = "?" + position;
|
||||
int pos = baseSql.indexOf(bindLiteral);
|
||||
if (pos > -1) {
|
||||
return setParamWithBindExpansion(position, (Collection) value, bindLiteral);
|
||||
}
|
||||
}
|
||||
|
||||
bindParams.setParameter(bindExpansion + position, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate setNull(int position, int jdbcType) {
|
||||
bindParams.setNullParameter(position, jdbcType);
|
||||
bindParams.setNullParameter(bindExpansion + position, jdbcType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate setNullParameter(int position, int jdbcType) {
|
||||
bindParams.setNullParameter(position, jdbcType);
|
||||
bindParams.setNullParameter(bindExpansion + position, jdbcType);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import io.ebeaninternal.server.persist.BatchedSqlException;
|
||||
import io.ebeaninternal.server.persist.DeleteMode;
|
||||
import io.ebeaninternal.server.persist.Flags;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
import io.ebeaninternal.server.persist.SaveManyBeans;
|
||||
import io.ebeaninternal.server.transaction.BeanPersistIdMap;
|
||||
import io.ebeanservice.docstore.api.DocStoreUpdate;
|
||||
import io.ebeanservice.docstore.api.DocStoreUpdateContext;
|
||||
@@ -174,7 +175,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
private int pendingPostUpdateNotify;
|
||||
|
||||
/**
|
||||
* Set to true when post execute has occured (so includes batch flush).
|
||||
* Set to true when post execute has occurred (so includes batch flush).
|
||||
*/
|
||||
private boolean postExecute;
|
||||
|
||||
@@ -183,6 +184,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
private boolean complete;
|
||||
|
||||
/**
|
||||
* Many to many intersection table changes that are held for later batch processing.
|
||||
*/
|
||||
private List<SaveManyBeans> saveManyIntersections;
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type, int flags) {
|
||||
|
||||
@@ -955,6 +961,13 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
if (isLogSummary()) {
|
||||
logSummary();
|
||||
}
|
||||
saveQueuedManyIntersection();
|
||||
}
|
||||
|
||||
private void saveQueuedManyIntersection() {
|
||||
if (saveManyIntersections != null) {
|
||||
saveManyIntersections.forEach(SaveManyBeans::saveIntersectionBatch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1119,6 +1132,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
updatedManysOnly = true;
|
||||
setNotifyCache();
|
||||
addPostCommitListeners();
|
||||
saveQueuedManyIntersection();
|
||||
}
|
||||
notifyCacheOnComplete();
|
||||
postUpdateNotify();
|
||||
@@ -1454,4 +1468,21 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
public String getSelectLastInsertedId() {
|
||||
return beanDescriptor.getSelectLastInsertedId(publish);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the intersection table updates should be queued and batched.
|
||||
*/
|
||||
public boolean isQueueManyIntersection() {
|
||||
return !postExecute;
|
||||
}
|
||||
|
||||
/**
|
||||
* The intersection table updates to the batch executed later on postExecute.
|
||||
*/
|
||||
public void addManyIntersection(SaveManyBeans saveManyIntersection) {
|
||||
if (this.saveManyIntersections == null) {
|
||||
this.saveManyIntersections = new ArrayList<>();
|
||||
}
|
||||
this.saveManyIntersections.add(saveManyIntersection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.lib.util.Str;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
|
||||
/**
|
||||
* Persist request specifically for CallableSql.
|
||||
@@ -24,12 +27,12 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
|
||||
private String tableName;
|
||||
|
||||
private String description;
|
||||
|
||||
private boolean addBatch;
|
||||
|
||||
private boolean forceNoBatch;
|
||||
|
||||
private boolean batchThisRequest;
|
||||
|
||||
public PersistRequestUpdateSql(SpiEbeanServer server, SpiSqlUpdate sqlUpdate,
|
||||
SpiTransaction t, PersistExecute persistExecute, boolean forceNoBatch) {
|
||||
|
||||
@@ -58,6 +61,25 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
return executeOrQueue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute using jdbc batch.
|
||||
*/
|
||||
public void executeAddBatch() {
|
||||
this.addBatch = true;
|
||||
persistExecute.executeSqlUpdate(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this request to BatchControl to flush later.
|
||||
*/
|
||||
public void addToFlushQueue(boolean early) {
|
||||
BatchControl control = transaction.getBatchControl();
|
||||
if (control == null) {
|
||||
control = persistExecute.createBatchControl(transaction);
|
||||
}
|
||||
control.addToFlushQueue(this, early);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeNow() {
|
||||
return persistExecute.executeSqlUpdate(this);
|
||||
@@ -104,10 +126,9 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
* Specify the type of statement executed. Used to automatically register
|
||||
* with the transaction event.
|
||||
*/
|
||||
public void setType(SqlType sqlType, String tableName, String description) {
|
||||
public void setType(SqlType sqlType, String tableName) {
|
||||
this.sqlType = sqlType;
|
||||
this.tableName = tableName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,6 +138,20 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
this.bindLog = bindLog;
|
||||
}
|
||||
|
||||
public void startBind(boolean batchThisRequest) {
|
||||
this.batchThisRequest = batchThisRequest;
|
||||
super.startBind(batchThisRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log the sql bind used with jdbc batch.
|
||||
*/
|
||||
public void logSqlBatchBind() {
|
||||
if (transaction.isLogSql()) {
|
||||
transaction.logSql(Str.add(" -- bind(", bindLog, ")"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform post execute processing.
|
||||
*/
|
||||
@@ -125,9 +160,8 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
if (startNanos > 0) {
|
||||
persistExecute.collectSqlUpdate(label, startNanos, rowCount);
|
||||
}
|
||||
if (transaction.isLogSummary()) {
|
||||
String m = description + " table[" + tableName + "] rows[" + rowCount + "] bind[" + bindLog + "]";
|
||||
transaction.logSummary(m);
|
||||
if (transaction.isLogSql() && !batchThisRequest) {
|
||||
transaction.logSql(Str.add(TrimLogSql.trim(updateSql.getGeneratedSql()), "; -- bind(", bindLog, ") rows(", String.valueOf(rowCount), ")"));
|
||||
}
|
||||
|
||||
if (updateSql.isAutoTableMod()) {
|
||||
|
||||
@@ -103,6 +103,11 @@ public interface Persister {
|
||||
*/
|
||||
void visitMetrics(MetricVisitor visitor);
|
||||
|
||||
/**
|
||||
* Execute or queue the update.
|
||||
*/
|
||||
void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue);
|
||||
|
||||
/**
|
||||
* Add the statement to JDBC batch for later execution via executeBatch.
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.expression.DefaultExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.IdInExpression;
|
||||
@@ -45,7 +45,7 @@ public class IntersectionRow {
|
||||
values.put(key, value);
|
||||
}
|
||||
|
||||
public SqlUpdate createInsert(SpiEbeanServer server) {
|
||||
public SpiSqlUpdate createInsert(SpiEbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
@@ -73,7 +73,7 @@ public class IntersectionRow {
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDelete(SpiEbeanServer server, DeleteMode deleteMode) {
|
||||
public SpiSqlUpdate createDelete(SpiEbeanServer server, DeleteMode deleteMode) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
@@ -108,7 +108,7 @@ public class IntersectionRow {
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDeleteChildren(SpiEbeanServer server) {
|
||||
public SpiSqlUpdate createDeleteChildren(SpiEbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ public abstract class AnnotationParser extends AnnotationBase {
|
||||
} else {
|
||||
prop.setId();
|
||||
if (prop.getPropertyType().equals(UUID.class)) {
|
||||
if (descriptor.getIdGeneratorName() == null) {
|
||||
if (readConfig.isIdGeneratorAutomatic() && descriptor.getIdGeneratorName() == null) {
|
||||
descriptor.setUuidGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ class ReadAnnotationConfig {
|
||||
private final boolean eagerFetchLobs;
|
||||
private final boolean javaxValidationAnnotations;
|
||||
private final boolean jacksonAnnotations;
|
||||
private final boolean idGeneratorAutomatic;
|
||||
|
||||
ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, ServerConfig serverConfig) {
|
||||
|
||||
@@ -23,6 +24,7 @@ class ReadAnnotationConfig {
|
||||
this.versionsBetweenSuffix = versionsBetweenSuffix;
|
||||
this.disableL2Cache = serverConfig.isDisableL2Cache();
|
||||
this.eagerFetchLobs = serverConfig.isEagerFetchLobs();
|
||||
this.idGeneratorAutomatic = serverConfig.isIdGeneratorAutomatic();
|
||||
|
||||
this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent();
|
||||
this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent();
|
||||
@@ -48,6 +50,10 @@ class ReadAnnotationConfig {
|
||||
return eagerFetchLobs;
|
||||
}
|
||||
|
||||
public boolean isIdGeneratorAutomatic() {
|
||||
return idGeneratorAutomatic;
|
||||
}
|
||||
|
||||
boolean isJavaxValidationAnnotations() {
|
||||
return javaxValidationAnnotations;
|
||||
}
|
||||
|
||||
@@ -162,6 +162,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new SimpleExpression(propertyName, Op.EQ, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression eqOrNull(String propertyName, Object value) {
|
||||
return or(eq(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -221,6 +226,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new InRangeExpression(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression inRangeWith(String lowProperty, String highProperty, Object value) {
|
||||
return and(le(lowProperty, value), gtOrNull(highProperty, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
@@ -245,6 +255,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new SimpleExpression(propertyName, Op.GT, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than or null - property greater than the given value or null.
|
||||
*/
|
||||
@Override
|
||||
public Expression gtOrNull(String propertyName, Object value) {
|
||||
return or(gt(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
@@ -254,6 +272,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new SimpleExpression(propertyName, Op.GT_EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than or null - property less than the given value or null.
|
||||
*/
|
||||
@Override
|
||||
public Expression ltOrNull(String propertyName, Object value) {
|
||||
return or(lt(propertyName, value), isNull(propertyName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
@@ -429,6 +455,16 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new InExpression(propertyName, values, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* In where null or empty values means that no predicate is added to the query.
|
||||
* <p>
|
||||
* That is, only add the IN predicate if the values are not null or empty.
|
||||
*/
|
||||
@Override
|
||||
public Expression inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return new InExpression(propertyName, values, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
@@ -529,7 +565,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression raw(String raw, Object value) {
|
||||
return new RawExpression(raw, new Object[]{value});
|
||||
return RawExpressionBuilder.buildSingle(raw, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,7 +577,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression raw(String raw, Object[] values) {
|
||||
return new RawExpression(raw, values);
|
||||
return RawExpressionBuilder.build(raw, values);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -764,6 +764,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqOrNull(String propertyName, Object value) {
|
||||
add(expr.eqOrNull(propertyName, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ieq(String propertyName, String value) {
|
||||
add(expr.ieq(propertyName, value));
|
||||
@@ -794,6 +800,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value) {
|
||||
add(expr.inRangeWith(lowProperty, highProperty, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
|
||||
add(expr.inRange(propertyName, value1, value2));
|
||||
@@ -836,6 +848,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtOrNull(String propertyName, Object value) {
|
||||
add(expr.gtOrNull(propertyName, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> icontains(String propertyName, String value) {
|
||||
add(expr.icontains(propertyName, value));
|
||||
@@ -894,6 +912,14 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values) {
|
||||
if (notEmpty(values)) {
|
||||
add(expr.in(propertyName, values));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> in(String propertyName, Object... values) {
|
||||
add(expr.in(propertyName, values));
|
||||
@@ -990,6 +1016,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltOrNull(String propertyName, Object value) {
|
||||
add(expr.ltOrNull(propertyName, value));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> not(Expression exp) {
|
||||
add(expr.not(exp));
|
||||
@@ -1044,6 +1076,18 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> rawOrEmpty(String raw, Collection<Object> values) {
|
||||
if (notEmpty(values)) {
|
||||
add(expr.raw(raw, values));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private boolean notEmpty(Collection<?> values) {
|
||||
return values != null && !values.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> startsWith(String propertyName, String value) {
|
||||
add(expr.startsWith(propertyName, value));
|
||||
|
||||
@@ -17,8 +17,16 @@ import java.util.List;
|
||||
|
||||
class InExpression extends AbstractExpression {
|
||||
|
||||
private static final String SQL_TRUE = "1=1";
|
||||
private static final String SQL_FALSE = "1=0";
|
||||
|
||||
private final boolean not;
|
||||
|
||||
/**
|
||||
* Set to true when adding "1=1" predicate (due to null or empty sourceValues).
|
||||
*/
|
||||
private final boolean empty;
|
||||
|
||||
private final Collection<?> sourceValues;
|
||||
|
||||
private List<Object> bindValues;
|
||||
@@ -26,18 +34,27 @@ class InExpression extends AbstractExpression {
|
||||
private boolean multiValueSupported;
|
||||
|
||||
InExpression(String propertyName, Collection<?> sourceValues, boolean not) {
|
||||
this(propertyName, sourceValues, not, false);
|
||||
}
|
||||
|
||||
InExpression(String propertyName, Collection<?> sourceValues, boolean not, boolean orEmpty) {
|
||||
super(propertyName);
|
||||
this.sourceValues = sourceValues;
|
||||
this.not = not;
|
||||
this.empty = orEmpty && (sourceValues == null || sourceValues.isEmpty());
|
||||
}
|
||||
|
||||
InExpression(String propertyName, Object[] array, boolean not) {
|
||||
super(propertyName);
|
||||
this.sourceValues = Arrays.asList(array);
|
||||
this.not = not;
|
||||
this.empty = false;
|
||||
}
|
||||
|
||||
private List<Object> values() {
|
||||
if (empty || sourceValues == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<Object> vals = new ArrayList<>(sourceValues.size());
|
||||
for (Object sourceValue : sourceValues) {
|
||||
assert sourceValue != null : "null is not allowed in in-queries";
|
||||
@@ -48,8 +65,8 @@ class InExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public boolean naturalKey(NaturalKeyQueryData<?> data) {
|
||||
// can't use naturalKey cache for NOT IN
|
||||
if (not) {
|
||||
// can't use naturalKey cache for NOT IN or when "empty"
|
||||
if (not || empty) {
|
||||
return false;
|
||||
}
|
||||
List<Object> copy = data.matchIn(propName, bindValues);
|
||||
@@ -70,11 +87,16 @@ class InExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.writeIn(propName, values().toArray(), not);
|
||||
if (!empty) {
|
||||
context.writeIn(propName, values().toArray(), not);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
for (Object value : bindValues) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException("null values in 'in(...)' queries must be handled separately!");
|
||||
@@ -108,10 +130,12 @@ class InExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
if (empty) {
|
||||
request.append(SQL_TRUE);
|
||||
return;
|
||||
}
|
||||
if (bindValues.isEmpty()) {
|
||||
String expr = not ? "1=1" : "1=0";
|
||||
request.append(expr);
|
||||
request.append(not ? SQL_TRUE : SQL_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -142,10 +166,14 @@ class InExpression extends AbstractExpression {
|
||||
builder.append("In[");
|
||||
}
|
||||
builder.append(propName);
|
||||
builder.append(" ?");
|
||||
if (!multiValueSupported) {
|
||||
// query plan specific to the number of parameters in the IN clause
|
||||
builder.append(bindValues.size());
|
||||
if (empty) {
|
||||
builder.append("empty");
|
||||
} else {
|
||||
builder.append(" ?");
|
||||
if (!multiValueSupported) {
|
||||
// query plan specific to the number of parameters in the IN clause
|
||||
builder.append(bindValues.size());
|
||||
}
|
||||
}
|
||||
builder.append("]");
|
||||
}
|
||||
|
||||
@@ -280,6 +280,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.and(expOne, expTwo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value) {
|
||||
return exprList.inRangeWith(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
|
||||
return exprList.inRange(propertyName, value1, value2);
|
||||
@@ -310,6 +315,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.eq(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqOrNull(String propertyName, Object value) {
|
||||
return exprList.eqOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> exampleLike(Object example) {
|
||||
return exprList.exampleLike(example);
|
||||
@@ -597,6 +607,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.gt(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtOrNull(String propertyName, Object value) {
|
||||
return exprList.gtOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> having() {
|
||||
throw new IllegalStateException("having() not allowed on Junction expression list");
|
||||
@@ -657,6 +672,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.in(propertyName, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return exprList.inOrEmpty(propertyName, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> in(String propertyName, Object... values) {
|
||||
return exprList.in(propertyName, values);
|
||||
@@ -732,6 +752,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.lt(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltOrNull(String propertyName, Object value) {
|
||||
return exprList.ltOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Object value) {
|
||||
return exprList.ne(propertyName, value);
|
||||
@@ -782,6 +807,11 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.raw(raw, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> rawOrEmpty(String raw, Collection<Object> values) {
|
||||
return exprList.rawOrEmpty(raw, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> raw(String raw) {
|
||||
return exprList.raw(raw);
|
||||
|
||||
@@ -12,9 +12,9 @@ import java.util.Collection;
|
||||
|
||||
class RawExpression extends NonPrepareExpression {
|
||||
|
||||
private final String sql;
|
||||
final String sql;
|
||||
|
||||
private final Object[] values;
|
||||
final Object[] values;
|
||||
|
||||
RawExpression(String sql, Object[] values) {
|
||||
this.sql = sql;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
class RawExpressionBuilder {
|
||||
|
||||
private static final String BP_1 = "?1";
|
||||
|
||||
private static final String[] BP = {BP_1, "?2", "?3", "?4", "?5", "?6", "?7", "?8",
|
||||
"?9", "?10", "?11", "?12", "?13", "?14", "?15", "?16", "?17", "?18", "?19", "?20"};
|
||||
|
||||
/**
|
||||
* Build RawExpression taking into account parameter expansion.
|
||||
*/
|
||||
static RawExpression buildSingle(String raw, Object value) {
|
||||
if (isExpand(value, raw, BP_1)) {
|
||||
Collection val = (Collection) value;
|
||||
raw = raw.replace(BP_1, expand(val));
|
||||
return new RawExpression(raw, val.toArray());
|
||||
}
|
||||
return new RawExpression(raw, new Object[]{value});
|
||||
}
|
||||
|
||||
/**
|
||||
* Build RawExpression for multiple bind values taking into account parameter expansion.
|
||||
*/
|
||||
static RawExpression build(String raw, Object[] values) {
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (isExpand(values[i], raw, match(i))) {
|
||||
return new RawExpressionBuilder(raw, values).build();
|
||||
}
|
||||
}
|
||||
return new RawExpression(raw, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this value is a collection that should be expanded.
|
||||
*/
|
||||
private static boolean isExpand(Object value, String raw, String bindMatch) {
|
||||
return value instanceof Collection && raw.contains(bindMatch);
|
||||
}
|
||||
|
||||
private static String match(int i) {
|
||||
if (i < 20) {
|
||||
return BP[i];
|
||||
}
|
||||
return "?" + (i + 1);
|
||||
}
|
||||
|
||||
private static String expand(Collection values) {
|
||||
|
||||
StringBuilder sqlExpand = new StringBuilder(values.size() * 2);
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
if (i > 0) {
|
||||
sqlExpand.append(",");
|
||||
}
|
||||
sqlExpand.append("?");
|
||||
}
|
||||
return sqlExpand.toString();
|
||||
}
|
||||
|
||||
private final String expanded;
|
||||
|
||||
private final List<Object> params = new ArrayList<>();
|
||||
|
||||
private RawExpressionBuilder(String raw, Object[] values) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
String match = match(i);
|
||||
if (!isExpand(values[i], raw, match)) {
|
||||
params.add(values[i]);
|
||||
} else {
|
||||
Collection val = (Collection) values[i];
|
||||
params.addAll(val);
|
||||
raw = raw.replace(match, expand(val));
|
||||
}
|
||||
}
|
||||
this.expanded = raw;
|
||||
}
|
||||
|
||||
private RawExpression build() {
|
||||
return new RawExpression(expanded, params.toArray());
|
||||
}
|
||||
}
|
||||
@@ -15,14 +15,16 @@ public class Str {
|
||||
// determine a decent buffer size
|
||||
int len = 16 + s0.length() + s1.length();
|
||||
for (String arg1 : args) {
|
||||
len += arg1.length();
|
||||
len += (arg1 == null) ? 0 : arg1.length();
|
||||
}
|
||||
|
||||
// append all the strings into the buffer
|
||||
StringBuilder sb = new StringBuilder(len);
|
||||
sb.append(s0).append(s1);
|
||||
for (String arg : args) {
|
||||
sb.append(arg);
|
||||
if (arg != null) {
|
||||
sb.append(arg);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.persist;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.core.PersistRequest;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.core.PersistRequestUpdateSql;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
|
||||
@@ -10,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controls the batch ordering of persist requests.
|
||||
@@ -67,6 +69,10 @@ public final class BatchControl {
|
||||
* Size of the largest buffer.
|
||||
*/
|
||||
private int bufferMax;
|
||||
private int topCounter;
|
||||
|
||||
private Queue earlyQueue;
|
||||
private Queue lateQueue;
|
||||
|
||||
/**
|
||||
* Create for a given transaction, PersistExecute, default size and getGeneratedKeys.
|
||||
@@ -224,14 +230,14 @@ public final class BatchControl {
|
||||
* Flush without resetting the topOrder (maintains the depth info).
|
||||
*/
|
||||
public void flush() throws BatchedSqlException {
|
||||
flush(false);
|
||||
flushBuffer(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush with a reset the topOrder (fully empty the batch).
|
||||
*/
|
||||
public void flushReset() throws BatchedSqlException {
|
||||
flush(true);
|
||||
flushBuffer(true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,12 +247,25 @@ public final class BatchControl {
|
||||
pstmtHolder.clear();
|
||||
beanHoldMap.clear();
|
||||
maxDepth = 0;
|
||||
topCounter = 0;
|
||||
}
|
||||
|
||||
private void flushBuffer(boolean resetTop) throws BatchedSqlException {
|
||||
flushInternal(resetTop);
|
||||
flushQueue(earlyQueue);
|
||||
flushQueue(lateQueue);
|
||||
}
|
||||
|
||||
private void flushQueue(Queue queue) throws BatchedSqlException {
|
||||
if (queue != null && queue.flush() && !pstmtHolder.isEmpty()) {
|
||||
flushPstmtHolder();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* execute all the requests currently queued or batched.
|
||||
*/
|
||||
private void flush(boolean resetTop) throws BatchedSqlException {
|
||||
private void flushInternal(boolean resetTop) throws BatchedSqlException {
|
||||
|
||||
try {
|
||||
bufferMax = 0;
|
||||
@@ -302,10 +321,8 @@ public final class BatchControl {
|
||||
if (maybe != -1) {
|
||||
beanDepth = maybe;
|
||||
} else {
|
||||
// we can't be certain of the relative ordering for this type so
|
||||
// flush and reset the batch as we are changing the type of our top level
|
||||
// bean so just keep it simple and flush and reset the top
|
||||
flushReset();
|
||||
// additional "top level" bean type ordered by save() order
|
||||
beanDepth += ++topCounter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,4 +384,43 @@ public final class BatchControl {
|
||||
public int[] execute(String key, boolean getGeneratedKeys) throws SQLException {
|
||||
return pstmtHolder.execute(key, getGeneratedKeys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a SqlUpdate request to execute after flush.
|
||||
*/
|
||||
public void addToFlushQueue(PersistRequestUpdateSql request, boolean early) {
|
||||
if (early) {
|
||||
// add it to the early queue
|
||||
if (earlyQueue == null) {
|
||||
earlyQueue = new Queue();
|
||||
}
|
||||
earlyQueue.add(request);
|
||||
} else {
|
||||
// add it to the late queue
|
||||
if (lateQueue == null) {
|
||||
lateQueue = new Queue();
|
||||
}
|
||||
lateQueue.add(request);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Queue {
|
||||
|
||||
private final List<PersistRequestUpdateSql> queue = new ArrayList<>();
|
||||
|
||||
boolean flush() {
|
||||
if (queue.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
for (PersistRequestUpdateSql request : queue) {
|
||||
request.executeAddBatch();
|
||||
}
|
||||
queue.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void add(PersistRequestUpdateSql request) {
|
||||
queue.add(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.persist.platform.MultiValueBind;
|
||||
import io.ebeaninternal.server.type.DataBind;
|
||||
import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.PostgresHelper;
|
||||
import io.ebeaninternal.server.type.RsetDataReader;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import io.ebeaninternal.server.type.TypeManager;
|
||||
@@ -374,6 +375,11 @@ public class Binder {
|
||||
b.setObject(data);
|
||||
break;
|
||||
|
||||
case DbPlatformType.INET:
|
||||
// data is always a String at this point
|
||||
b.setObject(PostgresHelper.asInet(data.toString()));
|
||||
break;
|
||||
|
||||
case java.sql.Types.OTHER:
|
||||
b.setObject(data, dataType);
|
||||
break;
|
||||
|
||||
@@ -141,12 +141,24 @@ public final class DefaultPersister implements Persister {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeOrQueue(SpiSqlUpdate update, SpiTransaction t, boolean queue) {
|
||||
if (queue) {
|
||||
addToFlushQueue(update, t, false);
|
||||
} else {
|
||||
executeSqlUpdate(update, t);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToFlushQueue(SpiSqlUpdate update, SpiTransaction t, boolean early) {
|
||||
new PersistRequestUpdateSql(server, update, t, persistExecute).addToFlushQueue(early);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the updateSql.
|
||||
*/
|
||||
@Override
|
||||
public int executeSqlUpdate(SqlUpdate updSql, Transaction t) {
|
||||
|
||||
return executeOrQueue(new PersistRequestUpdateSql(server, (SpiSqlUpdate) updSql, (SpiTransaction) t, persistExecute));
|
||||
}
|
||||
|
||||
@@ -958,12 +970,19 @@ public final class DefaultPersister implements Persister {
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAssocManyIntersection(EntityBean bean, BeanPropertyAssocMany<?> many, Transaction t, boolean publish) {
|
||||
void deleteManyIntersection(EntityBean bean, BeanPropertyAssocMany<?> many, SpiTransaction t, boolean publish, boolean queue) {
|
||||
|
||||
// delete all intersection rows for this bean
|
||||
SpiSqlUpdate sqlDelete = deleteAllIntersection(bean, many, publish);
|
||||
if (queue) {
|
||||
addToFlushQueue(sqlDelete, t, true);
|
||||
} else {
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
}
|
||||
}
|
||||
|
||||
private SpiSqlUpdate deleteAllIntersection(EntityBean bean, BeanPropertyAssocMany<?> many, boolean publish) {
|
||||
IntersectionRow intRow = many.buildManyToManyDeleteChildren(bean, publish);
|
||||
SqlUpdate sqlDelete = intRow.createDeleteChildren(server);
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
return intRow.createDeleteChildren(server);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1012,7 +1031,7 @@ public final class DefaultPersister implements Persister {
|
||||
if (many.hasJoinTable()) {
|
||||
if (deleteMode.isHard()) {
|
||||
// delete associated rows from intersection table (but not during soft delete)
|
||||
deleteAssocManyIntersection(parentBean, many, t, request.isPublish());
|
||||
deleteManyIntersection(parentBean, many, t, request.isPublish(), false);
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
@@ -87,23 +87,16 @@ class ExeUpdateSql {
|
||||
SpiSqlUpdate updateSql = request.getUpdateSql();
|
||||
SpiTransaction t = request.getTransaction();
|
||||
|
||||
String sql = updateSql.getSql();
|
||||
|
||||
BindParams bindParams = updateSql.getBindParams();
|
||||
|
||||
// process named parameters if required
|
||||
String sql = updateSql.getBaseSql();
|
||||
sql = BindParamsParser.parse(bindParams, sql);
|
||||
updateSql.setGeneratedSql(sql);
|
||||
|
||||
boolean logSql = request.isLogSql();
|
||||
|
||||
PreparedStatement pstmt;
|
||||
if (batchThisRequest) {
|
||||
pstmt = pstmtFactory.getPstmt(t, logSql, sql, request);
|
||||
pstmt = pstmtFactory.getPstmt(t, request.isLogSql(), sql, request);
|
||||
} else {
|
||||
if (logSql) {
|
||||
t.logSql(TrimLogSql.trim(sql));
|
||||
}
|
||||
pstmt = pstmtFactory.getPstmt(t, sql, request.isGetGeneratedKeys());
|
||||
}
|
||||
|
||||
@@ -117,9 +110,13 @@ class ExeUpdateSql {
|
||||
}
|
||||
|
||||
request.setBindLog(bindLog);
|
||||
updateSql.setGeneratedSql(sql);
|
||||
|
||||
// derive the statement type (for TransactionEvent)
|
||||
parseUpdate(sql, request);
|
||||
if (batchThisRequest) {
|
||||
request.logSqlBatchBind();
|
||||
}
|
||||
return pstmt;
|
||||
}
|
||||
|
||||
@@ -127,16 +124,16 @@ class ExeUpdateSql {
|
||||
private void determineType(String word1, String word2, String word3, PersistRequestUpdateSql request) {
|
||||
|
||||
if (word1.equalsIgnoreCase("UPDATE")) {
|
||||
request.setType(SqlType.SQL_UPDATE, word2, "UpdateSql");
|
||||
request.setType(SqlType.SQL_UPDATE, word2);
|
||||
|
||||
} else if (word1.equalsIgnoreCase("DELETE")) {
|
||||
request.setType(SqlType.SQL_DELETE, word3, "DeleteSql");
|
||||
request.setType(SqlType.SQL_DELETE, word3);
|
||||
|
||||
} else if (word1.equalsIgnoreCase("INSERT")) {
|
||||
request.setType(SqlType.SQL_INSERT, word3, "InsertSql");
|
||||
request.setType(SqlType.SQL_INSERT, word3);
|
||||
|
||||
} else {
|
||||
request.setType(SqlType.SQL_UNKNOWN, null, "UnknownSql");
|
||||
request.setType(SqlType.SQL_UNKNOWN, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +157,7 @@ class ExeUpdateSql {
|
||||
if (spaceCount < 2) {
|
||||
// unknown so no automatic L2 cache invalidation performed (so it should instead)
|
||||
// be done explicitly via the server.externalModification() method
|
||||
request.setType(SqlType.SQL_UNKNOWN, null, "UnknownSql");
|
||||
request.setType(SqlType.SQL_UNKNOWN, null);
|
||||
|
||||
} else {
|
||||
// try to determine if it is insert, update or delete and the table involved
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.ebeaninternal.server.persist;
|
||||
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.server.core.PersistRequest;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.deploy.BeanCollectionUtil;
|
||||
@@ -24,7 +24,7 @@ import java.util.Set;
|
||||
/**
|
||||
* Saves the details for a OneToMany or ManyToMany relationship (entity beans).
|
||||
*/
|
||||
class SaveManyBeans extends SaveManyBase {
|
||||
public class SaveManyBeans extends SaveManyBase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SaveManyBeans.class);
|
||||
|
||||
@@ -244,14 +244,29 @@ class SaveManyBeans extends SaveManyBase {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
if (request.isQueueManyIntersection()) {
|
||||
// queue/delay until bean persist request is flushed
|
||||
this.deleteMissing = deleteMissingChildren;
|
||||
request.addManyIntersection(this);
|
||||
} else {
|
||||
saveAssocManyIntersection(deleteMissingChildren, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Push intersection table changes onto batch flush queue.
|
||||
*/
|
||||
public void saveIntersectionBatch() {
|
||||
saveAssocManyIntersection(deleteMissing, true);
|
||||
}
|
||||
|
||||
private void saveAssocManyIntersection(boolean deleteMissingChildren, boolean queue) {
|
||||
|
||||
//SpiTransaction t = saveManyPropRequest.getTransaction();
|
||||
boolean vanillaCollection = !(value instanceof BeanCollection<?>);
|
||||
|
||||
if (vanillaCollection || deleteMissingChildren) {
|
||||
// delete all intersection rows and then treat all
|
||||
// beans in the collection as additions
|
||||
persister.deleteAssocManyIntersection(parentBean, many, transaction, publish);
|
||||
persister.deleteManyIntersection(parentBean, many, transaction, publish, queue);
|
||||
}
|
||||
|
||||
Collection<?> deletions = null;
|
||||
@@ -287,10 +302,6 @@ class SaveManyBeans extends SaveManyBase {
|
||||
transaction.depth(+1);
|
||||
|
||||
if (additions != null && !additions.isEmpty()) {
|
||||
// ensure any cascade batch has been flushed prior
|
||||
// to inserting into the intersection table
|
||||
transaction.flushBatch();
|
||||
|
||||
for (Object other : additions) {
|
||||
EntityBean otherBean = (EntityBean) other;
|
||||
// the object from the 'other' side of the ManyToMany
|
||||
@@ -309,24 +320,20 @@ class SaveManyBeans extends SaveManyBase {
|
||||
} else {
|
||||
// build a intersection row for 'insert'
|
||||
IntersectionRow intRow = many.buildManyToManyMapBean(parentBean, otherBean, publish);
|
||||
SqlUpdate sqlInsert = intRow.createInsert(server);
|
||||
persister.executeSqlUpdate(sqlInsert, transaction);
|
||||
SpiSqlUpdate sqlInsert = intRow.createInsert(server);
|
||||
persister.executeOrQueue(sqlInsert, transaction, queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deletions != null && !deletions.isEmpty()) {
|
||||
// ensure any cascade batch has been flushed prior
|
||||
// to inserting into the intersection table
|
||||
transaction.flushBatch();
|
||||
|
||||
for (Object other : deletions) {
|
||||
EntityBean otherDelete = (EntityBean) other;
|
||||
// the object from the 'other' side of the ManyToMany
|
||||
// build a intersection row for 'delete'
|
||||
IntersectionRow intRow = many.buildManyToManyMapBean(parentBean, otherDelete, publish);
|
||||
SqlUpdate sqlDelete = intRow.createDelete(server, DeleteMode.HARD);
|
||||
persister.executeSqlUpdate(sqlDelete, transaction);
|
||||
SpiSqlUpdate sqlDelete = intRow.createDelete(server, DeleteMode.HARD);
|
||||
persister.executeOrQueue(sqlDelete, transaction, queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,8 +82,8 @@ abstract class AbstractMultiValueBind extends MultiValueBind {
|
||||
//case NCLOB:
|
||||
case NCHAR:
|
||||
case NVARCHAR:
|
||||
return "varchar";
|
||||
case ExtraDbTypes.UUID: // Db Native UUID
|
||||
case ExtraDbTypes.UUID: // Postgres cast to uuid[]
|
||||
case ExtraDbTypes.INET: // Postgres cast to inet[]
|
||||
return "varchar";
|
||||
|
||||
default:
|
||||
|
||||
@@ -14,6 +14,9 @@ public class PostgresMultiValueBind extends AbstractMultiValueBind {
|
||||
if (dbType == ExtraDbTypes.UUID) {
|
||||
return (not) ? " != all(?::uuid[])" : " = any(?::uuid[])";
|
||||
}
|
||||
if (dbType == ExtraDbTypes.INET) {
|
||||
return (not) ? " != all(?::inet[])" : " = any(?::inet[])";
|
||||
}
|
||||
String arrayType = getArrayType(dbType);
|
||||
if (arrayType == null) {
|
||||
return super.getInExpression(not, type, size);
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
class DbOrderByTrim {
|
||||
|
||||
private static final Pattern orderByTrim = Pattern.compile("(?i)\\b asc\\b|\\b desc\\b|\\b nulls first\\b|\\b nulls last\\b");
|
||||
private static final Pattern orderByTrim = Pattern.compile("(?i) asc\\b| desc\\b|\\b nulls first\\b|\\b nulls last\\b");
|
||||
|
||||
/**
|
||||
* Convert the dbOrderBy clause to be safe for adding to select or distinct on.
|
||||
|
||||
@@ -34,6 +34,11 @@ public class DefaultRelationalQuery implements SpiSqlQuery {
|
||||
|
||||
private int bufferFetchSizeHint;
|
||||
|
||||
/**
|
||||
* Helper to add positioned parameters in order.
|
||||
*/
|
||||
private int addPos;
|
||||
|
||||
/**
|
||||
* Bind parameters when using the query language.
|
||||
*/
|
||||
@@ -107,6 +112,14 @@ public class DefaultRelationalQuery implements SpiSqlQuery {
|
||||
return Optional.ofNullable(findOne());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultRelationalQuery setParams(Object... values) {
|
||||
for (Object value : values) {
|
||||
setParameter(++addPos, value);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultRelationalQuery setParameter(int position, Object value) {
|
||||
bindParams.setParameter(position, value);
|
||||
|
||||
@@ -334,6 +334,24 @@ public final class ConvertInetAddresses {
|
||||
return ip.getHostAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the host address without the square brackets around IPv6 addresses.
|
||||
*/
|
||||
public static String toHostAddress(InetAddress ip) {
|
||||
return ip.getHostAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the IPv4 or IPv6 address without quare brackets around IPv6 addresses.
|
||||
*/
|
||||
public static InetAddress fromHost(String hostAddr) {
|
||||
if (hostAddr.startsWith("[")) {
|
||||
// IPv6 address
|
||||
hostAddr = hostAddr.substring(1, hostAddr.length() - 1);
|
||||
}
|
||||
return forString(hostAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InetAddress representing the literal IPv4 or IPv6 host
|
||||
* portion of a URL, encoded in the format specified by RFC 3986 section 3.2.2.
|
||||
|
||||
@@ -14,6 +14,8 @@ import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.types.Cdir;
|
||||
import io.ebean.types.Inet;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.api.ExtraTypeFactory;
|
||||
import io.ebeaninternal.dbmigration.DbOffline;
|
||||
@@ -37,6 +39,8 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
@@ -128,7 +132,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
private final ScalarType<?> dateType = new ScalarTypeDate();
|
||||
|
||||
private final ScalarType<?> inetAddressType = new ScalarTypeInetAddress();
|
||||
private final ScalarType<?> urlType = new ScalarTypeURL();
|
||||
private final ScalarType<?> uriType = new ScalarTypeURI();
|
||||
private final ScalarType<?> localeType = new ScalarTypeLocale();
|
||||
@@ -975,8 +978,21 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
addType(UUID.class, uuidType);
|
||||
}
|
||||
|
||||
if (offlineMigrationGeneration || (postgres && !config.getPlatformConfig().isDatabaseInetAddressVarchar())) {
|
||||
addInetAddressType(new ScalarTypeInetAddressPostgres());
|
||||
} else {
|
||||
addInetAddressType(new ScalarTypeInetAddress());
|
||||
}
|
||||
|
||||
if (offlineMigrationGeneration || postgres) {
|
||||
addType(Cdir.class, new ScalarTypeCdir.Postgres());
|
||||
addType(Inet.class, new ScalarTypeInet.Postgres());
|
||||
} else {
|
||||
addType(Cdir.class, new ScalarTypeCdir.Varchar());
|
||||
addType(Inet.class, new ScalarTypeInet.Varchar());
|
||||
}
|
||||
|
||||
addType(File.class, fileType);
|
||||
addType(InetAddress.class, inetAddressType);
|
||||
addType(Locale.class, localeType);
|
||||
addType(Currency.class, currencyType);
|
||||
addType(TimeZone.class, timeZoneType);
|
||||
@@ -1063,4 +1079,10 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
nativeMap.put(Types.TIMESTAMP, timestampType);
|
||||
}
|
||||
|
||||
private void addInetAddressType(ScalarType scalarType) {
|
||||
addType(InetAddress.class, scalarType);
|
||||
addType(Inet4Address.class, scalarType);
|
||||
addType(Inet6Address.class, scalarType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,12 @@ public class PostgresHelper {
|
||||
*/
|
||||
public static final String JSONB_TYPE = "jsonb";
|
||||
|
||||
public static final String INET_TYPE = "inet";
|
||||
|
||||
public static Object asInet(String value) throws SQLException {
|
||||
return asObject(INET_TYPE, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct and return Postgres specific PG object.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.types.Cdir;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* ScalarType for Cdir to Varchar or Postgres CDIR.
|
||||
*/
|
||||
public abstract class ScalarTypeCdir extends ScalarTypeBaseVarchar<Cdir> {
|
||||
|
||||
ScalarTypeCdir() {
|
||||
super(Cdir.class, false, ExtraDbTypes.INET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void bind(DataBind b, Cdir value) throws SQLException;
|
||||
|
||||
@Override
|
||||
public Cdir convertFromDbString(String dbValue) {
|
||||
return parse(dbValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToDbString(Cdir beanValue) {
|
||||
return formatValue(beanValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Cdir value) {
|
||||
return value.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cdir parse(String value) {
|
||||
return new Cdir(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cdir to Varchar.
|
||||
*/
|
||||
public static class Varchar extends ScalarTypeCdir {
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, Cdir value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
b.setString(convertToDbString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cdir to Postgres CDIR.
|
||||
*/
|
||||
public static class Postgres extends ScalarTypeCdir {
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, Cdir value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.OTHER);
|
||||
} else {
|
||||
String strValue = convertToDbString(value);
|
||||
b.setObject(PostgresHelper.asInet(strValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.types.Inet;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* ScalarType for Inet to Varchar or Postgres INET.
|
||||
*/
|
||||
public abstract class ScalarTypeInet extends ScalarTypeBaseVarchar<Inet> {
|
||||
|
||||
ScalarTypeInet(int jdbcType) {
|
||||
super(Inet.class, false, jdbcType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void bind(DataBind b, Inet value) throws SQLException;
|
||||
|
||||
@Override
|
||||
public Inet convertFromDbString(String dbValue) {
|
||||
return parse(dbValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToDbString(Inet beanValue) {
|
||||
return formatValue(beanValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(Inet value) {
|
||||
return value.getAddress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inet parse(String value) {
|
||||
return new Inet(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inet to Varchar.
|
||||
*/
|
||||
public static class Varchar extends ScalarTypeInet {
|
||||
|
||||
Varchar() {
|
||||
super(Types.VARCHAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, Inet value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.VARCHAR);
|
||||
} else {
|
||||
b.setString(convertToDbString(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inet to Postgres INET.
|
||||
*/
|
||||
public static class Postgres extends ScalarTypeInet {
|
||||
|
||||
Postgres() {
|
||||
super(ExtraDbTypes.INET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, Inet value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.OTHER);
|
||||
} else {
|
||||
String strValue = convertToDbString(value);
|
||||
b.setObject(PostgresHelper.asInet(strValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.text.TextException;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* ScalarType for InetAddress to Postgres INET.
|
||||
*/
|
||||
public class ScalarTypeInetAddressPostgres extends ScalarTypeBaseVarchar<InetAddress> {
|
||||
|
||||
public ScalarTypeInetAddressPostgres() {
|
||||
super(InetAddress.class, false, ExtraDbTypes.INET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBind b, InetAddress value) throws SQLException {
|
||||
if (value == null) {
|
||||
b.setNull(Types.OTHER);
|
||||
} else {
|
||||
String strValue = convertToDbString(value);
|
||||
b.setObject(PostgresHelper.asInet(strValue));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress convertFromDbString(String dbValue) {
|
||||
try {
|
||||
return parse(dbValue);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new RuntimeException("Error with InetAddresses [" + dbValue + "] " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertToDbString(InetAddress beanValue) {
|
||||
return formatValue(beanValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String formatValue(InetAddress v) {
|
||||
return ConvertInetAddresses.toHostAddress(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetAddress parse(String value) {
|
||||
try {
|
||||
return ConvertInetAddresses.fromHost(value);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new TextException("Error with InetAddresses [{}]", value, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -94,6 +94,16 @@ public abstract class BaseTestCase {
|
||||
return trimSql(query.getGeneratedSql(), columns);
|
||||
}
|
||||
|
||||
protected void assertSqlBind(List<String> sql, int i) {
|
||||
assertThat(sql.get(i)).contains("-- bind");
|
||||
}
|
||||
|
||||
protected void assertSqlBind(List<String> sql, int from, int to) {
|
||||
for (int i = from; i <= to; i++) {
|
||||
assertThat(sql.get(i)).contains("-- bind");
|
||||
}
|
||||
}
|
||||
|
||||
protected String trimSql(String sql) {
|
||||
|
||||
if (sql.contains(" c1,")) {
|
||||
|
||||
@@ -143,7 +143,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
if (isSqlServer()) {
|
||||
assertThat(sql.get(0)).contains("select top 10 t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
|
||||
} else {
|
||||
assertThat(sql.get(0)).contains("select t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
@@ -175,7 +175,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
if (isSqlServer()) {
|
||||
assertThat(sql.get(0)).contains("select top 10 t0.id, t0.email, "
|
||||
+ concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
} else {
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
|
||||
@@ -130,7 +130,7 @@ public class DtoQueryTest extends BaseTestCase {
|
||||
|
||||
List<Integer> ids = Arrays.asList(1, 2);
|
||||
|
||||
List<SqlRow> list = server().createSqlQuery("select id, name from o_customer where id = any(?)")
|
||||
List<SqlRow> list = DB.sqlQuery("select id, name from o_customer where id = any(?)")
|
||||
.setParameter(1, ids)
|
||||
.findList();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
List<EBasicVer> someBeans = beans(3);
|
||||
|
||||
Ebean.saveAll(someBeans);
|
||||
DB.saveAll(someBeans);
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
ids.add(someBean.getId());
|
||||
@@ -25,7 +25,7 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.deleteAll(EBasicVer.class, ids);
|
||||
DB.deleteAll(EBasicVer.class, ids);
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertThat(loggedSql).hasSize(1);
|
||||
@@ -37,21 +37,18 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
List<EBasicVer> someBeans = beans(3);
|
||||
|
||||
Ebean.saveAll(someBeans);
|
||||
DB.saveAll(someBeans);
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
ids.add(someBean.getId());
|
||||
}
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database db = DB.getDefault();
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = server.beginTransaction();
|
||||
try {
|
||||
server.deleteAll(EBasicVer.class, ids, txn);
|
||||
try (Transaction txn = db.beginTransaction()) {
|
||||
db.deleteAll(EBasicVer.class, ids, txn);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertThat(loggedSql).hasSize(1);
|
||||
@@ -63,7 +60,7 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
List<EBasicVer> someBeans = beans(3);
|
||||
|
||||
Ebean.saveAll(someBeans);
|
||||
DB.saveAll(someBeans);
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
ids.add(someBean.getId());
|
||||
@@ -71,7 +68,7 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.deleteAllPermanent(EBasicVer.class, ids);
|
||||
DB.deleteAllPermanent(EBasicVer.class, ids);
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertThat(loggedSql).hasSize(1);
|
||||
@@ -84,21 +81,18 @@ public class EbeanServer_deleteAllByIdTest extends BaseTestCase {
|
||||
|
||||
List<EBasicVer> someBeans = beans(3);
|
||||
|
||||
Ebean.saveAll(someBeans);
|
||||
DB.saveAll(someBeans);
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (EBasicVer someBean : someBeans) {
|
||||
ids.add(someBean.getId());
|
||||
}
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database db = DB.getDefault();
|
||||
// act
|
||||
LoggedSqlCollector.start();
|
||||
Transaction txn = server.beginTransaction();
|
||||
try {
|
||||
server.deleteAllPermanent(EBasicVer.class, ids, txn);
|
||||
try (Transaction txn = db.beginTransaction()) {
|
||||
db.deleteAllPermanent(EBasicVer.class, ids, txn);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
assertThat(loggedSql).hasSize(1);
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.text.PathProperties;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import org.junit.Test;
|
||||
import org.tests.inheritance.Stockforecast;
|
||||
import org.tests.model.basic.Car;
|
||||
import org.tests.model.basic.Customer;
|
||||
@@ -15,60 +16,61 @@ import org.tests.model.basic.OrderDetail;
|
||||
import org.tests.model.basic.Person;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.tests.model.basic.Vehicle;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
public class BeanTypeTest {
|
||||
|
||||
static EbeanServer server = Ebean.getDefaultServer();
|
||||
static Database db = DB.getDefault();
|
||||
|
||||
<T> BeanType<T> beanType(Class<T> cls) {
|
||||
return server.getPluginApi().getBeanType(cls);
|
||||
return db.getPluginApi().getBeanType(cls);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBeanType() throws Exception {
|
||||
public void getBeanType() {
|
||||
assertThat(beanType(Order.class).getBeanType()).isEqualTo(Order.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTypeAtPath_when_ManyToOne() throws Exception {
|
||||
public void getTypeAtPath_when_ManyToOne() {
|
||||
BeanType<Order> orderType = beanType(Order.class);
|
||||
BeanType<?> customerType = orderType.getBeanTypeAtPath("customer");
|
||||
assertThat(customerType.getBeanType()).isEqualTo(Customer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTypeAtPath_when_OneToMany() throws Exception {
|
||||
public void getTypeAtPath_when_OneToMany() {
|
||||
BeanType<Order> orderType = beanType(Order.class);
|
||||
BeanType<?> detailsType = orderType.getBeanTypeAtPath("details");
|
||||
assertThat(detailsType.getBeanType()).isEqualTo(OrderDetail.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTypeAtPath_when_nested() throws Exception {
|
||||
public void getTypeAtPath_when_nested() {
|
||||
BeanType<Order> orderType = beanType(Order.class);
|
||||
BeanType<?> productType = orderType.getBeanTypeAtPath("details.product");
|
||||
assertThat(productType.getBeanType()).isEqualTo(Product.class);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void getTypeAtPath_when_simpleType() throws Exception {
|
||||
public void getTypeAtPath_when_simpleType() {
|
||||
|
||||
beanType(Order.class).getBeanTypeAtPath("status");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createBean() throws Exception {
|
||||
public void createBean() {
|
||||
|
||||
assertThat(beanType(Order.class).createBean()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void property() throws Exception {
|
||||
public void property() {
|
||||
|
||||
Order order = new Order();
|
||||
order.setStatus(Order.Status.APPROVED);
|
||||
@@ -78,13 +80,13 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getBaseTable() throws Exception {
|
||||
public void getBaseTable() {
|
||||
|
||||
assertThat(beanType(Order.class).getBaseTable()).isEqualTo("o_order");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanId_and_getBeanId() throws Exception {
|
||||
public void beanId_and_getBeanId() {
|
||||
|
||||
Order order = new Order();
|
||||
order.setId(42);
|
||||
@@ -97,7 +99,7 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setBeanId() throws Exception {
|
||||
public void setBeanId() {
|
||||
|
||||
Order order = new Order();
|
||||
beanType(Order.class).setBeanId(order, 42);
|
||||
@@ -106,7 +108,7 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isDocStoreIndex() throws Exception {
|
||||
public void isDocStoreIndex() {
|
||||
|
||||
assertThat(beanType(Order.class).isDocStoreMapped()).isFalse();
|
||||
assertThat(beanType(Person.class).isDocStoreMapped()).isFalse();
|
||||
@@ -116,7 +118,7 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docStore_getEmbedded() throws Exception {
|
||||
public void docStore_getEmbedded() {
|
||||
|
||||
BeanDocType<Order> orderDocType = beanType(Order.class).docStore();
|
||||
FetchPath customer = orderDocType.getEmbedded("customer");
|
||||
@@ -125,7 +127,7 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docStore_getEmbeddedManyRoot() throws Exception {
|
||||
public void docStore_getEmbeddedManyRoot() {
|
||||
|
||||
BeanDocType<Order> orderDocType = beanType(Order.class).docStore();
|
||||
|
||||
@@ -139,28 +141,28 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDocStoreQueueId() throws Exception {
|
||||
public void getDocStoreQueueId() {
|
||||
|
||||
assertThat(beanType(Order.class).getDocStoreQueueId()).isEqualTo("order");
|
||||
assertThat(beanType(Customer.class).getDocStoreQueueId()).isEqualTo("customer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDocStoreIndexType() throws Exception {
|
||||
public void getDocStoreIndexType() {
|
||||
|
||||
assertThat(beanType(Order.class).docStore().getIndexType()).isEqualTo("order");
|
||||
assertThat(beanType(Customer.class).docStore().getIndexType()).isEqualTo("customer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDocStoreIndexName() throws Exception {
|
||||
public void getDocStoreIndexName() {
|
||||
|
||||
assertThat(beanType(Order.class).docStore().getIndexType()).isEqualTo("order");
|
||||
assertThat(beanType(Customer.class).docStore().getIndexType()).isEqualTo("customer");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docStoreNested() throws Exception {
|
||||
public void docStoreNested() {
|
||||
|
||||
FetchPath parse = PathProperties.parse("id,name");
|
||||
|
||||
@@ -169,9 +171,9 @@ public class BeanTypeTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void docStoreApplyPath() throws Exception {
|
||||
public void docStoreApplyPath() {
|
||||
|
||||
SpiQuery<Order> orderQuery = (SpiQuery<Order>) server.find(Order.class);
|
||||
SpiQuery<Order> orderQuery = (SpiQuery<Order>) db.find(Order.class);
|
||||
beanType(Order.class).docStore().applyPath(orderQuery);
|
||||
|
||||
OrmQueryDetail detail = orderQuery.getDetail();
|
||||
@@ -228,13 +230,13 @@ public class BeanTypeTest {
|
||||
|
||||
@Test
|
||||
public void addInheritanceWhere_when_leaf() {
|
||||
Query<Vehicle> query = server.find(Vehicle.class);
|
||||
Query<Vehicle> query = db.find(Vehicle.class);
|
||||
beanType(Car.class).addInheritanceWhere(query);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addInheritanceWhere_when_root() {
|
||||
Query<Vehicle> query = server.find(Vehicle.class);
|
||||
Query<Vehicle> query = db.find(Vehicle.class);
|
||||
beanType(Vehicle.class).addInheritanceWhere(query);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
package io.ebean.text.json;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.text.PathProperties;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
@@ -16,16 +15,18 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class JsonContextTest {
|
||||
|
||||
@Test
|
||||
public void testIsSupportedType() throws Exception {
|
||||
public void testIsSupportedType() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
JsonContext json = server.json();
|
||||
JsonContext json = DB.json();
|
||||
assertTrue(json.isSupportedType(Customer.class));
|
||||
assertFalse(json.isSupportedType(System.class));
|
||||
}
|
||||
@@ -35,14 +36,14 @@ public class JsonContextTest {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<Order> orders = Ebean.find(Order.class)
|
||||
List<Order> orders = DB.find(Order.class)
|
||||
.fetch("customer", "id, name")
|
||||
.where().eq("customer.id", 1)
|
||||
.findList();
|
||||
|
||||
String json = Ebean.json().toJson(orders);
|
||||
String json = DB.json().toJson(orders);
|
||||
|
||||
List<Order> orders1 = Ebean.json().toList(Order.class, json);
|
||||
List<Order> orders1 = DB.json().toList(Order.class, json);
|
||||
|
||||
Customer customer = null;
|
||||
for (Order order : orders1) {
|
||||
@@ -60,16 +61,16 @@ public class JsonContextTest {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<Order> orders = Ebean.find(Order.class)
|
||||
List<Order> orders = DB.find(Order.class)
|
||||
.select("status")
|
||||
.fetch("customer", "id, name")
|
||||
.findList();
|
||||
|
||||
String json = Ebean.json().toJson(orders);
|
||||
String json = DB.json().toJson(orders);
|
||||
|
||||
JsonReadOptions options = new JsonReadOptions().setEnableLazyLoading(true);
|
||||
|
||||
List<Order> orders1 = Ebean.json().toList(Order.class, json, options);
|
||||
List<Order> orders1 = DB.json().toList(Order.class, json, options);
|
||||
|
||||
for (Order order : orders1) {
|
||||
Customer customer = order.getCustomer();
|
||||
@@ -81,11 +82,9 @@ public class JsonContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_toObject() throws Exception {
|
||||
public void test_toObject() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
JsonContext json = server.json();
|
||||
JsonContext json = DB.getDefault().json();
|
||||
|
||||
Customer customer = new Customer();
|
||||
customer.setId(1);
|
||||
@@ -111,7 +110,7 @@ public class JsonContextTest {
|
||||
|
||||
String jsonWithUnknown = "{\"id\":42,\"unknownProp\":\"foo\",\"name\":\"rob\",\"version\":1}";
|
||||
|
||||
Customer customer = Ebean.json().toBean(Customer.class, jsonWithUnknown);
|
||||
Customer customer = DB.json().toBean(Customer.class, jsonWithUnknown);
|
||||
assertEquals(Integer.valueOf(42), customer.getId());
|
||||
assertEquals("rob", customer.getName());
|
||||
}
|
||||
@@ -139,7 +138,7 @@ public class JsonContextTest {
|
||||
options.addRootVisitor(custReadVisitor);
|
||||
|
||||
|
||||
Customer customer = Ebean.json().toBean(Customer.class, jsonWithUnknown, options);
|
||||
Customer customer = DB.json().toBean(Customer.class, jsonWithUnknown, options);
|
||||
assertEquals(Integer.valueOf(42), customer.getId());
|
||||
assertEquals("rob", customer.getName());
|
||||
|
||||
@@ -160,7 +159,7 @@ public class JsonContextTest {
|
||||
JsonReadOptions options = new JsonReadOptions();
|
||||
options.addRootVisitor(custReadVisitor);
|
||||
|
||||
Customer customer = Ebean.json().toBean(Customer.class, someJsonAllKnown, options);
|
||||
Customer customer = DB.json().toBean(Customer.class, someJsonAllKnown, options);
|
||||
assertEquals(Integer.valueOf(42), customer.getId());
|
||||
assertEquals("rob", customer.getName());
|
||||
|
||||
@@ -171,10 +170,8 @@ public class JsonContextTest {
|
||||
@Test
|
||||
public void testCreateGenerator() throws Exception {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonContext json = server.json();
|
||||
JsonContext json = DB.json();
|
||||
JsonGenerator generator = json.createGenerator(writer);
|
||||
|
||||
Customer customer = new Customer();
|
||||
@@ -198,10 +195,8 @@ public class JsonContextTest {
|
||||
@Test
|
||||
public void testCreateGenerator_writeRaw() throws Exception {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonContext json = server.json();
|
||||
JsonContext json = DB.json();
|
||||
JsonGenerator generator = json.createGenerator(writer);
|
||||
|
||||
// test that we can write anything via writeRaw()
|
||||
|
||||
@@ -507,14 +507,24 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery sqlQuery(String sql) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery createSqlQuery(String sql) {
|
||||
return sqlQuery(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate sqlUpdate(String sql) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlUpdate createSqlUpdate(String sql) {
|
||||
return null;
|
||||
return sqlUpdate(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.SqlQuery;
|
||||
import io.ebean.SqlRow;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
@@ -108,8 +107,7 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
|
||||
// Run migration
|
||||
runScript(false, "1.1.sql");
|
||||
SqlQuery select = server().createSqlQuery("select * from migtest_e_basic order by id");
|
||||
List<SqlRow> result = select.findList();
|
||||
List<SqlRow> result = server().sqlQuery("select * from migtest_e_basic order by id").findList();
|
||||
assertThat(result).hasSize(2);
|
||||
|
||||
SqlRow row = result.get(0);
|
||||
@@ -137,11 +135,10 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
// Oracle caches the statement and does not detect schema change. It fails with
|
||||
// an ORA-01007
|
||||
if (isOracle()) {
|
||||
select = server().createSqlQuery("select * from migtest_e_basic order by id,id");
|
||||
result = server().sqlQuery("select * from migtest_e_basic order by id,id").findList();
|
||||
} else {
|
||||
select = server().createSqlQuery("select * from migtest_e_basic order by id");
|
||||
result = server().sqlQuery("select * from migtest_e_basic order by id").findList();
|
||||
}
|
||||
result = select.findList();
|
||||
assertThat(result).hasSize(2);
|
||||
row = result.get(0);
|
||||
assertThat(row.keySet()).doesNotContain("old_boolean", "old_boolean2");
|
||||
@@ -150,8 +147,7 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
runScript(false, "1.4__dropsFor_1.3.sql");
|
||||
|
||||
// now DB structure shoud be the same as v1_0
|
||||
select = server().createSqlQuery("select * from migtest_e_basic order by id");
|
||||
result = select.findList();
|
||||
result = server().sqlQuery("select * from migtest_e_basic order by id").findList();
|
||||
assertThat(result).hasSize(2);
|
||||
row = result.get(0);
|
||||
assertThat(row.keySet()).contains("old_boolean", "old_boolean2");
|
||||
|
||||
+3
-3
@@ -2,14 +2,14 @@ package io.ebeaninternal.dbmigration.model.build;
|
||||
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DefaultConstraintMaxLength;
|
||||
import io.ebeaninternal.dbmigration.model.MColumn;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import io.ebeaninternal.dbmigration.model.ModelContainer;
|
||||
import io.ebeaninternal.dbmigration.model.visitor.VisitAllUsing;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -19,7 +19,7 @@ public class ModelBuildBeanVisitorTest extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
SpiEbeanServer defaultServer = (SpiEbeanServer) Ebean.getDefaultServer();
|
||||
SpiEbeanServer defaultServer = (SpiEbeanServer) DB.getDefault();
|
||||
|
||||
ModelContainer model = new ModelContainer();
|
||||
|
||||
|
||||
@@ -11,7 +11,25 @@ import static org.assertj.core.api.StrictAssertions.assertThat;
|
||||
public class InExpressionTest extends BaseExpressionTest {
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_diffPropertyName_should_differentPlanHash() throws Exception {
|
||||
public void queryPlanHash_given_diffEmpty_should_differentPlanHash() {
|
||||
|
||||
List<Integer> emptyValues = values();
|
||||
|
||||
InExpression ex1 = new InExpression("foo", emptyValues, false, true);
|
||||
InExpression ex2 = new InExpression("foo", emptyValues, false);
|
||||
InExpression ex3 = new InExpression("foo", emptyValues, false, true);
|
||||
InExpression ex4 = new InExpression("foo", null, false, true);
|
||||
|
||||
ex1.prepareExpression(multi());
|
||||
ex2.prepareExpression(multi());
|
||||
|
||||
different(ex1, ex2);
|
||||
same(ex1, ex3); // same empty
|
||||
same(ex1, ex4); // same null
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_diffPropertyName_should_differentPlanHash() {
|
||||
|
||||
List<Integer> values = values(42, 92);
|
||||
|
||||
@@ -25,7 +43,7 @@ public class InExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_diffBindCount_should_differentPlanHash() throws Exception {
|
||||
public void queryPlanHash_given_diffBindCount_should_differentPlanHash() {
|
||||
|
||||
List<Integer> values1 = values(42, 92);
|
||||
List<Integer> values2 = values(42, 92, 82);
|
||||
@@ -39,7 +57,7 @@ public class InExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_diffBindCount_withMultiSupport_samePlanHash() throws Exception {
|
||||
public void queryPlanHash_given_diffBindCount_withMultiSupport_samePlanHash() {
|
||||
|
||||
List<Integer> values1 = values(42, 92);
|
||||
List<Integer> values2 = values(42, 92, 82);
|
||||
@@ -53,7 +71,7 @@ public class InExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_diffNotFlag_should_differentPlanHash() throws Exception {
|
||||
public void queryPlanHash_given_diffNotFlag_should_differentPlanHash() {
|
||||
|
||||
List<Integer> values = values(42, 92);
|
||||
|
||||
@@ -67,7 +85,7 @@ public class InExpressionTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void queryPlanHash_given_sameNotFlag_should_samePlanHash() throws Exception {
|
||||
public void queryPlanHash_given_sameNotFlag_should_samePlanHash() {
|
||||
|
||||
List<Integer> values = values(42, 92);
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class RawExpressionBuilderTest {
|
||||
|
||||
@Test
|
||||
public void buildSingle_noop() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo = ?", 42);
|
||||
assertThat(exp.sql).isEqualTo("foo = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildSingle_noExpand() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo = ?", asList(42, 43));
|
||||
assertThat(exp.sql).isEqualTo("foo = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildSingle_expand() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo in (?1)", asList(42, 43));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?,?)");
|
||||
assertThat(exp.values).contains(42, 43);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void buildSingle_expand_more() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo in (?1)", asList(42, 43, 44, 45));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?,?,?,?)");
|
||||
assertThat(exp.values).contains(42, 43, 44, 45);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void buildSingle_expand_single() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo in (?1)", asList(42));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?)");
|
||||
assertThat(exp.values).contains(42);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void build_noop() {
|
||||
RawExpression exp = RawExpressionBuilder.build("foo = ?", asArray(42));
|
||||
assertThat(exp.sql).isEqualTo("foo = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void build_noExpand() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.buildSingle("foo = ? and bar = any(?)", asArray(44, asList(42, 43)));
|
||||
assertThat(exp.sql).isEqualTo("foo = ? and bar = any(?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void build_expand() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.build("foo in (?) and bar in (?2)", asArray(44, asList(42, 43)));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?) and bar in (?,?)");
|
||||
assertThat(exp.values).contains(44, 42, 43);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void build_expand2() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.build("foo in (?) and bar in (?2) (?3)", asArray(44, asList(42, 43), asList(91, 92, 93)));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?) and bar in (?,?) (?,?,?)");
|
||||
assertThat(exp.values).containsExactly(44, 42, 43, 91, 92, 93);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void build_expand3() {
|
||||
|
||||
RawExpression exp = RawExpressionBuilder.build("foo in (?) and bar in (?2) (?3) and ?", asArray(44, asList(42, 43), asList(91, 92, 93), 87));
|
||||
assertThat(exp.sql).isEqualTo("foo in (?) and bar in (?,?) (?,?,?) and ?");
|
||||
assertThat(exp.values).containsExactly(44, 42, 43, 91, 92, 93, 87);
|
||||
}
|
||||
|
||||
private Object[] asArray(Object... values) {
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -364,6 +364,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.SQLSERVER)
|
||||
public void selectFetchFetchLimit() {
|
||||
|
||||
Query<Customer> query = parse("select name fetch billingAddress (line1, city) fetch shippingAddress (line1) limit 10");
|
||||
@@ -392,6 +393,7 @@ public class EqlParserTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.SQLSERVER)
|
||||
public void selectFetchFetchManyPropertiesLimit() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DbOrderByTrimTest {
|
||||
|
||||
@Test
|
||||
public void trim() {
|
||||
|
||||
String[] tests = {"foo", "bar", "a b c", "some_", "some()", "some'g'", "some('sd')", "some(a.b, '<s d>')"};
|
||||
for (String value : tests) {
|
||||
test(value, " desc");
|
||||
}
|
||||
for (String value : tests) {
|
||||
test(value, " asc");
|
||||
}
|
||||
}
|
||||
|
||||
private void test(String value, String suffix) {
|
||||
assertEquals(value, DbOrderByTrim.trim(value + suffix));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_when_pgp_sym_decrypt() {
|
||||
assertEquals("pgp_sym_decrypt(t0.columnName, '<encryption key>')", DbOrderByTrim.trim("pgp_sym_decrypt(t0.columnName, '<encryption key>') desc"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trim_doubleSpace() {
|
||||
assertEquals("foo bar", DbOrderByTrim.trim("foo desc bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trim_description() {
|
||||
assertEquals("foo description", DbOrderByTrim.trim("foo description"));
|
||||
assertEquals("foo ription", DbOrderByTrim.trim("foo desc ription"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trim_asc1() {
|
||||
assertEquals("foo asc1", DbOrderByTrim.trim("foo asc1"));
|
||||
assertEquals("foo 1", DbOrderByTrim.trim("foo asc 1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trim_various() {
|
||||
assertEquals("foo bar", DbOrderByTrim.trim("foo asc desc bar"));
|
||||
assertEquals("foo bar", DbOrderByTrim.trim("foo desc asc desc asc asc bar"));
|
||||
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo DESC"));
|
||||
assertEquals("foo ", DbOrderByTrim.trim("foo DESC "));
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo ASC"));
|
||||
assertEquals("foo ", DbOrderByTrim.trim("foo ASC "));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void trim_nulls() {
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo nulls first asc"));
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo nulls last desc"));
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo asc nulls first"));
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo desc nulls last"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,22 +3,28 @@ package io.ebeaninternal.server.transaction;
|
||||
import io.ebean.config.ProfilingConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class DefaultProfileHandlerTest {
|
||||
@Test
|
||||
public void createProfileStream() throws Exception {
|
||||
|
||||
DefaultProfileHandler handler = new DefaultProfileHandler(new ProfilingConfig());
|
||||
@Test
|
||||
public void createProfileStream() {
|
||||
|
||||
ProfilingConfig profilingConfig = new ProfilingConfig();
|
||||
profilingConfig.setDirectory("target/profiling");
|
||||
|
||||
DefaultProfileHandler handler = new DefaultProfileHandler(profilingConfig);
|
||||
|
||||
assertNotNull(handler.createProfileStream(12));
|
||||
assertNull(handler.createProfileStream(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createProfileStream_when_specificIncludeIds() throws Exception {
|
||||
public void createProfileStream_when_specificIncludeIds() {
|
||||
|
||||
ProfilingConfig config = new ProfilingConfig();
|
||||
config.setDirectory("target/profiling");
|
||||
config.setIncludeProfileIds(new int[]{100,101});
|
||||
|
||||
DefaultProfileHandler handler = new DefaultProfileHandler(config);
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class JdbcTransactionTest {
|
||||
|
||||
@Test
|
||||
public void isSkipCache() throws Exception {
|
||||
public void isSkipCache() {
|
||||
|
||||
Transaction transaction = Ebean.beginTransaction();
|
||||
try {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
// implicitly skip false due to query only at this point
|
||||
assertThat(transaction.isSkipCache()).isFalse();
|
||||
|
||||
EBasic basic = new EBasic("b1");
|
||||
Ebean.save(basic);
|
||||
DB.save(basic);
|
||||
|
||||
// implicitly skip true due to save
|
||||
assertThat(transaction.isSkipCache()).isTrue();
|
||||
@@ -35,42 +34,35 @@ public class JdbcTransactionTest {
|
||||
|
||||
transaction.setSkipCache(true);
|
||||
assertThat(transaction.isSkipCache()).isTrue();
|
||||
|
||||
} finally {
|
||||
transaction.end();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void skipCacheAfterSave() throws Exception {
|
||||
public void skipCacheAfterSave() {
|
||||
|
||||
ServerCacheManager cacheManager = Ebean.getDefaultServer().getServerCacheManager();
|
||||
ServerCacheManager cacheManager = DB.getDefault().getServerCacheManager();
|
||||
ServerCache customerBeanCache = cacheManager.getBeanCache(Customer.class);
|
||||
ServerCache contactNatKeyCache = cacheManager.getNaturalKeyCache(Contact.class);
|
||||
|
||||
Transaction transaction = Ebean.beginTransaction();
|
||||
try {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
customerBeanCache.getStatistics(true);
|
||||
contactNatKeyCache.getStatistics(true);
|
||||
|
||||
Customer.find.byId(19898989);
|
||||
Ebean.find(Contact.class).where().eq("email", "junk@foo.com").findOne();
|
||||
DB.find(Contact.class).where().eq("email", "junk@foo.com").findOne();
|
||||
|
||||
assertThat(customerBeanCache.getStatistics(true).getMissCount()).isEqualTo(1);
|
||||
assertThat(contactNatKeyCache.getStatistics(true).getMissCount()).isEqualTo(1);
|
||||
|
||||
EBasic basic = new EBasic("b1");
|
||||
Ebean.save(basic);
|
||||
DB.save(basic);
|
||||
|
||||
// these don't hit L2 cache due to the save of b1
|
||||
Customer.find.byId(29898989);
|
||||
Ebean.find(Contact.class).where().eq("email", "junk2@foo.com").findOne();
|
||||
DB.find(Contact.class).where().eq("email", "junk2@foo.com").findOne();
|
||||
|
||||
assertThat(customerBeanCache.getStatistics(true).getMissCount()).isEqualTo(0);
|
||||
assertThat(contactNatKeyCache.getStatistics(true).getMissCount()).isEqualTo(0);
|
||||
|
||||
} finally {
|
||||
transaction.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +1,46 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ConvertInetAddressTest {
|
||||
|
||||
@Test
|
||||
public void forString() {
|
||||
|
||||
InetAddress addr = ConvertInetAddresses.forString("128.1.10.23");
|
||||
Assert.assertNotNull(addr);
|
||||
Assert.assertEquals("128.1.10.23", addr.getHostAddress());
|
||||
assertEquals("128.1.10.23", addr.getHostAddress());
|
||||
|
||||
String ip6addr = "2001:db8:85a3:0:0:8a2e:370:7334";
|
||||
InetAddress addr6 = ConvertInetAddresses.forString(ip6addr);
|
||||
String uriAddr6 = ConvertInetAddresses.toUriString(addr6);
|
||||
Assert.assertEquals("[" + ip6addr + "]", uriAddr6);
|
||||
Assert.assertEquals(ip6addr, addr6.getHostAddress());
|
||||
assertEquals("[" + ip6addr + "]", uriAddr6);
|
||||
assertEquals(ip6addr, addr6.getHostAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ipv6_fromHost_getHostAddress() {
|
||||
InetAddress addr2 = ConvertInetAddresses.fromHost("2001:4f8:3:ba:2e0:81ff:fe22:d1f1");
|
||||
assertEquals("2001:4f8:3:ba:2e0:81ff:fe22:d1f1", addr2.getHostAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ipv6_fromHost_getHostAddress_2() {
|
||||
InetAddress addr2 = ConvertInetAddresses.fromHost("2001:db8:85a3:0:0:8a2e:370:7334");
|
||||
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", addr2.getHostAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toUriString() {
|
||||
|
||||
InetAddress addr = ConvertInetAddresses.forString("128.1.10.23");
|
||||
Assert.assertEquals("128.1.10.23", addr.getHostAddress());
|
||||
assertEquals("128.1.10.23", addr.getHostAddress());
|
||||
|
||||
String uriAddr = ConvertInetAddresses.toUriString(addr);
|
||||
Assert.assertEquals("128.1.10.23", uriAddr);
|
||||
assertEquals("128.1.10.23", uriAddr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,13 +16,21 @@ public class ScalarTypeInstantTest {
|
||||
|
||||
ScalarTypeInstant type = new ScalarTypeInstant(JsonConfig.DateTime.MILLIS);
|
||||
|
||||
private Instant now() {
|
||||
// in JDK11 Instant.now() returns a nanosecond precise instant.
|
||||
// as ScalarTypeInstant is only milliSecond precise, tests may fail with
|
||||
// expected:<2019-02-10T15:39:36.702700200Z> but was:<2019-02-10T15:39:36.702Z>
|
||||
// if we use Instant.now() - so we use this workaround here.
|
||||
return Instant.ofEpochMilli(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadData() throws Exception {
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(os);
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
type.writeData(out, now);
|
||||
type.writeData(out, null);
|
||||
out.flush();
|
||||
@@ -41,7 +49,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testToJdbcType() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Timestamp timestamp = Timestamp.from(now);
|
||||
Object val1 = type.toJdbcType(now);
|
||||
Object val2 = type.toJdbcType(timestamp);
|
||||
@@ -53,7 +61,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testToBeanType() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Instant val1 = type.toBeanType(now);
|
||||
Instant val2 = type.toBeanType(Timestamp.from(now));
|
||||
|
||||
@@ -64,7 +72,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testFormatValue() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Timestamp timestamp = Timestamp.from(now);
|
||||
String formatted = type.formatValue(now);
|
||||
assertEquals("" + timestamp.getTime(), formatted);
|
||||
@@ -73,7 +81,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testParse_when_epochMillis() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Timestamp timestamp = Timestamp.from(now);
|
||||
Instant val1 = type.parse("" + timestamp.getTime());
|
||||
assertEquals(now, val1);
|
||||
@@ -82,7 +90,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testParse_when_timestampForm() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Timestamp timestamp = Timestamp.from(now);
|
||||
Instant val1 = type.parse(timestamp.toString());
|
||||
assertEquals(now, val1);
|
||||
@@ -91,7 +99,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testFormatAndParse() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
|
||||
String format = type.format(now);
|
||||
Instant val1 = type.parse(format);
|
||||
@@ -107,7 +115,7 @@ public class ScalarTypeInstantTest {
|
||||
@Test
|
||||
public void testConvertFromMillis() throws Exception {
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
Instant val = type.convertFromMillis(now.toEpochMilli());
|
||||
assertEquals(now, val);
|
||||
}
|
||||
@@ -116,7 +124,7 @@ public class ScalarTypeInstantTest {
|
||||
public void testJsonRead() throws Exception {
|
||||
|
||||
|
||||
Instant now = Instant.now();
|
||||
Instant now = now();
|
||||
|
||||
JsonTester<Instant> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ScalarTypeLocalDateTimeTest {
|
||||
@Test
|
||||
public void testConvertToMillis() throws Exception {
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime now = LocalDateTime.now().withNano(123_000_000); // jdk11 workaround
|
||||
long asMillis = type.convertToMillis(now);
|
||||
LocalDateTime fromMillis = type.convertFromMillis(asMillis);
|
||||
|
||||
@@ -74,7 +74,7 @@ public class ScalarTypeLocalDateTimeTest {
|
||||
@Test
|
||||
public void testJson() throws Exception {
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime now = LocalDateTime.now().withNano(123_000_000); // jdk11 workaround
|
||||
|
||||
JsonTester<LocalDateTime> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
@@ -61,7 +61,7 @@ public class ScalarTypeOffsetDateTimeTest {
|
||||
@Test
|
||||
public void testJson() throws Exception {
|
||||
|
||||
OffsetDateTime now = OffsetDateTime.now();
|
||||
OffsetDateTime now = OffsetDateTime.now().withNano(123_000_000); // jdk11 workaround
|
||||
|
||||
JsonTester<OffsetDateTime> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
@@ -62,7 +62,7 @@ public class ScalarTypeZonedDateTimeTest {
|
||||
@Test
|
||||
public void testJson() throws Exception {
|
||||
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
ZonedDateTime now = ZonedDateTime.now().withNano(123_000_000); // jdk11 workaround
|
||||
|
||||
JsonTester<ZonedDateTime> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(now);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.SqlRow;
|
||||
import org.tests.model.basic.UUOne;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.UUOne;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -25,11 +25,11 @@ public class TestBinaryUUID extends BaseTestCase {
|
||||
one1.setId(id);
|
||||
one1.setName("second one");
|
||||
|
||||
Ebean.save(one0);
|
||||
Ebean.save(one1);
|
||||
DB.save(one0);
|
||||
DB.save(one1);
|
||||
|
||||
UUOne fetch0 = Ebean.find(UUOne.class, one0.getId());
|
||||
UUOne fetch1 = Ebean.find(UUOne.class, one1.getId());
|
||||
UUOne fetch0 = DB.find(UUOne.class, one0.getId());
|
||||
UUOne fetch1 = DB.find(UUOne.class, one1.getId());
|
||||
|
||||
assertEquals(one0.getId(), fetch0.getId());
|
||||
assertEquals(one0.getName(), fetch0.getName());
|
||||
@@ -38,7 +38,7 @@ public class TestBinaryUUID extends BaseTestCase {
|
||||
assertEquals(one1.getName(), fetch1.getName());
|
||||
|
||||
String sql = "select id, name from uuone";
|
||||
List<SqlRow> list = Ebean.createSqlQuery(sql).findList();
|
||||
List<SqlRow> list = DB.createSqlQuery(sql).findList();
|
||||
for (SqlRow sqlRow : list) {
|
||||
Object sqlId = sqlRow.get("id");
|
||||
assertNotNull(sqlId);
|
||||
@@ -47,8 +47,8 @@ public class TestBinaryUUID extends BaseTestCase {
|
||||
}
|
||||
|
||||
|
||||
String asJson = Ebean.json().toJson(fetch0);
|
||||
UUOne bean = Ebean.json().toBean(UUOne.class, asJson);
|
||||
String asJson = DB.json().toJson(fetch0);
|
||||
UUOne bean = DB.json().toBean(UUOne.class, asJson);
|
||||
|
||||
assertEquals(fetch0.getId(), bean.getId());
|
||||
assertEquals(fetch0.getName(), bean.getName());
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.SqlUpdate;
|
||||
import org.tests.model.basic.MRole;
|
||||
import org.tests.model.basic.MUser;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.MRole;
|
||||
import org.tests.model.basic.MUser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -17,32 +16,28 @@ public class TestM2MVanilla extends BaseTestCase {
|
||||
@Test
|
||||
public void testVanilla() {
|
||||
|
||||
SqlUpdate delInt = Ebean.createSqlUpdate("delete from mrole_muser");
|
||||
SqlUpdate delRoles = Ebean.createSqlUpdate("delete from mrole");
|
||||
SqlUpdate delUsers = Ebean.createSqlUpdate("delete from muser");
|
||||
|
||||
Ebean.execute(delInt);
|
||||
Ebean.execute(delRoles);
|
||||
Ebean.execute(delUsers);
|
||||
DB.createSqlUpdate("delete from mrole_muser").execute();
|
||||
DB.sqlUpdate("delete from mrole").execute();
|
||||
DB.sqlUpdate("delete from muser").execute();
|
||||
|
||||
MRole r1 = new MRole();
|
||||
r1.setRoleName("role1");
|
||||
Ebean.save(r1);
|
||||
DB.save(r1);
|
||||
|
||||
MRole r2 = new MRole();
|
||||
r2.setRoleName("role2");
|
||||
Ebean.save(r2);
|
||||
DB.save(r2);
|
||||
|
||||
MRole r3 = new MRole();
|
||||
r3.setRoleName("role3");
|
||||
Ebean.save(r3);
|
||||
DB.save(r3);
|
||||
|
||||
MUser u0 = new MUser();
|
||||
u0.setUserName("something");
|
||||
|
||||
Ebean.save(u0);
|
||||
DB.save(u0);
|
||||
|
||||
MUser user = Ebean.find(MUser.class, u0.getUserid());
|
||||
MUser user = DB.find(MUser.class, u0.getUserid());
|
||||
|
||||
List<MRole> roleList = new ArrayList<>();
|
||||
roleList.add(r1);
|
||||
@@ -50,34 +45,34 @@ public class TestM2MVanilla extends BaseTestCase {
|
||||
|
||||
user.setRoles(roleList);
|
||||
|
||||
Ebean.save(user);
|
||||
DB.save(user);
|
||||
// Ebean.saveManyToManyAssociations(user, "roles");
|
||||
|
||||
MUser checkUser = Ebean.find(MUser.class, u0.getUserid());
|
||||
MUser checkUser = DB.find(MUser.class, u0.getUserid());
|
||||
List<MRole> checkRoles = checkUser.getRoles();
|
||||
Assert.assertNotNull(checkRoles);
|
||||
Assert.assertEquals(2, checkRoles.size());
|
||||
|
||||
checkRoles.add(r3);
|
||||
|
||||
Ebean.save(checkUser);
|
||||
DB.save(checkUser);
|
||||
// Ebean.saveManyToManyAssociations(checkUser, "roles");
|
||||
|
||||
MUser checkUser2 = Ebean.find(MUser.class, u0.getUserid());
|
||||
MUser checkUser2 = DB.find(MUser.class, u0.getUserid());
|
||||
List<MRole> checkRoles2 = checkUser2.getRoles();
|
||||
Assert.assertNotNull(checkRoles2);
|
||||
Assert.assertEquals("added a role", 3, checkRoles2.size());
|
||||
|
||||
Query<MUser> rolesQuery0 = Ebean.find(MUser.class).where().eq("roles", r1).query();
|
||||
Query<MUser> rolesQuery0 = DB.find(MUser.class).where().eq("roles", r1).query();
|
||||
|
||||
rolesQuery0.findList();
|
||||
|
||||
Query<MUser> rolesQuery = Ebean.find(MUser.class).where().in("roles", roleList).query();
|
||||
Query<MUser> rolesQuery = DB.find(MUser.class).where().in("roles", roleList).query();
|
||||
|
||||
List<MUser> userInRolesList = rolesQuery.findList();
|
||||
Assert.assertTrue(!userInRolesList.isEmpty());
|
||||
|
||||
List<MUser> list = Ebean.find(MUser.class)
|
||||
List<MUser> list = DB.find(MUser.class)
|
||||
.where().in("roles", roleList)
|
||||
.filterMany("roles").eq("roleName", "role1")
|
||||
.findList();
|
||||
@@ -88,14 +83,14 @@ public class TestM2MVanilla extends BaseTestCase {
|
||||
|
||||
checkRoles2.remove(0);
|
||||
checkRoles2.remove(0);
|
||||
Ebean.save(checkUser2);
|
||||
DB.save(checkUser2);
|
||||
|
||||
checkUser2 = Ebean.find(MUser.class, u0.getUserid());
|
||||
checkUser2 = DB.find(MUser.class, u0.getUserid());
|
||||
checkRoles2 = checkUser2.getRoles();
|
||||
Assert.assertNotNull(checkRoles2);
|
||||
Assert.assertEquals("added a role", 1, checkRoles2.size());
|
||||
|
||||
Ebean.delete(checkUser2);
|
||||
DB.delete(checkUser2);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.SqlRow;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -17,7 +17,7 @@ public class TestOrderTotalAmountSql extends BaseTestCase {
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql = "select order_id, sum(order_qty*unit_price) as total_amount from o_order_detail where order_qty > :minQty group by order_id";
|
||||
List<SqlRow> sqlRows = Ebean.createSqlQuery(sql).setParameter("minQty", 1).findList();
|
||||
List<SqlRow> sqlRows = DB.sqlQuery(sql).setParameter("minQty", 1).findList();
|
||||
|
||||
for (SqlRow sqlRow : sqlRows) {
|
||||
Integer id = sqlRow.getInteger("order_id");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
@@ -9,6 +9,8 @@ import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestQueryWhereInRange extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
@@ -18,14 +20,77 @@ public class TestQueryWhereInRange extends BaseTestCase {
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query= Ebean.find(Order.class)
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.where().inRange("orderDate", today.minusDays(7), today)
|
||||
.isNotNull("id")
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
sqlOf(query).contains("(order_date >= ? and order_date < ?)");
|
||||
assertThat(sqlOf(query)).contains("where (t0.order_date >= ? and t0.order_date < ?) and ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eqOrNull() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.where().eqOrNull("orderDate", today)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.order_date = ? or t0.order_date is null)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void gtOrNull() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.where().gtOrNull("orderDate", today)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("where (t0.order_date > ? or t0.order_date is null)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ltOrNull() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.where().ltOrNull("orderDate", today)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains(" where (t0.order_date < ? or t0.order_date is null)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inRangeWith() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LocalDate today = LocalDate.now();
|
||||
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.where().inRangeWith("orderDate", "shipDate", today)
|
||||
.query();
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("(t0.order_date <= ? and (t0.ship_date > ? or t0.ship_date is null))");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package org.tests.basic.encrypt;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.SqlQuery;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.SqlRow;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
@@ -26,7 +25,7 @@ public class TestEncrypt extends BaseTestCase {
|
||||
public void testQueryBind() {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.find(EBasicEncrypt.class)
|
||||
DB.find(EBasicEncrypt.class)
|
||||
.where().startsWith("description", "Rob")
|
||||
.findList();
|
||||
|
||||
@@ -39,23 +38,23 @@ public class TestEncrypt extends BaseTestCase {
|
||||
@ForPlatform(Platform.H2)
|
||||
public void test() {
|
||||
|
||||
Ebean.find(EBasicEncrypt.class).delete();
|
||||
DB.find(EBasicEncrypt.class).delete();
|
||||
|
||||
EBasicEncrypt e = new EBasicEncrypt();
|
||||
e.setName("testname");
|
||||
e.setDescription("testdesc");
|
||||
e.setDob(new Date(System.currentTimeMillis() - 100000));
|
||||
|
||||
Ebean.save(e);
|
||||
DB.save(e);
|
||||
|
||||
SqlQuery q = Ebean.createSqlQuery("select * from e_basicenc where id = :id");
|
||||
q.setParameter("id", e.getId());
|
||||
SqlRow row = DB.createSqlQuery("select * from e_basicenc where id = :id")
|
||||
.setParameter("id", e.getId())
|
||||
.findOne();
|
||||
|
||||
SqlRow row = q.findOne();
|
||||
row.getString("name");
|
||||
row.get("description");
|
||||
|
||||
EBasicEncrypt e1 = Ebean.find(EBasicEncrypt.class, e.getId());
|
||||
EBasicEncrypt e1 = DB.find(EBasicEncrypt.class, e.getId());
|
||||
|
||||
e1.getDescription();
|
||||
|
||||
@@ -63,14 +62,14 @@ public class TestEncrypt extends BaseTestCase {
|
||||
e1.setDescription("moddesc");
|
||||
e1.setStatus(EBasicEncrypt.Status.ONE);
|
||||
|
||||
Ebean.save(e1);
|
||||
DB.save(e1);
|
||||
|
||||
EBasicEncrypt e2 = Ebean.find(EBasicEncrypt.class, e.getId());
|
||||
EBasicEncrypt e2 = DB.find(EBasicEncrypt.class, e.getId());
|
||||
|
||||
assertEquals("moddesc", e2.getDescription());
|
||||
assertEquals(EBasicEncrypt.Status.ONE, e2.getStatus());
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer) Ebean.getServer(null);
|
||||
SpiEbeanServer server = (SpiEbeanServer) DB.getDefault();
|
||||
DbEncrypt dbEncrypt = server.getDatabasePlatform().getDbEncrypt();
|
||||
|
||||
if (dbEncrypt == null) {
|
||||
@@ -79,12 +78,12 @@ public class TestEncrypt extends BaseTestCase {
|
||||
|
||||
} else {
|
||||
|
||||
List<EBasicEncrypt> list = Ebean.find(EBasicEncrypt.class).where()
|
||||
List<EBasicEncrypt> list = DB.find(EBasicEncrypt.class).where()
|
||||
.eq("description", "moddesc").findList();
|
||||
|
||||
assertEquals(1, list.size());
|
||||
|
||||
list = Ebean.find(EBasicEncrypt.class).where().startsWith("description", "modde").findList();
|
||||
list = DB.find(EBasicEncrypt.class).where().startsWith("description", "modde").findList();
|
||||
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package org.tests.basic.encrypt;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.SqlQuery;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.SqlRow;
|
||||
import org.tests.model.basic.EBasicEncryptBinary;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicEncryptBinary;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@@ -22,17 +21,17 @@ public class TestEncryptBinary extends BaseTestCase {
|
||||
e.setSomeTime(t0);
|
||||
e.setData("HelloWorld".getBytes());
|
||||
|
||||
Ebean.save(e);
|
||||
DB.save(e);
|
||||
|
||||
SqlQuery q = Ebean.createSqlQuery("select * from e_basicenc_bin where id = :id");
|
||||
q.setParameter("id", e.getId());
|
||||
SqlRow row = DB.createSqlQuery("select * from e_basicenc_bin where id = :id")
|
||||
.setParameter("id", e.getId())
|
||||
.findOne();
|
||||
|
||||
SqlRow row = q.findOne();
|
||||
row.getString("name");
|
||||
row.get("data");
|
||||
row.get("some_time");
|
||||
|
||||
EBasicEncryptBinary e1 = Ebean.find(EBasicEncryptBinary.class, e.getId());
|
||||
EBasicEncryptBinary e1 = DB.find(EBasicEncryptBinary.class, e.getId());
|
||||
|
||||
Timestamp t1 = e1.getSomeTime();
|
||||
e1.getData();
|
||||
@@ -44,9 +43,9 @@ public class TestEncryptBinary extends BaseTestCase {
|
||||
e1.setName("testmod");
|
||||
e1.setDescription("moddesc");
|
||||
|
||||
Ebean.save(e1);
|
||||
DB.save(e1);
|
||||
|
||||
EBasicEncryptBinary e2 = Ebean.find(EBasicEncryptBinary.class, e.getId());
|
||||
EBasicEncryptBinary e2 = DB.find(EBasicEncryptBinary.class, e.getId());
|
||||
e2.getDescription();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package org.tests.basic.type;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.SqlQuery;
|
||||
import io.ebean.SqlRow;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.tests.model.basic.EBasic.Status;
|
||||
import org.tests.model.basic.EBasicEnumId;
|
||||
import org.tests.model.basic.EBasicEnumInt;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -25,26 +25,25 @@ public class TestEnumValueAnnotation extends BaseTestCase {
|
||||
b.setName("Banana");
|
||||
b.setStatus(Status.NEW);
|
||||
|
||||
Ebean.save(b);
|
||||
DB.save(b);
|
||||
|
||||
SqlQuery q = Ebean.createSqlQuery("select * from e_basic where id = :id");
|
||||
q.setParameter("id", b.getId());
|
||||
SqlRow sqlRow = DB.createSqlQuery("select * from e_basic where id = :id")
|
||||
.setParameter("id", b.getId())
|
||||
.findOne();
|
||||
|
||||
SqlRow sqlRow = q.findOne();
|
||||
String strStatus = sqlRow.getString("status");
|
||||
|
||||
assertEquals("N", strStatus);
|
||||
|
||||
EBasic b2 = new EBasic();
|
||||
b2.setName("Apple");
|
||||
b2.setStatus(Status.NEW);
|
||||
|
||||
Ebean.save(b2);
|
||||
DB.save(b2);
|
||||
|
||||
EBasic b3 = Ebean.find(EBasic.class, b2.getId());
|
||||
EBasic b3 = DB.find(EBasic.class, b2.getId());
|
||||
b3.setName("Orange");
|
||||
|
||||
Ebean.save(b3);
|
||||
DB.save(b3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -53,9 +52,9 @@ public class TestEnumValueAnnotation extends BaseTestCase {
|
||||
b.setName("Banana");
|
||||
b.setStatus(EBasicEnumId.Status.NEW);
|
||||
|
||||
Ebean.save(b);
|
||||
DB.save(b);
|
||||
|
||||
SqlQuery q = Ebean.createSqlQuery("select * from e_basic_enum_id where status = :status");
|
||||
SqlQuery q = DB.createSqlQuery("select * from e_basic_enum_id where status = :status");
|
||||
q.setParameter("status", b.getStatus());
|
||||
|
||||
SqlRow sqlRow = q.findOne();
|
||||
@@ -64,7 +63,7 @@ public class TestEnumValueAnnotation extends BaseTestCase {
|
||||
assertEquals("N", strStatus);
|
||||
|
||||
try {
|
||||
b = Ebean.find(EBasicEnumId.class, b.getStatus());
|
||||
b = DB.find(EBasicEnumId.class, b.getStatus());
|
||||
} catch (java.lang.IllegalArgumentException iae) {
|
||||
Assert.fail("The use of an enum as id should work : " + iae.getLocalizedMessage());
|
||||
}
|
||||
@@ -79,9 +78,9 @@ public class TestEnumValueAnnotation extends BaseTestCase {
|
||||
b.setName("Banana");
|
||||
b.setStatus(EBasicEnumInt.Status.NEW);
|
||||
|
||||
Ebean.save(b);
|
||||
DB.save(b);
|
||||
|
||||
SqlQuery q = Ebean.createSqlQuery("select * from e_basic_eni where id = :id");
|
||||
SqlQuery q = DB.createSqlQuery("select * from e_basic_eni where id = :id");
|
||||
q.setParameter("id", b.getId());
|
||||
|
||||
Optional<SqlRow> sqlRow = q.findOneOrEmpty();
|
||||
@@ -91,7 +90,7 @@ public class TestEnumValueAnnotation extends BaseTestCase {
|
||||
});
|
||||
|
||||
|
||||
EBasicEnumInt b2 = Ebean.find(EBasicEnumInt.class)
|
||||
EBasicEnumInt b2 = DB.find(EBasicEnumInt.class)
|
||||
.where().eq("id", b.getId())
|
||||
.eq("status", EBasicEnumInt.Status.NEW)
|
||||
.findOne();
|
||||
|
||||
@@ -1,61 +1,153 @@
|
||||
package org.tests.basic.type;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
|
||||
import org.tests.model.basic.EWithInetAddr;
|
||||
import org.junit.Assert;
|
||||
import io.ebean.types.Cdir;
|
||||
import io.ebean.types.Inet;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EWithInetAddr;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class TestInetAddressType extends TransactionalTestCase {
|
||||
|
||||
@Test
|
||||
public void testIp4() throws UnknownHostException {
|
||||
|
||||
insertUpdateDeleteFind("120.12.12.56");
|
||||
insertUpdateDeleteFind("120.12.12.56", "120.12.12.56");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIp6() throws UnknownHostException {
|
||||
|
||||
insertUpdateDeleteFind("2001:db8:85a3:0:0:8a2e:370:7334");
|
||||
if (isPostgres()) {
|
||||
insertUpdateDeleteFind("2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3::8a2e:370:7334");
|
||||
} else {
|
||||
insertUpdateDeleteFind("2001:db8:85a3:0:0:8a2e:370:7334", "2001:db8:85a3:0:0:8a2e:370:7334");
|
||||
}
|
||||
}
|
||||
|
||||
private void insertUpdateDeleteFind(String ipAddress) throws UnknownHostException {
|
||||
@Test
|
||||
public void test_inet_queryIn() {
|
||||
|
||||
List<Inet> addrs = Inet.listOf("120.12.12.56", "120.12.12.57");
|
||||
|
||||
DB.find(EWithInetAddr.class)
|
||||
.where()
|
||||
.in("inet2", addrs)
|
||||
.findList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_inetAdress_queryIn() throws UnknownHostException {
|
||||
|
||||
List<InetAddress> addrs = new ArrayList<>();
|
||||
addrs.add(InetAddress.getByName("120.12.12.56"));
|
||||
addrs.add(InetAddress.getByName("120.12.12.57"));
|
||||
|
||||
DB.find(EWithInetAddr.class)
|
||||
.where()
|
||||
.in("inetAddress", addrs)
|
||||
.findList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_inet_queryEq() {
|
||||
|
||||
DB.find(EWithInetAddr.class)
|
||||
.where()
|
||||
.eq("inet2", new Inet("120.12.12.58"))
|
||||
.findList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_inet4address_queryEq() throws UnknownHostException {
|
||||
|
||||
DB.find(EWithInetAddr.class)
|
||||
.where()
|
||||
.eq("inetAddress", InetAddress.getByName("120.12.12.58"))
|
||||
.findList();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_inet6address_queryEq() throws UnknownHostException {
|
||||
|
||||
DB.find(EWithInetAddr.class)
|
||||
.where()
|
||||
.eq("inetAddress", InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"))
|
||||
.findList();
|
||||
}
|
||||
|
||||
private void insertUpdateDeleteFind(String ipAddress, String expected) throws UnknownHostException {
|
||||
|
||||
EWithInetAddr bean1 = new EWithInetAddr();
|
||||
bean1.setName("jim");
|
||||
|
||||
InetAddress address1 = InetAddress.getByName(ipAddress);
|
||||
bean1.setInetAddress(address1);
|
||||
bean1.setInet2(new Inet(ipAddress));
|
||||
bean1.setCdir(new Cdir(ipAddress));
|
||||
|
||||
Ebean.save(bean1);
|
||||
|
||||
EWithInetAddr bean2 = Ebean.find(EWithInetAddr.class, bean1.getId());
|
||||
DB.save(bean1);
|
||||
|
||||
EWithInetAddr bean2 = DB.find(EWithInetAddr.class, bean1.getId());
|
||||
InetAddress address2 = bean2.getInetAddress();
|
||||
Assert.assertNotNull(address2.getHostAddress());
|
||||
Assert.assertEquals(address1.getHostAddress(), address2.getHostAddress());
|
||||
assertNotNull(address2.getHostAddress());
|
||||
assertThat(address1.getHostAddress()).isEqualTo(address2.getHostAddress());
|
||||
assertThat(bean2.getInet2().getAddress()).isEqualTo(expected);
|
||||
assertThat(bean2.getCdir().getAddress()).isEqualTo(expected);
|
||||
|
||||
bean2.setName("modJim");
|
||||
bean2.setInetAddress(InetAddress.getByName("120.12.20.80"));
|
||||
Ebean.save(bean2);
|
||||
Ebean.delete(bean2);
|
||||
bean1.setInet2(new Inet("120.12.20.80"));
|
||||
bean1.setCdir(new Cdir("120.12.20.80"));
|
||||
DB.save(bean2);
|
||||
DB.delete(bean2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void use_null() throws UnknownHostException {
|
||||
public void testIp6_ranges() {
|
||||
|
||||
insertFindDeleteRange("2001:4f8:3:ba::/64");
|
||||
insertFindDeleteRange("2001:4f8:3:ba:2e0:81ff:fe22:d1f1/64");
|
||||
}
|
||||
|
||||
private void insertFindDeleteRange(String ipAddressRange) {
|
||||
|
||||
EWithInetAddr bean1 = new EWithInetAddr();
|
||||
bean1.setName("withRange");
|
||||
bean1.setInet2(new Inet(ipAddressRange));
|
||||
bean1.setCdir(new Cdir(ipAddressRange));
|
||||
|
||||
DB.save(bean1);
|
||||
|
||||
EWithInetAddr bean2 = DB.find(EWithInetAddr.class, bean1.getId());
|
||||
assertNotNull(bean2.getInet2());
|
||||
assertThat(bean2.getInet2().getAddress()).isEqualTo(ipAddressRange);
|
||||
assertThat(bean2.getCdir().getAddress()).isEqualTo(ipAddressRange);
|
||||
|
||||
DB.delete(bean2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void use_null() {
|
||||
|
||||
EWithInetAddr bean1 = new EWithInetAddr();
|
||||
bean1.setName("jim");
|
||||
|
||||
Ebean.save(bean1);
|
||||
DB.save(bean1);
|
||||
|
||||
EWithInetAddr bean2 = Ebean.find(EWithInetAddr.class, bean1.getId());
|
||||
InetAddress address2 = bean2.getInetAddress();
|
||||
Assert.assertNull(address2);
|
||||
EWithInetAddr bean2 = DB.find(EWithInetAddr.class, bean1.getId());
|
||||
assertNull(bean2.getInetAddress());
|
||||
assertNull(bean2.getInet2());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ public class TestBatchInsertFlush extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.SQLSERVER)
|
||||
public void noflushWhenIdIsLoaded() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
|
||||
@@ -5,12 +5,14 @@ import io.ebean.annotation.Cache;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
@Cache
|
||||
public class PersonCacheEmail {
|
||||
|
||||
@Id
|
||||
@Size(max=128)
|
||||
private String id;
|
||||
|
||||
@ManyToOne
|
||||
|
||||
@@ -4,12 +4,14 @@ import io.ebean.annotation.Cache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Entity
|
||||
@Cache
|
||||
public class PersonCacheInfo {
|
||||
|
||||
@Id
|
||||
@Size(max=128)
|
||||
private String personId;
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package org.tests.insert;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.plugin.Property;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -14,80 +16,74 @@ public class TestInsertCheckUnique extends BaseTestCase {
|
||||
|
||||
@Before
|
||||
public void clearDb() {
|
||||
server().find(Document.class).asDraft().where().contains("title", "UniqueKey").delete();
|
||||
server().find(Document.class).asDraft().where().isNull("title").delete();
|
||||
DB.find(Document.class).asDraft().where().contains("title", "UniqueKey").delete();
|
||||
DB.find(Document.class).asDraft().where().isNull("title").delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insert_duplicateKey() {
|
||||
server().beginTransaction();
|
||||
try {
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
Document doc1 = new Document();
|
||||
doc1.setTitle("ThisIsAUniqueKey");
|
||||
doc1.setTitle("AUniqueKey_duplicateCheck");
|
||||
doc1.setBody("one");
|
||||
|
||||
assertThat(server().checkUniqueness(doc1)).isEmpty();
|
||||
assertThat(DB.checkUniqueness(doc1)).isEmpty();
|
||||
doc1.save();
|
||||
|
||||
Document doc2 = new Document();
|
||||
doc2.setTitle("ThisIsAUniqueKey");
|
||||
doc2.setTitle("AUniqueKey_duplicateCheck");
|
||||
doc2.setBody("clashes with doc1");
|
||||
|
||||
assertThat(server().checkUniqueness(doc2)).isEmpty();
|
||||
assertThat(DB.checkUniqueness(doc2)).isEmpty();
|
||||
|
||||
server().publish(doc1.getClass(), doc1.getId());
|
||||
DB.getDefault().publish(doc1.getClass(), doc1.getId());
|
||||
|
||||
assertThat(server().checkUniqueness(doc2).toString()).contains("title");
|
||||
} finally {
|
||||
server().endTransaction();
|
||||
assertThat(DB.checkUniqueness(doc2).toString()).contains("title");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insert_duplicateNull() {
|
||||
server().beginTransaction();
|
||||
try {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
Document doc1 = new Document();
|
||||
doc1.setTitle(null);
|
||||
doc1.setBody("one");
|
||||
|
||||
assertThat(server().checkUniqueness(doc1)).isEmpty();
|
||||
assertThat(DB.checkUniqueness(doc1)).isEmpty();
|
||||
doc1.save();
|
||||
|
||||
Document doc2 = new Document();
|
||||
doc2.setTitle(null);
|
||||
doc2.setBody("clashes with doc1");
|
||||
|
||||
assertThat(server().checkUniqueness(doc2)).isEmpty();
|
||||
assertThat(DB.checkUniqueness(doc2)).isEmpty();
|
||||
|
||||
server().publish(doc1.getClass(), doc1.getId());
|
||||
DB.getDefault().publish(doc1.getClass(), doc1.getId());
|
||||
|
||||
assertThat(server().checkUniqueness(doc2)).isEmpty();
|
||||
assertThat(DB.checkUniqueness(doc2)).isEmpty();
|
||||
|
||||
doc2.save();
|
||||
server().publish(doc2.getClass(), doc2.getId());
|
||||
} finally {
|
||||
server().endTransaction();
|
||||
DB.getDefault().publish(doc2.getClass(), doc2.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void example() {
|
||||
|
||||
server().beginTransaction();
|
||||
try {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
Document doc1 = new Document();
|
||||
doc1.setTitle("One flew over the cuckoo's nest");
|
||||
doc1.setBody("one");
|
||||
doc1.save();
|
||||
|
||||
server().publish(doc1.getClass(), doc1.getId());
|
||||
DB.getDefault().publish(doc1.getClass(), doc1.getId());
|
||||
|
||||
Document doc2 = new Document();
|
||||
doc2.setTitle("One flew over the cuckoo's nest");
|
||||
doc2.setBody("clashes with doc1");
|
||||
|
||||
Set<Property> properties = server().checkUniqueness(doc2);
|
||||
Set<Property> properties = DB.checkUniqueness(doc2);
|
||||
if (properties.isEmpty()) {
|
||||
// it is unique ... carry on
|
||||
} else {
|
||||
@@ -110,9 +106,7 @@ public class TestInsertCheckUnique extends BaseTestCase {
|
||||
}
|
||||
|
||||
|
||||
assertThat(server().checkUniqueness(doc2).toString()).contains("title");
|
||||
} finally {
|
||||
server().endTransaction();
|
||||
assertThat(DB.checkUniqueness(doc2).toString()).contains("title");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ public class TestMergeM2M extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("select");
|
||||
assertThat(sql.get(1)).contains("insert into mmachine");
|
||||
assertThat(sql.get(2)).contains("insert into mmachine_mgroup");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("select");
|
||||
assertThat(sql.get(1)).contains("insert into mmachine");
|
||||
@@ -66,11 +66,13 @@ public class TestMergeM2M extends BaseTestCase {
|
||||
Ebean.merge(m1, options);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql).hasSize(9);
|
||||
assertThat(sql.get(0)).contains("select");
|
||||
assertThat(sql.get(1)).contains("delete from mmachine_mgroup");
|
||||
assertThat(sql.get(2)).contains("insert into mmachine_mgroup");
|
||||
assertThat(sql.get(3)).contains("update mmachine");
|
||||
assertSqlBind(sql, 2, 4);
|
||||
|
||||
assertThat(sql.get(5)).contains("insert into mmachine_mgroup");
|
||||
assertSqlBind(sql, 6, 7);
|
||||
assertThat(sql.get(8)).contains("update mmachine");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.tests.model.basic;
|
||||
|
||||
import io.ebean.types.Cdir;
|
||||
import io.ebean.types.Inet;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
@@ -20,6 +23,10 @@ public class EWithInetAddr {
|
||||
|
||||
InetAddress inetAddress;
|
||||
|
||||
Inet inet2;
|
||||
|
||||
Cdir cdir;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -52,4 +59,19 @@ public class EWithInetAddr {
|
||||
this.inetAddress = inetAddress;
|
||||
}
|
||||
|
||||
public Inet getInet2() {
|
||||
return inet2;
|
||||
}
|
||||
|
||||
public void setInet2(Inet inet2) {
|
||||
this.inet2 = inet2;
|
||||
}
|
||||
|
||||
public Cdir getCdir() {
|
||||
return cdir;
|
||||
}
|
||||
|
||||
public void setCdir(Cdir cdir) {
|
||||
this.cdir = cdir;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
eventLog();
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
EcPerson person = new EcPerson("Fiona021");
|
||||
@@ -30,11 +31,11 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ec_person");
|
||||
assertThat(sql.get(1)).contains("insert into ec_person_phone");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ec_person");
|
||||
assertThat(sql.get(1)).contains("insert into ec_person_phone");
|
||||
@@ -130,12 +131,13 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("update ec_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ec_person_phone where owner_id=?");
|
||||
assertThat(sql.get(2)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update ec_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ec_person_phone where owner_id=?");
|
||||
@@ -160,10 +162,12 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql).hasSize(9);
|
||||
assertThat(sql.get(0)).contains("update ec_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(2)).contains("delete from ec_person_phone where owner_id=?");
|
||||
assertThat(sql.get(3)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
assertSqlBind(sql, 3);
|
||||
assertThat(sql.get(4)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
assertSqlBind(sql, 5, 8);
|
||||
|
||||
assertThat(eventLog()).containsExactly("preUpdate", "postUpdate");
|
||||
|
||||
@@ -192,9 +196,11 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(8);
|
||||
assertThat(sql.get(0)).contains("delete from ec_person_phone where owner_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
assertSqlBind(sql, 1);
|
||||
assertThat(sql.get(2)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
assertSqlBind(sql, 3, 7);
|
||||
|
||||
assertThat(eventLog()).containsExactly("preUpdate", "postUpdate");
|
||||
|
||||
@@ -208,11 +214,12 @@ public class TestElementCollectionBasic extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(8);
|
||||
assertThat(sql.get(0)).contains("delete from ec_person_phone where owner_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 7);
|
||||
|
||||
} else {
|
||||
assertThat(sql).hasSize(7);
|
||||
assertThat(sql.get(0)).contains("delete from ec_person_phone where owner_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ec_person_phone (owner_id,phone) values (?,?)");
|
||||
|
||||
+7
-7
@@ -1,5 +1,6 @@
|
||||
package org.tests.model.elementcollection;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
@@ -10,7 +11,7 @@ import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestElementCollectionBasicCache {
|
||||
public class TestElementCollectionBasicCache extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@@ -42,9 +43,9 @@ public class TestElementCollectionBasicCache {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
}
|
||||
else {
|
||||
assertThat(sql).hasSize(6);
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
}
|
||||
|
||||
@@ -68,9 +69,8 @@ public class TestElementCollectionBasicCache {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2); // cache hit
|
||||
}
|
||||
else {
|
||||
assertThat(sql).hasSize(6); // cache hit
|
||||
} else {
|
||||
assertThat(sql).hasSize(5); // cache hit
|
||||
}
|
||||
|
||||
|
||||
@@ -25,11 +25,11 @@ public class TestElementCollectionBasicMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ecm_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecm_person_phone");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ecm_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecm_person_phone");
|
||||
@@ -105,12 +105,12 @@ public class TestElementCollectionBasicMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("update ecm_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecm_person_phone_numbers where ecm_person_id=?");
|
||||
assertThat(sql.get(2)).contains("insert into ecm_person_phone_numbers (ecm_person_id,type,number) values (?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update ecm_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecm_person_phone_numbers where ecm_person_id=?");
|
||||
@@ -139,11 +139,11 @@ public class TestElementCollectionBasicMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("delete from ecm_person_phone_numbers where ecm_person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecm_person_phone_numbers (ecm_person_id,type,number) values (?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("delete from ecm_person_phone_numbers where ecm_person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecm_person_phone_numbers (ecm_person_id,type,number) values (?,?,?)");
|
||||
|
||||
+2
-1
@@ -23,9 +23,10 @@ public class TestElementCollectionBasicMapAsLob extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ecmc_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecmc_person_phone");
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ecmc_person");
|
||||
|
||||
+8
-7
@@ -1,5 +1,6 @@
|
||||
package org.tests.model.elementcollection;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
@@ -10,7 +11,7 @@ import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestElementCollectionBasicMapCache {
|
||||
public class TestElementCollectionBasicMapCache extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
@@ -44,9 +45,9 @@ public class TestElementCollectionBasicMapCache {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
}
|
||||
else {
|
||||
assertThat(sql).hasSize(6);
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
}
|
||||
|
||||
@@ -72,9 +73,9 @@ public class TestElementCollectionBasicMapCache {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2); // cache hit
|
||||
}
|
||||
else {
|
||||
assertThat(sql).hasSize(4); // cache hit
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3); // cache hit
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ public class TestElementCollectionBasicSet extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ecs_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecs_person_phone");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ecs_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecs_person_phone");
|
||||
@@ -103,12 +103,12 @@ public class TestElementCollectionBasicSet extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("update ecs_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecs_person_phone where ecs_person_id=?");
|
||||
assertThat(sql.get(2)).contains("insert into ecs_person_phone (ecs_person_id,phone) values (?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update ecs_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecs_person_phone where ecs_person_id=?");
|
||||
@@ -137,11 +137,11 @@ public class TestElementCollectionBasicSet extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("delete from ecs_person_phone where ecs_person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecs_person_phone (ecs_person_id,phone) values (?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("delete from ecs_person_phone where ecs_person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecs_person_phone (ecs_person_id,phone) values (?,?)");
|
||||
|
||||
+9
-9
@@ -23,11 +23,11 @@ public class TestElementCollectionEmbeddedList extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ecbl_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ecbl_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers");
|
||||
@@ -103,12 +103,12 @@ public class TestElementCollectionEmbeddedList extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("update ecbl_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(2)).contains("insert into ecbl_person_phone_numbers (person_id,country_code,area,number) values (?,?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update ecbl_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
@@ -137,11 +137,11 @@ public class TestElementCollectionEmbeddedList extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers (person_id,country_code,area,number) values (?,?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers (person_id,country_code,area,number) values (?,?,?,?)");
|
||||
|
||||
+4
-4
@@ -48,11 +48,11 @@ public class TestElementCollectionEmbeddedListCache extends BaseTestCase {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2); // update of collection only
|
||||
assertThat(sql).hasSize(4); // update of collection only
|
||||
assertThat(sql.get(0)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers (person_id,country_code,area,number) values (?,?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3); // update of collection only
|
||||
assertThat(sql.get(0)).contains("delete from ecbl_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbl_person_phone_numbers (person_id,country_code,area,number) values (?,?,?,?)");
|
||||
@@ -76,7 +76,7 @@ public class TestElementCollectionEmbeddedListCache extends BaseTestCase {
|
||||
Ebean.save(three);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(4);
|
||||
|
||||
EcblPerson four = Ebean.find(EcblPerson.class)
|
||||
.setId(person.getId())
|
||||
|
||||
+9
-9
@@ -24,11 +24,11 @@ public class TestElementCollectionEmbeddedMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("insert into ecbm_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into ecbm_person");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers");
|
||||
@@ -96,12 +96,12 @@ public class TestElementCollectionEmbeddedMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("update ecbm_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(2)).contains("insert into ecbm_person_phone_numbers (person_id,mkey,country_code,area,number)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 3, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update ecbm_person set name=?, version=? where id=? and version=?");
|
||||
assertThat(sql.get(1)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
@@ -130,11 +130,11 @@ public class TestElementCollectionEmbeddedMap extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql).hasSize(6);
|
||||
assertThat(sql.get(0)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers (person_id,mkey,country_code,area,number) values (?,?,?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 5);
|
||||
} else {
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers (person_id,mkey,country_code,area,number) values (?,?,?,?,?)");
|
||||
|
||||
+4
-4
@@ -49,11 +49,11 @@ public class TestElementCollectionEmbeddedMapCache extends BaseTestCase {
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(2); // update of collection only
|
||||
assertThat(sql).hasSize(4); // update of collection only
|
||||
assertThat(sql.get(0)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers (person_id,mkey,country_code,area,number) values (?,?,?,?,?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 2, 3);
|
||||
} else {
|
||||
assertThat(sql).hasSize(3); // update of collection only
|
||||
assertThat(sql.get(0)).contains("delete from ecbm_person_phone_numbers where person_id=?");
|
||||
assertThat(sql.get(1)).contains("insert into ecbm_person_phone_numbers (person_id,mkey,country_code,area,number) values (?,?,?,?,?)");
|
||||
@@ -77,7 +77,7 @@ public class TestElementCollectionEmbeddedMapCache extends BaseTestCase {
|
||||
Ebean.save(three);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql).hasSize(4);
|
||||
|
||||
EcbmPerson four = Ebean.find(EcbmPerson.class)
|
||||
.setId(person.getId())
|
||||
|
||||
@@ -2,6 +2,9 @@ package org.tests.model.onetoone;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -12,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class TestOneToOneOrphanRemove extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.SQLSERVER)
|
||||
public void base() {
|
||||
|
||||
OtoCust jack = new OtoCust("Jack");
|
||||
|
||||
@@ -38,21 +38,21 @@ public class TestOneToManyJoinTable extends BaseTestCase {
|
||||
|
||||
List<String> sql = LoggedSqlCollector.current();
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("insert into troop_monkey (troop_pid, monkey_mid) values (?, ?)");
|
||||
}
|
||||
else {
|
||||
assertSqlBind(sql, 1, 2);
|
||||
|
||||
} else {
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("insert into troop_monkey (troop_pid, monkey_mid) values (?, ?)");
|
||||
assertThat(sql.get(1)).contains("insert into troop_monkey (troop_pid, monkey_mid) values (?, ?)");
|
||||
}
|
||||
|
||||
int intersectionRows = Ebean.createSqlQuery("select count(*) as total from troop_monkey where troop_pid = ?")
|
||||
long intersectionRows = Ebean.createSqlQuery("select count(*) as total from troop_monkey where troop_pid = ?")
|
||||
.setParameter(1, troop.getPid())
|
||||
.findOne()
|
||||
.getInteger("total");
|
||||
.findSingleLong();
|
||||
|
||||
assertThat(intersectionRows).isEqualTo(2);
|
||||
assertThat(intersectionRows).isEqualTo(2L);
|
||||
|
||||
LoggedSqlCollector.current();
|
||||
JtTroop fetchTroop = Ebean.find(JtTroop.class)
|
||||
@@ -97,12 +97,14 @@ public class TestOneToManyJoinTable extends BaseTestCase {
|
||||
//Collections.sort(sql);
|
||||
|
||||
if (isPersistBatchOnCascade()) {
|
||||
assertThat(sql).hasSize(8);
|
||||
assertThat(sql).hasSize(13);
|
||||
assertThat(sql.get(0)).contains("insert into trainer ");
|
||||
assertThat(sql.get(1)).contains("insert into monkey ");
|
||||
assertSqlBind(sql, 2, 4);
|
||||
assertThat(sql.get(5)).contains("update monkey set name=?, food_preference=?, version=? where mid=? and version=?");
|
||||
assertThat(sql.get(6)).contains("-- bind(");
|
||||
assertThat(sql.get(7)).contains("insert into trainer_monkey ");
|
||||
assertSqlBind(sql, 8, 12);
|
||||
|
||||
} else {
|
||||
assertThat(sql).hasSize(10);
|
||||
|
||||
@@ -36,12 +36,14 @@ public class TestOneToManyJoinTableInheritance extends BaseTestCase {
|
||||
|
||||
assertThat(sql).hasSize(11);
|
||||
assertThat(sql.get(0)).contains("insert into class_super ");
|
||||
assertThat(sql.get(2)).contains("insert into monkey ");
|
||||
assertThat(sql.get(2)).contains("insert into monkey ");
|
||||
assertThat(sql.get(5)).contains("insert into class_super_monkey ");
|
||||
assertThat(sql.get(6)).contains("insert into class_super ");
|
||||
assertThat(sql.get(8)).contains("insert into monkey ");
|
||||
assertThat(sql.get(10)).contains("insert into class_super_monkey ");
|
||||
assertThat(sql.get(1)).contains("-- bind(ClassA)");
|
||||
assertThat(sql.get(2)).contains("-- bind(ClassB)");
|
||||
assertThat(sql.get(3)).contains("insert into monkey ");
|
||||
assertThat(sql.get(4)).contains("-- bind(Sim");
|
||||
assertThat(sql.get(5)).contains("-- bind(Tim");
|
||||
assertThat(sql.get(6)).contains("-- bind(Uim");
|
||||
assertThat(sql.get(7)).contains("insert into class_super_monkey (class_super_sid, monkey_mid) values (?, ?)");
|
||||
assertSqlBind(sql, 8, 10);
|
||||
|
||||
ClassA dbA = Ebean.find(ClassA.class, 1);
|
||||
ClassB dbB = Ebean.find(ClassB.class, 2);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user