mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
52
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0544fa7ab4 | ||
|
|
51eed9bfe4 | ||
|
|
32ce1f1d59 | ||
|
|
f445c118a0 | ||
|
|
a8ff918bb3 | ||
|
|
729aeae0d7 | ||
|
|
17a9341287 | ||
|
|
c863014fec | ||
|
|
8170db4101 | ||
|
|
434a5117a2 | ||
|
|
85ed8cd784 | ||
|
|
9b70900267 | ||
|
|
0e33d58bb2 | ||
|
|
9d9d13060c | ||
|
|
e071eecd59 | ||
|
|
bc8e254a65 | ||
|
|
e0e369904c | ||
|
|
bd85ba17a1 | ||
|
|
8801b8d8ca | ||
|
|
ebd6c535ab | ||
|
|
5c771a7219 | ||
|
|
eb6f722385 | ||
|
|
cef4f59b2c | ||
|
|
67352ab3b2 | ||
|
|
4a21395cda | ||
|
|
fcd7f8b6cf | ||
|
|
4565719728 | ||
|
|
cbdf5609b2 | ||
|
|
f97359502b | ||
|
|
ffaf00c064 | ||
|
|
f6f9511d2a | ||
|
|
5e94c26094 | ||
|
|
5aaed4e12b | ||
|
|
c29a57b5ec | ||
|
|
998b8cc192 | ||
|
|
9c1d930fb8 | ||
|
|
d6d7537a9c | ||
|
|
92e83c49d9 | ||
|
|
d758590da4 | ||
|
|
21a5efa9b9 | ||
|
|
55a2cb12bb | ||
|
|
293700acc0 | ||
|
|
8980a3b6fd | ||
|
|
72efc5d7d6 | ||
|
|
84589fcce6 | ||
|
|
a0e44aedf3 | ||
|
|
41102aca35 | ||
|
|
548cea432e | ||
|
|
592cb37693 | ||
|
|
f2178bf0a6 | ||
|
|
5cae425b09 | ||
|
|
94b78f1c2d |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.3.1</version>
|
||||
<version>12.3.4</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-12.3.1</tag>
|
||||
<tag>ebean-12.3.4</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -87,7 +87,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>6.11</version>
|
||||
<version>6.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -99,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>4.9.1</version>
|
||||
<version>5.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -248,6 +248,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mariadb.jdbc</groupId>
|
||||
<artifactId>mariadb-java-client</artifactId>
|
||||
<version>2.6.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sap.cloud.db.jdbc</groupId>
|
||||
<artifactId>ngdbc</artifactId>
|
||||
@@ -292,7 +299,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.2.4</version>
|
||||
<version>12.3.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
@@ -310,7 +317,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<version>3.0.0-M4</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
|
||||
@@ -31,15 +31,18 @@ public interface BackgroundExecutor {
|
||||
* Execute a task periodically with a fixed delay between each execution.
|
||||
* <p>
|
||||
* For example, execute a runnable every minute.
|
||||
* </p>
|
||||
* <p>
|
||||
* The delay is the time between executions no matter how long the task took.
|
||||
* That is, this method has the same behaviour characteristics as
|
||||
* {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)}
|
||||
* </p>
|
||||
*/
|
||||
void executePeriodically(Runnable r, long delay, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Execute a task periodically additionally with an initial delay different from delay.
|
||||
*/
|
||||
void executePeriodically(Runnable r, long initialDelay, long delay, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Schedules a Runnable for one-shot action that becomes enabled after the given delay.
|
||||
*
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Ebean will be Deprecated - please migrate to use DB.
|
||||
* Deprecated - please migrate to use <code>io.ebean.DB</code>.
|
||||
* <p>
|
||||
* Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
|
||||
* <p>
|
||||
@@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <p>
|
||||
* The preference is to use DB and Database rather than Ebean and EbeanServer.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ebean {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to <code>io.ebean.Database</code>.
|
||||
* Provides the API for fetching and saving beans to a particular Database.
|
||||
* <p>
|
||||
* Effectively this is an alias for {@link Database} which is now the new
|
||||
@@ -8,6 +9,7 @@ package io.ebean;
|
||||
* <p>
|
||||
* The preference is to use DB and Database rather than Ebean and EbeanServer.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface EbeanServer extends Database {
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to DatabaseFactory.
|
||||
* <p>
|
||||
* Creates EbeanServer instances.
|
||||
* <p>
|
||||
* This uses either a ServerConfig or properties in the ebean.properties file to
|
||||
@@ -28,6 +30,7 @@ import java.util.ServiceLoader;
|
||||
* convenient way of using the 'default/primary' EbeanServer.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
public class EbeanServerFactory {
|
||||
|
||||
|
||||
|
||||
@@ -70,30 +70,40 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> order(String orderByClause);
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
* <p>
|
||||
* This follows SQL syntax using commas between each property with the
|
||||
* optional asc and desc keywords representing ascending and descending order
|
||||
* respectively.
|
||||
*/
|
||||
ExpressionList<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is the same as <code>orderBy()</code>
|
||||
*/
|
||||
OrderBy<T> order();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to order().
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* <p>
|
||||
* This is the same as <code>order()</code>
|
||||
*/
|
||||
@Deprecated
|
||||
OrderBy<T> orderBy();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to {@link #order(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to {@link #order(String)}
|
||||
* Deprecated migrate to {@link #orderBy(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> setOrderBy(String orderBy);
|
||||
@@ -1241,26 +1251,37 @@ public interface ExpressionList<T> {
|
||||
/**
|
||||
* Add raw expression with a single parameter.
|
||||
* <p>
|
||||
* The raw expression should contain a single ? at the location of the
|
||||
* parameter.
|
||||
* The raw expression should contain a single ? or ?1
|
||||
* at the location of the parameter. We use ?1 when binding a
|
||||
* collection for an IN expression.
|
||||
* </p>
|
||||
* <p>
|
||||
* <p>>
|
||||
* When properties in the clause are fully qualified as table-column names
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
* <p>
|
||||
* <h4>Example:</h4>
|
||||
* <h4>Examples:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use a database function
|
||||
* raw("add_days(orderDate, 10) < ?", someDate)
|
||||
*
|
||||
* raw("name like ?", "Rob%")
|
||||
*
|
||||
* raw("name in (?1)", asList("Rob", "Fiona", "Jack"))
|
||||
*
|
||||
* raw("name = any(?)", asList("Rob", "Fiona", "Jack"))
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Subquery example:</h4>
|
||||
* <h4>Subquery examples:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Bind collection using ?1
|
||||
* .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
|
||||
*
|
||||
* // Using Postgres ANY expression
|
||||
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1270,14 +1291,25 @@ public interface ExpressionList<T> {
|
||||
/**
|
||||
* Add raw expression with an array of parameters.
|
||||
* <p>
|
||||
* The raw expression should contain the same number of ? as there are
|
||||
* parameters.
|
||||
* </p>
|
||||
* The raw expression should contain the same number of ? or ?1, ?2 ... bind parameters
|
||||
* as there are values. We use ?1, ?2 etc when binding a collection for an IN expression.
|
||||
* <p>
|
||||
* When properties in the clause are fully qualified as table-column names
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
*
|
||||
* <h4>Examples:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* raw("unitPrice > ? and product.id > ?", 2, 3)
|
||||
*
|
||||
* raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)",
|
||||
* Order.Status.APPROVED,
|
||||
* new Timestamp(System.currentTimeMillis()),
|
||||
* "Rob")
|
||||
*
|
||||
* }</pre></pre>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw, Object... values);
|
||||
|
||||
|
||||
@@ -92,11 +92,9 @@ public interface ExtendedServer {
|
||||
* {@link #findEachWhile(Query, Predicate, Transaction)} is preferred
|
||||
* to findIterate(). The reason is that those methods automatically take care of
|
||||
* closing the queryIterator (and the underlying jdbc statement and resultSet).
|
||||
* </p>
|
||||
* <p>
|
||||
* This is similar to findEach in that not all the result beans need to be held
|
||||
* in memory at the same time and as such is good for processing large queries.
|
||||
* </p>
|
||||
*
|
||||
* @see Query#findIterate()
|
||||
* @see Query#findEach(Consumer)
|
||||
@@ -106,7 +104,10 @@ public interface ExtendedServer {
|
||||
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the query result as a Stream using a single persistence context.
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this can support very large queries iterating any number of results.
|
||||
* To do so internally it can use multiple persistence contexts.
|
||||
* <p>
|
||||
* Note that the stream needs to be closed so use with try with resources.
|
||||
* </p>
|
||||
@@ -115,12 +116,17 @@ public interface ExtendedServer {
|
||||
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the query result as a Stream (with multiple persistence contexts).
|
||||
* Deprecated - migrate to findStream().
|
||||
* <p>
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this can support very large queries iterating any number of results.
|
||||
* To do so internally it can use multiple persistence contexts.
|
||||
* <p>
|
||||
* Note that the stream needs to be closed so use with try with resources.
|
||||
* </p>
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
<T> Stream<T> findLargeStream(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
|
||||
@@ -711,9 +711,9 @@ public interface Query<T> {
|
||||
/**
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this will hold all resulting beans in memory using a single
|
||||
* persistence context. Use findLargeStream() for queries that expect to
|
||||
* return a large number of results.
|
||||
* Note that this can support very large queries iterating
|
||||
* any number of results. To do so internally it can use
|
||||
* multiple persistence contexts.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -731,6 +731,8 @@ public interface Query<T> {
|
||||
Stream<T> findStream();
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to findStream.
|
||||
* <p>
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this uses multiple persistence contexts such that we can use
|
||||
@@ -749,6 +751,7 @@ public interface Query<T> {
|
||||
* }</pre>
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated
|
||||
Stream<T> findLargeStream();
|
||||
|
||||
/**
|
||||
@@ -1352,9 +1355,13 @@ public interface Query<T> {
|
||||
Query<T> having(Expression addExpressionToHaving);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to {@link #order(String)}
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
* <p>
|
||||
* This follows SQL syntax using commas between each property with the
|
||||
* optional asc and desc keywords representing ascending and descending order
|
||||
* respectively.
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> orderBy(String orderByClause);
|
||||
|
||||
/**
|
||||
@@ -1373,13 +1380,20 @@ public interface Query<T> {
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* <p>
|
||||
* This is the same as <code>orderBy()</code>
|
||||
*/
|
||||
OrderBy<T> order();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to order().
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* <p>
|
||||
* This is the same as <code>order()</code>
|
||||
*/
|
||||
@Deprecated
|
||||
OrderBy<T> orderBy();
|
||||
|
||||
/**
|
||||
@@ -1388,9 +1402,8 @@ public interface Query<T> {
|
||||
Query<T> setOrder(OrderBy<T> orderBy);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to {@link #setOrder(OrderBy)}
|
||||
* Set an OrderBy object to replace any existing OrderBy clause.
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> setOrderBy(OrderBy<T> orderBy);
|
||||
|
||||
/**
|
||||
|
||||
@@ -224,12 +224,49 @@ public interface SqlQuery extends Serializable {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* When binding a collection of values into a IN expression we should use
|
||||
* indexed parameters like ?1, ?2, ?3 etc rather than just ?.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select c.id, c.name from customer c where c.name in (?1)";
|
||||
*
|
||||
* List<SqlRow> rows = DB.sqlQuery(sql)
|
||||
* .setParameter(asList("Rob", "Fiona", "Jack"))
|
||||
* .findList();
|
||||
*
|
||||
*
|
||||
* List<SqlRow> rows = DB.sqlQuery(sql)
|
||||
* .setParameter(1, asList("Rob", "Fiona", "Jack"))
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*
|
||||
* @param value The value to bind
|
||||
*/
|
||||
SqlQuery setParameter(Object value);
|
||||
|
||||
/**
|
||||
* Bind the parameter by its index position (1 based like JDBC).
|
||||
* <p>
|
||||
* When binding a collection of values into a IN expression we should use
|
||||
* indexed parameters like ?1, ?2, ?3 etc rather than just ?.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select c.id, c.name from customer c where c.name in (?1)";
|
||||
*
|
||||
* List<SqlRow> rows = DB.sqlQuery(sql)
|
||||
* .setParameter(asList("Rob", "Fiona", "Jack"))
|
||||
* .findList();
|
||||
*
|
||||
*
|
||||
* List<SqlRow> rows = DB.sqlQuery(sql)
|
||||
* .setParameter(1, asList("Rob", "Fiona", "Jack"))
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*/
|
||||
SqlQuery setParameter(int position, Object value);
|
||||
|
||||
|
||||
@@ -5,18 +5,16 @@ package io.ebean;
|
||||
* <p>
|
||||
* Provides a simple way to execute raw SQL insert update or delete statements
|
||||
* without having to resort to JDBC.
|
||||
* </p>
|
||||
* <p>
|
||||
* Supports the use of positioned or named parameters and can automatically
|
||||
* notify Ebean of the table modified so that Ebean can maintain its cache.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that {@link #setAutoTableMod(boolean)} and
|
||||
* Ebean#externalModification(String, boolean, boolean, boolean)} can be to
|
||||
* notify Ebean of external changes and enable Ebean to maintain it's "L2"
|
||||
* server cache.
|
||||
* </p>
|
||||
*
|
||||
* <h2>Positioned parameter example</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example using 'positioned' parameters
|
||||
@@ -30,6 +28,7 @@ package io.ebean;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Named parameter example</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example using 'named' parameters
|
||||
@@ -45,8 +44,31 @@ package io.ebean;
|
||||
* String msg = "There were " + rows + " rows updated";
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Index parameter examples (e.g. ?1, ?2, ?3 ...)</h2>
|
||||
* <p>
|
||||
* <h3>Example: Using setNextParameter()</h3>
|
||||
* We can use index parameters like ?1, ?2, ?3 etc when binding arrays/collections
|
||||
* of values into an IN expression.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Binding a list of 3 values (9991, 9992, 9993) into an IN expression
|
||||
*
|
||||
* DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
|
||||
* .setParameter(1, "Foo")
|
||||
* .setParameter(2, asList(9991, 9992, 9993))
|
||||
* .execute();
|
||||
*
|
||||
* // note this effectively is the same as
|
||||
*
|
||||
* DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
|
||||
* .setParameter("Foo")
|
||||
* .setParameter(asList(9991, 9992, 9993))
|
||||
* .execute();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Example: Using setParameter()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
|
||||
@@ -56,19 +78,19 @@ package io.ebean;
|
||||
* try (Transaction txn = DB.beginTransaction()) {
|
||||
* txn.setBatchMode(true);
|
||||
*
|
||||
* insert.setNextParameter(10000);
|
||||
* insert.setNextParameter("hello");
|
||||
* insert.setNextParameter("rob");
|
||||
* insert.setParameter(10000);
|
||||
* insert.setParameter("hello");
|
||||
* insert.setParameter("rob");
|
||||
* insert.execute();
|
||||
*
|
||||
* insert.setNextParameter(10001);
|
||||
* insert.setNextParameter("goodbye");
|
||||
* insert.setNextParameter("rob");
|
||||
* insert.setParameter(10001);
|
||||
* insert.setParameter("goodbye");
|
||||
* insert.setParameter("rob");
|
||||
* insert.execute();
|
||||
*
|
||||
* insert.setNextParameter(10002);
|
||||
* insert.setNextParameter("chow");
|
||||
* insert.setNextParameter("bob");
|
||||
* insert.setParameter(10002);
|
||||
* insert.setParameter("chow");
|
||||
* insert.setParameter("bob");
|
||||
* insert.execute();
|
||||
*
|
||||
* txn.commit();
|
||||
@@ -81,19 +103,19 @@ package io.ebean;
|
||||
*
|
||||
* try (Transaction txn = DB.beginTransaction()) {
|
||||
*
|
||||
* insert.setNextParameter(10000);
|
||||
* insert.setNextParameter("hello");
|
||||
* insert.setNextParameter("rob");
|
||||
* insert.setParameter(10000);
|
||||
* insert.setParameter("hello");
|
||||
* insert.setParameter("rob");
|
||||
* insert.addBatch();
|
||||
*
|
||||
* insert.setNextParameter(10001);
|
||||
* insert.setNextParameter("goodbye");
|
||||
* insert.setNextParameter("rob");
|
||||
* insert.setParameter(10001);
|
||||
* insert.setParameter("goodbye");
|
||||
* insert.setParameter("rob");
|
||||
* insert.addBatch();
|
||||
*
|
||||
* insert.setNextParameter(10002);
|
||||
* insert.setNextParameter("chow");
|
||||
* insert.setNextParameter("bob");
|
||||
* insert.setParameter(10002);
|
||||
* insert.setParameter("chow");
|
||||
* insert.setParameter("bob");
|
||||
* insert.addBatch();
|
||||
*
|
||||
* int[] rows = insert.executeBatch();
|
||||
|
||||
@@ -61,6 +61,22 @@ public interface PersistenceContext {
|
||||
*/
|
||||
int size(Class<?> rootType);
|
||||
|
||||
/**
|
||||
* Return a copy of the Persistence context to use for large query iteration.
|
||||
*/
|
||||
PersistenceContext forIterate();
|
||||
|
||||
/**
|
||||
* Return a new Persistence context during iteration of large query result.
|
||||
*/
|
||||
PersistenceContext forIterateReset();
|
||||
|
||||
/**
|
||||
* Return true if the persistence context has grown and hit the 'reset limit'
|
||||
* during large query iteration.
|
||||
*/
|
||||
boolean resetLimit();
|
||||
|
||||
/**
|
||||
* Wrapper on a bean to also indicate if a bean has been deleted.
|
||||
* <p>
|
||||
|
||||
@@ -18,4 +18,9 @@ public @interface ModuleInfo {
|
||||
* The db name prefix is added to entity classes for non default databases.
|
||||
*/
|
||||
String[] entities() default {};
|
||||
|
||||
/**
|
||||
* Other classes like Attribute Converters.
|
||||
*/
|
||||
String[] other() default {};
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to <code>io.ebean.DatabaseConfig</code>.
|
||||
*
|
||||
* The configuration used for creating a Database.
|
||||
* <p>
|
||||
* Used to programmatically construct a Database and optionally register it
|
||||
@@ -80,6 +82,7 @@ import java.util.ServiceLoader;
|
||||
* @author rbygrave
|
||||
* @see DatabaseFactory
|
||||
*/
|
||||
@Deprecated
|
||||
public class ServerConfig {
|
||||
|
||||
/**
|
||||
|
||||
@@ -43,11 +43,8 @@ public abstract class AbstractDbEncrypt implements DbEncrypt {
|
||||
public DbEncryptFunction getDbEncryptFunction(int jdbcType) {
|
||||
switch (jdbcType) {
|
||||
case Types.VARCHAR:
|
||||
return varcharEncryptFunction;
|
||||
case Types.CLOB:
|
||||
return varcharEncryptFunction;
|
||||
case Types.CHAR:
|
||||
return varcharEncryptFunction;
|
||||
case Types.LONGVARCHAR:
|
||||
return varcharEncryptFunction;
|
||||
|
||||
|
||||
@@ -7,30 +7,18 @@ package io.ebean.config.dbplatform;
|
||||
* As an alternative to using DB encryption you can encrypt/decrypt in java via
|
||||
* a special ScalarType but this has the limitation that you can't include that
|
||||
* property in query where clauses.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface DbEncrypt {
|
||||
|
||||
// /**
|
||||
// * Return the SQL for decrypting a column returning a VARCHAR.
|
||||
// */
|
||||
// String getDecryptSql(String columnWithTableAlias);
|
||||
//
|
||||
// /**
|
||||
// * Return the DB function with bind variables used to encrypt a VARCHAR
|
||||
// * value.
|
||||
// */
|
||||
// String getEncryptBindSql();
|
||||
|
||||
/**
|
||||
* Return the DB encrypt function for the given JDBC type.
|
||||
*/
|
||||
DbEncryptFunction getDbEncryptFunction(int jdbcType);
|
||||
|
||||
/**
|
||||
* Return the DB type that encrypted Strings are stored in.
|
||||
* <p>
|
||||
* This is VARCHAR for MySql and VARBINARY for most others.
|
||||
* </p>
|
||||
*/
|
||||
int getEncryptDbType();
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import io.ebean.config.dbplatform.DbStandardHistorySupport;
|
||||
|
||||
/**
|
||||
* History support for MariaDB.
|
||||
*/
|
||||
public class MariaDbHistorySupport extends DbStandardHistorySupport {
|
||||
|
||||
/**
|
||||
* Return the ' as of timestamp ?' clause appended after the table name.
|
||||
*/
|
||||
@Override
|
||||
public String getAsOfViewSuffix(String asOfViewSuffix) {
|
||||
return " for system_time as of ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
|
||||
return " for system_time between ? and ?";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL Server specific effective start column.
|
||||
*/
|
||||
@Override
|
||||
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "From";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the SQL Server specific effective end column.
|
||||
*/
|
||||
@Override
|
||||
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "To";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.mysql.BaseMySqlPlatform;
|
||||
|
||||
/**
|
||||
* MariaDB platform.
|
||||
*/
|
||||
public class MariaDbPlatform extends BaseMySqlPlatform {
|
||||
|
||||
public MariaDbPlatform() {
|
||||
super();
|
||||
this.platform = Platform.MARIADB;
|
||||
this.historySupport = new MariaDbHistorySupport();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package io.ebean.config.dbplatform.mysql;
|
||||
|
||||
import io.ebean.Query;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Base platform for both MySql and MariaDB.
|
||||
*/
|
||||
public abstract class BaseMySqlPlatform extends DatabasePlatform {
|
||||
|
||||
public BaseMySqlPlatform() {
|
||||
super();
|
||||
this.useExtraTransactionOnIterateSecondaryQueries = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.supportsSavepointId = false;
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
this.historySupport = new MySqlHistorySupport();
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
this.dbIdentity.setSupportsSequence(false);
|
||||
|
||||
this.dbDefaultValue.setNow("now(6)"); // must have same precision as TIMESTAMP
|
||||
this.dbDefaultValue.setFalse("0");
|
||||
this.dbDefaultValue.setTrue("1");
|
||||
|
||||
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("1205")
|
||||
.addDuplicateKey("1062", "1169")
|
||||
.addDataIntegrity("630", "839", "840", "893", "1215", "1216", "1217", "1364", "1451", "1452", "1557")
|
||||
.build();
|
||||
|
||||
this.openQuote = "`";
|
||||
this.closeQuote = "`";
|
||||
// use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not.
|
||||
this.likeClauseRaw = "like ? escape''";
|
||||
this.likeClauseEscaped = "like ? escape'|'";
|
||||
|
||||
this.forwardOnlyHintOnFindIterate = true;
|
||||
this.booleanDbType = Types.BIT;
|
||||
|
||||
dbTypeMap.put(DbType.BIT, new DbPlatformType("tinyint(1)"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("tinyint(1)"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime(6)"));
|
||||
dbTypeMap.put(DbType.CLOB, new MySqlClob());
|
||||
dbTypeMap.put(DbType.BLOB, new MySqlBlob());
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("binary", 255));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
|
||||
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbPlatformType("json", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
|
||||
// NOWAIT and SKIP LOCKED currently not supported with MySQL
|
||||
return sql + " for update";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
|
||||
public class MySql55Platform extends MySqlPlatform {
|
||||
public class MySql55Platform extends BaseMySqlPlatform {
|
||||
|
||||
public MySql55Platform() {
|
||||
super();
|
||||
|
||||
@@ -1,77 +1,15 @@
|
||||
package io.ebean.config.dbplatform.mysql;
|
||||
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* MySQL specific platform.
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>supportsGetGeneratedKeys = true</li>
|
||||
* <li>Uses LIMIT OFFSET clause</li>
|
||||
* <li>Uses ` for quoted identifiers</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public class MySqlPlatform extends DatabasePlatform {
|
||||
public class MySqlPlatform extends BaseMySqlPlatform {
|
||||
|
||||
public MySqlPlatform() {
|
||||
super();
|
||||
this.platform = Platform.MYSQL;
|
||||
this.useExtraTransactionOnIterateSecondaryQueries = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.supportsSavepointId = false;
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
this.historySupport = new MySqlHistorySupport();
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
this.dbIdentity.setSupportsSequence(false);
|
||||
|
||||
this.dbDefaultValue.setNow("now(6)"); // must have same precision as TIMESTAMP
|
||||
this.dbDefaultValue.setFalse("0");
|
||||
this.dbDefaultValue.setTrue("1");
|
||||
|
||||
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("1205")
|
||||
.addDuplicateKey("1062", "1169")
|
||||
.addDataIntegrity("630", "839", "840", "893", "1215", "1216", "1217", "1364", "1451", "1452", "1557")
|
||||
.build();
|
||||
|
||||
this.openQuote = "`";
|
||||
this.closeQuote = "`";
|
||||
// use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not.
|
||||
this.likeClauseRaw = "like ? escape''";
|
||||
this.likeClauseEscaped = "like ? escape'|'";
|
||||
|
||||
this.forwardOnlyHintOnFindIterate = true;
|
||||
this.booleanDbType = Types.BIT;
|
||||
|
||||
dbTypeMap.put(DbType.BIT, new DbPlatformType("tinyint(1)"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("tinyint(1)"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime(6)"));
|
||||
dbTypeMap.put(DbType.CLOB, new MySqlClob());
|
||||
dbTypeMap.put(DbType.BLOB, new MySqlBlob());
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("binary", 255));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
|
||||
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbPlatformType("json", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
|
||||
// NOWAIT and SKIP LOCKED currently not supported with MySQL
|
||||
return sql + " for update";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
/**
|
||||
* Set the query to be a delete query.
|
||||
*/
|
||||
void setupForDeleteOrUpdate(boolean deleteRequest);
|
||||
void setupForDeleteOrUpdate();
|
||||
|
||||
/**
|
||||
* Set the query to be delete by ids due to cascading delete.
|
||||
@@ -788,7 +788,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
/**
|
||||
* Set to true when we only include the Id property if it is explicitly included in the select().
|
||||
*/
|
||||
void setManualId(boolean manualId);
|
||||
void setManualId();
|
||||
|
||||
/**
|
||||
* Set default select clauses where none have been explicitly defined.
|
||||
|
||||
@@ -313,4 +313,9 @@ public interface SpiTransaction extends Transaction {
|
||||
* Return true when nested transactions should create Savepoints.
|
||||
*/
|
||||
boolean isNestedUseSavepoint();
|
||||
|
||||
/**
|
||||
* Return true if explicitly set to skip cache (ignores skipOnWrite).
|
||||
*/
|
||||
boolean isSkipCacheExplicit();
|
||||
}
|
||||
|
||||
@@ -158,6 +158,11 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
transaction.setSkipCache(skipCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCacheExplicit() {
|
||||
return transaction.isSkipCacheExplicit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
return transaction.isSkipCache();
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.ebean.config.dbplatform.db2.DB2Platform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mariadb.MariaDbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
@@ -820,6 +821,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
return new Postgres9Platform();
|
||||
case POSTGRES:
|
||||
return new PostgresPlatform();
|
||||
case MARIADB:
|
||||
return new MariaDbPlatform();
|
||||
case MYSQL55:
|
||||
return new MySql55Platform();
|
||||
case MYSQL:
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
|
||||
/**
|
||||
* MariaDB platform DDL.
|
||||
*/
|
||||
public class MariaDbDdl extends MySqlDdl {
|
||||
|
||||
public MariaDbDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.historyDdl = new MariaDbHistoryDdl();
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.migration.AddHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* History DDL for MariaDB.
|
||||
*/
|
||||
public class MariaDbHistoryDdl implements PlatformHistoryDdl {
|
||||
|
||||
private String systemPeriodStart;
|
||||
private String systemPeriodEnd;
|
||||
private PlatformDdl platformDdl;
|
||||
|
||||
@Override
|
||||
public void configure(ServerConfig serverConfig, PlatformDdl platformDdl) {
|
||||
this.systemPeriodStart = serverConfig.getAsOfSysPeriod() + "From";
|
||||
this.systemPeriodEnd = serverConfig.getAsOfSysPeriod() + "To";
|
||||
this.platformDdl = platformDdl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createWithHistory(DdlWrite writer, MTable table) throws IOException {
|
||||
String baseTable = table.getName();
|
||||
enableSystemVersioning(writer, baseTable);
|
||||
}
|
||||
|
||||
String getHistoryTable(String baseTable) {
|
||||
String historyTable = baseTable + "_history";
|
||||
if (baseTable.startsWith("[")) {
|
||||
historyTable = historyTable.replace("]", "") + "]";
|
||||
}
|
||||
if (historyTable.indexOf('.') == -1) {
|
||||
// history must contain schema, add the default schema if none was specified
|
||||
historyTable = "dbo." + historyTable;
|
||||
}
|
||||
return historyTable;
|
||||
}
|
||||
|
||||
private void enableSystemVersioning(DdlWrite writer, String baseTable) throws IOException {
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
|
||||
final String systemTime = String.format("system_time(%s, %s),", systemPeriodStart, systemPeriodEnd);
|
||||
apply.append("alter table ").append(baseTable).newLine()
|
||||
.append(" add column ").append(systemPeriodStart).append(" timestamp(6) generated always as row start,").newLine()
|
||||
.append(" add column ").append(systemPeriodEnd).append(" timestamp(6) generated always as row end,").newLine()
|
||||
.append(" add period for ").append(systemTime).newLine()
|
||||
.append(" add system versioning;").newLine();
|
||||
|
||||
DdlBuffer drop = writer.dropAll();
|
||||
//drop.append("IF OBJECT_ID('").append(baseTable).append("', 'U') IS NOT NULL alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
|
||||
//drop.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException {
|
||||
String baseTable = dropHistoryTable.getBaseTable();
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
apply.append("-- dropping history support for ").append(baseTable).endOfStatement();
|
||||
// drop default constraints
|
||||
|
||||
apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodStart, DdlHelp.DROP_DEFAULT)).endOfStatement();
|
||||
apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodEnd, DdlHelp.DROP_DEFAULT)).endOfStatement();
|
||||
// switch of versioning & period
|
||||
apply.append("alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
|
||||
apply.append("alter table ").append(baseTable).append(" drop period for system_time").endOfStatement();
|
||||
// now drop tables & columns
|
||||
apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodStart).endOfStatement();
|
||||
apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodEnd).endOfStatement();
|
||||
//apply.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement();
|
||||
apply.end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHistoryTable(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException {
|
||||
String baseTable = addHistoryTable.getBaseTable();
|
||||
enableSystemVersioning(writer, baseTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTriggers(DdlWrite writer, HistoryTableUpdate baseTable) throws IOException {
|
||||
// SQL Server 2016 does not need triggers
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
String baseTableName = baseTable.getBaseTable();
|
||||
apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = off (history_table=")
|
||||
.append(getHistoryTable(baseTableName)).append("))").endOfStatement();
|
||||
apply.append("-- history migration goes here").newLine();
|
||||
apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = on (history_table=")
|
||||
.append(getHistoryTable(baseTableName)).append("))").endOfStatement();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import java.util.Objects;
|
||||
*/
|
||||
public class MColumn {
|
||||
|
||||
private final String name;
|
||||
private String name;
|
||||
private String type;
|
||||
private String checkConstraint;
|
||||
private String checkConstraintName;
|
||||
@@ -88,7 +88,6 @@ public class MColumn {
|
||||
* Return a copy of this column used for creating the associated draft table.
|
||||
*/
|
||||
public MColumn copyForDraft() {
|
||||
|
||||
MColumn copy = new MColumn(name, type);
|
||||
copy.draftOnly = draftOnly;
|
||||
copy.checkConstraint = checkConstraint;
|
||||
@@ -470,6 +469,14 @@ public class MColumn {
|
||||
this.dbMigrationInfos = dbMigrationInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename the column.
|
||||
*/
|
||||
public MColumn rename(String newName) {
|
||||
this.name = newName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply changes based on the AlterColumn request.
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.ebeaninternal.dbmigration.migration.DropColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.migration.DropTable;
|
||||
import io.ebeaninternal.dbmigration.migration.ForeignKey;
|
||||
import io.ebeaninternal.dbmigration.migration.RenameColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.UniqueConstraint;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -415,6 +416,15 @@ public class MTable {
|
||||
}
|
||||
}
|
||||
|
||||
public void apply(RenameColumn renameColumn) {
|
||||
checkTableName(renameColumn.getTableName());
|
||||
MColumn column = columns.remove(renameColumn.getOldName());
|
||||
if (column == null) {
|
||||
throw new IllegalStateException("Column [" + renameColumn.getOldName() + "] does not exist for RenameColumn change on table [" + renameColumn.getTableName() + "]?");
|
||||
}
|
||||
addColumn(column.rename(renameColumn.getNewName()));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import io.ebeaninternal.dbmigration.migration.DropHistoryTable;
|
||||
import io.ebeaninternal.dbmigration.migration.DropIndex;
|
||||
import io.ebeaninternal.dbmigration.migration.DropTable;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
import io.ebeaninternal.dbmigration.migration.RenameColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.Sql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -163,6 +164,8 @@ public class ModelContainer {
|
||||
applyChange((AddColumn) change);
|
||||
} else if (change instanceof DropColumn) {
|
||||
applyChange((DropColumn) change);
|
||||
} else if (change instanceof RenameColumn) {
|
||||
applyChange((RenameColumn) change);
|
||||
} else if (change instanceof CreateIndex) {
|
||||
applyChange((CreateIndex) change);
|
||||
} else if (change instanceof DropIndex) {
|
||||
@@ -314,6 +317,14 @@ public class ModelContainer {
|
||||
table.apply(dropColumn);
|
||||
}
|
||||
|
||||
protected void applyChange(RenameColumn renameColumn) {
|
||||
MTable table = tables.get(renameColumn.getTableName());
|
||||
if (table == null) {
|
||||
throw new IllegalStateException("Table [" + renameColumn.getTableName() + "] does not exist in model?");
|
||||
}
|
||||
table.apply(renameColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a table (typically from reading EbeanServer meta data).
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebean.config.dbplatform.db2.DB2Platform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mariadb.MariaDbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
@@ -76,11 +77,13 @@ public class DatabasePlatformFactory {
|
||||
* Lookup the platform by name.
|
||||
*/
|
||||
private DatabasePlatform byDatabaseName(String dbName) {
|
||||
|
||||
dbName = dbName.toLowerCase();
|
||||
if (dbName.equals("h2")) {
|
||||
return new H2Platform();
|
||||
}
|
||||
if (dbName.equals("mariadb")) {
|
||||
return new MariaDbPlatform();
|
||||
}
|
||||
if (dbName.equals("mysql")) {
|
||||
return new MySqlPlatform();
|
||||
}
|
||||
@@ -123,7 +126,6 @@ public class DatabasePlatformFactory {
|
||||
if (dbName.equals("hana")) {
|
||||
return new HanaPlatform();
|
||||
}
|
||||
|
||||
throw new RuntimeException("database platform " + dbName + " is not known?");
|
||||
}
|
||||
|
||||
@@ -160,14 +162,16 @@ public class DatabasePlatformFactory {
|
||||
return new OraclePlatform();
|
||||
} else if (dbProductName.contains("microsoft")) {
|
||||
throw new IllegalArgumentException("For SqlServer please explicitly choose either sqlserver16 or sqlserver17 as the platform via ServerConfig.setDatabasePlatformName. Refer to issue #1340 for more details");
|
||||
} else if (dbProductName.contains("mysql")) {
|
||||
return mysqlVersion(majorVersion, minorVersion);
|
||||
} else if (dbProductName.contains("h2")) {
|
||||
return new H2Platform();
|
||||
} else if (dbProductName.contains("hsql database engine")) {
|
||||
return new HsqldbPlatform();
|
||||
} else if (dbProductName.contains("postgres")) {
|
||||
return readPostgres(connection, majorVersion);
|
||||
} else if (dbProductName.contains("mariadb")) {
|
||||
return new MariaDbPlatform();
|
||||
} else if (dbProductName.contains("mysql")) {
|
||||
return mysqlVersion(majorVersion, minorVersion);
|
||||
} else if (dbProductName.contains("nuo")) {
|
||||
return new NuoDbPlatform();
|
||||
} else if (dbProductName.contains("sqlite")) {
|
||||
|
||||
@@ -33,7 +33,6 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
@Override
|
||||
public void execute(Runnable r) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
|
||||
if (map == null) {
|
||||
pool.execute(r);
|
||||
} else {
|
||||
@@ -50,10 +49,14 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
|
||||
@Override
|
||||
public void executePeriodically(Runnable r, long delay, TimeUnit unit) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
executePeriodically(r, delay, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePeriodically(Runnable r, long initialDelay, long delay, TimeUnit unit) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
if (map == null) {
|
||||
schedulePool.scheduleWithFixedDelay(r, delay, delay, unit);
|
||||
schedulePool.scheduleWithFixedDelay(r, initialDelay, delay, unit);
|
||||
} else {
|
||||
schedulePool.scheduleWithFixedDelay(() -> {
|
||||
MDC.setContextMap(map);
|
||||
@@ -62,14 +65,13 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
}, delay, delay, unit);
|
||||
}, initialDelay, delay, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> schedule(Runnable r, long delay, TimeUnit unit) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
|
||||
if (map == null) {
|
||||
return schedulePool.schedule(r, delay, unit);
|
||||
} else {
|
||||
@@ -87,7 +89,6 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
@Override
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> c, long delay, TimeUnit unit) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
|
||||
if (map == null) {
|
||||
return schedulePool.schedule(c, delay, unit);
|
||||
} else {
|
||||
|
||||
@@ -1507,19 +1507,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> Stream<T> findLargeStream(Query<T> query, Transaction transaction) {
|
||||
return findStreamWithSingleContext(false, query, transaction);
|
||||
return findStream(query, transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Stream<T> findStream(Query<T> query, Transaction transaction) {
|
||||
return findStreamWithSingleContext(true, query, transaction);
|
||||
}
|
||||
|
||||
private <T> Stream<T> findStreamWithSingleContext(boolean singleContext, Query<T> query, Transaction transaction) {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
|
||||
if (singleContext) {
|
||||
request.setIterateSingleContext();
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return toStream(request.findIterate());
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
SpiQuery<?> ormQuery = query.getOrmQuery();
|
||||
if (ormQuery != null) {
|
||||
ormQuery.setType(type);
|
||||
ormQuery.setManualId(true);
|
||||
ormQuery.setManualId();
|
||||
|
||||
// execute the underlying ORM query returning the ResultSet
|
||||
SpiResultSet result = server.findResultSet(ormQuery, trans);
|
||||
@@ -102,7 +102,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
@SuppressWarnings("unchecked")
|
||||
public T readNextBean() throws SQLException {
|
||||
dataReader.resetColumnPosition();
|
||||
return (T)plan.readRow(dataReader);
|
||||
return (T) plan.readRow(dataReader);
|
||||
}
|
||||
|
||||
private DtoMappingRequest mappingRequest() throws SQLException {
|
||||
@@ -110,19 +110,29 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
}
|
||||
|
||||
private DtoColumn[] readMeta() throws SQLException {
|
||||
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
int cols = metaData.getColumnCount();
|
||||
DtoColumn[] meta = new DtoColumn[cols];
|
||||
for (int i = 0; i < cols; i++) {
|
||||
int pos = i+1;
|
||||
int pos = i + 1;
|
||||
String columnLabel = metaData.getColumnLabel(pos);
|
||||
if (columnLabel == null) {
|
||||
columnLabel = metaData.getColumnName(pos);
|
||||
}
|
||||
meta[i] = new DtoColumn(columnLabel);
|
||||
meta[i] = new DtoColumn(parseColumn(columnLabel));
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
static String parseColumn(String columnLabel) {
|
||||
if (columnLabel.startsWith("_e_") || columnLabel.startsWith("_E_")) {
|
||||
// encrypted column alias in the form _e_<tableAlias>_<column>
|
||||
final int pos = columnLabel.indexOf("_", 3);
|
||||
if (pos > -1) {
|
||||
return columnLabel.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
return columnLabel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -117,12 +117,8 @@ class InitDataSource {
|
||||
}
|
||||
|
||||
private DataSource create(DataSourceConfig dsConfig, boolean readOnly) {
|
||||
DataSourceFactory factory = DataSourceFactory.get();
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException("No DataSourceFactory service implementation found in class path. Missing dependency to ebean-datasource?");
|
||||
}
|
||||
String poolName = config.getName() + (readOnly ? "-ro" : "");
|
||||
return factory.createPool(poolName, dsConfig);
|
||||
return DataSourceFactory.create(poolName, dsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -503,10 +503,9 @@ public class InternalConfiguration {
|
||||
* Create the DataTimeZone implementation to use.
|
||||
*/
|
||||
private DataTimeZone initDataTimeZone() {
|
||||
|
||||
String tz = serverConfig.getDataTimeZone();
|
||||
if (tz == null) {
|
||||
if (isMySql(getPlatform())) {
|
||||
if (isMySqlOrMariaDB(getPlatform())) {
|
||||
return new MySqlDataTimeZone();
|
||||
}
|
||||
return new NoDataTimeZone();
|
||||
@@ -518,8 +517,8 @@ public class InternalConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMySql(Platform platform) {
|
||||
return platform.base() == Platform.MYSQL;
|
||||
private boolean isMySqlOrMariaDB(Platform platform) {
|
||||
return platform.base() == Platform.MYSQL || platform.base() == Platform.MARIADB;
|
||||
}
|
||||
|
||||
public DataTimeZone getDataTimeZone() {
|
||||
|
||||
@@ -57,14 +57,14 @@ public class MultiTenantDbCatalogSupplier implements DataSourceSupplier {
|
||||
@Override
|
||||
public void shutdown(boolean deregisterDriver) {
|
||||
if (readOnlyDataSource instanceof DataSourcePool) {
|
||||
((DataSourcePool) readOnlyDataSource).shutdown(false);
|
||||
((DataSourcePool) readOnlyDataSource).shutdown();
|
||||
}
|
||||
if (dataSource instanceof DataSourcePool) {
|
||||
((DataSourcePool) dataSource).shutdown(deregisterDriver);
|
||||
((DataSourcePool) dataSource).shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private class CatalogDataSource implements DataSource {
|
||||
private static class CatalogDataSource implements DataSource {
|
||||
|
||||
final DataSource dataSource;
|
||||
final CurrentTenantProvider tenantProvider;
|
||||
|
||||
@@ -57,10 +57,10 @@ class MultiTenantDbSchemaSupplier implements DataSourceSupplier {
|
||||
@Override
|
||||
public void shutdown(boolean deregisterDriver) {
|
||||
if (readOnlyDataSource instanceof DataSourcePool) {
|
||||
((DataSourcePool) readOnlyDataSource).shutdown(false);
|
||||
((DataSourcePool) readOnlyDataSource).shutdown();
|
||||
}
|
||||
if (dataSource instanceof DataSourcePool) {
|
||||
((DataSourcePool) dataSource).shutdown(deregisterDriver);
|
||||
((DataSourcePool) dataSource).shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,8 +89,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
|
||||
private Set<String> dependentTables;
|
||||
|
||||
private boolean iterateSingleContext;
|
||||
|
||||
/**
|
||||
* Create the InternalQueryRequest.
|
||||
*/
|
||||
@@ -108,15 +106,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return queryEngine.translate(this, bindLog, sql, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIterateSingleContext() {
|
||||
this.iterateSingleContext = true;
|
||||
}
|
||||
|
||||
public boolean isIterateSingleContext() {
|
||||
return iterateSingleContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeleteByStatement() {
|
||||
if (!transaction.isPersistCascade() || beanDescriptor.isDeleteByStatement()) {
|
||||
@@ -316,7 +305,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
*/
|
||||
@Override
|
||||
public JsonReadOptions createJsonReadOptions() {
|
||||
|
||||
persistenceContext = getPersistenceContext(query, transaction);
|
||||
if (query.getPersistenceContext() == null) {
|
||||
query.setPersistenceContext(persistenceContext);
|
||||
@@ -327,7 +315,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
loadContext = new DLoadContext(this, secondaryQueries);
|
||||
jsonRead.setLoadContext(loadContext);
|
||||
}
|
||||
|
||||
return jsonRead;
|
||||
}
|
||||
|
||||
@@ -335,8 +322,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
* For iterate queries reset the persistenceContext and loadContext.
|
||||
*/
|
||||
public void flushPersistenceContextOnIterate() {
|
||||
if (!iterateSingleContext) {
|
||||
persistenceContext = new DefaultPersistenceContext();
|
||||
if (persistenceContext.resetLimit()) {
|
||||
persistenceContext = persistenceContext.forIterateReset();
|
||||
loadContext.resetPersistenceContext(persistenceContext);
|
||||
if (jsonRead != null) {
|
||||
jsonRead.setPersistenceContext(persistenceContext);
|
||||
@@ -350,7 +337,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
* transaction scoped.
|
||||
*/
|
||||
private PersistenceContext getPersistenceContext(SpiQuery<?> query, SpiTransaction t) {
|
||||
|
||||
// check if there is already a persistence context set which is the case
|
||||
// when lazy loading or query joins are executed
|
||||
PersistenceContext ctx = query.getPersistenceContext();
|
||||
@@ -358,7 +344,14 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
|
||||
// determine the scope (from the query and then server)
|
||||
PersistenceContextScope scope = ebeanServer.getPersistenceContextScope(query);
|
||||
return (scope == PersistenceContextScope.QUERY || t == null) ? new DefaultPersistenceContext() : t.getPersistenceContext();
|
||||
if (scope == PersistenceContextScope.QUERY || t == null) {
|
||||
return new DefaultPersistenceContext();
|
||||
}
|
||||
if (Type.ITERATE == query.getType()) {
|
||||
return t.getPersistenceContext().forIterate();
|
||||
} else {
|
||||
return t.getPersistenceContext();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -578,6 +571,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return cacheKey != null && query.getUseQueryCache().isPut();
|
||||
}
|
||||
|
||||
public boolean isBeanCachePutMany() {
|
||||
return !transaction.isSkipCacheExplicit() && query.isBeanCachePut();
|
||||
}
|
||||
|
||||
public boolean isBeanCachePut() {
|
||||
return !transaction.isSkipCache() && query.isBeanCachePut();
|
||||
}
|
||||
@@ -586,7 +583,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
* Merge in prior L2 bean cache hits with the query result.
|
||||
*/
|
||||
public void mergeCacheHits(BeanCollection<T> result) {
|
||||
|
||||
if (cacheBeans != null && !cacheBeans.isEmpty()) {
|
||||
if (query.getType() == Type.MAP) {
|
||||
mergeCacheHitsToMap(result);
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebeaninternal.dbmigration.ddlgeneration.platform.DB2Ddl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.H2Ddl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.HanaColumnStoreDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.HsqldbDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.MariaDbDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.MySqlDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.NuoDbDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.OracleDdl;
|
||||
@@ -31,6 +32,8 @@ public class PlatformDdlBuilder {
|
||||
return new H2Ddl(platform);
|
||||
case DB2:
|
||||
return new DB2Ddl(platform);
|
||||
case MARIADB:
|
||||
return new MariaDbDdl(platform);
|
||||
case MYSQL55:
|
||||
case MYSQL:
|
||||
return new MySqlDdl(platform);
|
||||
|
||||
@@ -44,10 +44,10 @@ class SimpleDataSourceProvider implements DataSourceSupplier {
|
||||
@Override
|
||||
public void shutdown(boolean deregisterDriver) {
|
||||
if (readOnlyDataSource instanceof DataSourcePool){
|
||||
((DataSourcePool) readOnlyDataSource).shutdown(false);
|
||||
((DataSourcePool) readOnlyDataSource).shutdown();
|
||||
}
|
||||
if (dataSource instanceof DataSourcePool){
|
||||
((DataSourcePool) dataSource).shutdown(deregisterDriver);
|
||||
((DataSourcePool) dataSource).shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,9 +177,4 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
|
||||
*/
|
||||
boolean isDeleteByStatement();
|
||||
|
||||
/**
|
||||
* Set when we want to use a single persistence context for all beans returned
|
||||
* in the query (so all beans are held in memory)
|
||||
*/
|
||||
void setIterateSingleContext();
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* Run periodic trim of query plans.
|
||||
*/
|
||||
public void scheduleBackgroundTrim() {
|
||||
backgroundExecutor.executePeriodically(this::trimQueryPlans, 60L, TimeUnit.SECONDS);
|
||||
backgroundExecutor.executePeriodically(this::trimQueryPlans, 117L, 60L, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private void trimQueryPlans() {
|
||||
|
||||
@@ -542,12 +542,11 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
return dbEncryptFunction.getDecryptSql(propertyName);
|
||||
}
|
||||
|
||||
public String getDecryptSql() {
|
||||
return dbEncryptFunction.getDecryptSql(this.getDbColumn());
|
||||
}
|
||||
|
||||
private String getDecryptSql(String tableAlias) {
|
||||
return dbEncryptFunction.getDecryptSql(tableAlias + "." + this.getDbColumn());
|
||||
/**
|
||||
* Return the SQL for the column including decryption function and column alias.
|
||||
*/
|
||||
private String getDecryptSqlWithColumnAlias(String tableAlias) {
|
||||
return dbEncryptFunction.getDecryptSql(tableAlias + "." + this.getDbColumn()) + " _e_" + tableAlias + "_" + this.getDbColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -600,8 +599,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
if (dbEncrypted) {
|
||||
String decryptSql = getDecryptSql(ctx.peekTableAlias());
|
||||
ctx.appendRawColumn(decryptSql);
|
||||
ctx.appendRawColumn(getDecryptSqlWithColumnAlias(ctx.peekTableAlias()));
|
||||
ctx.addEncryptedProp(this);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -50,4 +50,45 @@ public class DtoMappingRequest {
|
||||
public QueryPlanMetric createMetric() {
|
||||
return MetricFactory.get().createQueryPlanMetric(type, label, profileLocation, sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map all DB columns to setters.
|
||||
*/
|
||||
DtoReadSet[] mapSetters(DtoMeta meta) {
|
||||
DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length];
|
||||
for (int i = 0; i < columnMeta.length; i++) {
|
||||
setterProps[i] = mapColumn(i, meta);
|
||||
}
|
||||
return setterProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map DB columns after constructor to setters.
|
||||
*/
|
||||
DtoReadSet[] mapArgPlusSetters(DtoMeta meta, int firstOnes) {
|
||||
DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length - firstOnes];
|
||||
int pos = 0;
|
||||
for (int i = firstOnes; i < columnMeta.length; i++) {
|
||||
setterProps[pos++] = mapColumn(i, meta);
|
||||
}
|
||||
return setterProps;
|
||||
}
|
||||
|
||||
private DtoReadSet mapColumn(int pos, DtoMeta meta) {
|
||||
String label = columnMeta[pos].getLabel();
|
||||
DtoReadSet property = meta.findProperty(label);
|
||||
if (property == null || property.isReadOnly()) {
|
||||
if (isRelaxedMode()) {
|
||||
property = DtoReadSetColumnSkip.INSTANCE;
|
||||
} else {
|
||||
throw new IllegalStateException(unableToMapColumnMessage(columnMeta[pos], meta));
|
||||
}
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
private String unableToMapColumnMessage(DtoColumn col, DtoMeta meta) {
|
||||
return "Unable to map DB column " + col + " to a property with a setter method on " + meta.dtoType()+". Consider query.setRelaxedMode() to skip mapping this column.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,55 +72,16 @@ class DtoMeta {
|
||||
}
|
||||
|
||||
private DtoQueryPlanConPlus matchMaxArgPlusSetters(DtoMappingRequest request) {
|
||||
|
||||
|
||||
int firstOnes = maxArgConstructor.getArgCount();
|
||||
|
||||
DtoColumn[] cols = request.getColumnMeta();
|
||||
|
||||
DtoReadSet[] setterProps = new DtoReadSet[cols.length - firstOnes];
|
||||
|
||||
int pos = 0;
|
||||
for (int i = firstOnes; i < cols.length; i++) {
|
||||
String label = cols[i].getLabel();
|
||||
DtoReadSet property = findProperty(label);
|
||||
if (property == null || property.isReadOnly()) {
|
||||
if (request.isRelaxedMode()) {
|
||||
property = DtoReadSetColumnSkip.INSTANCE;
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to map DB column " + cols[i] + " to a property with a setter method on " + dtoType);
|
||||
}
|
||||
}
|
||||
setterProps[pos++] = property;
|
||||
}
|
||||
|
||||
DtoReadSet[] setterProps = request.mapArgPlusSetters(this, maxArgConstructor.getArgCount());
|
||||
return new DtoQueryPlanConPlus(request, maxArgConstructor, setterProps);
|
||||
}
|
||||
|
||||
private DtoQueryPlan matchSetters(DtoMappingRequest request) {
|
||||
|
||||
DtoColumn[] cols = request.getColumnMeta();
|
||||
|
||||
DtoReadSet[] setterProps = new DtoReadSet[cols.length];
|
||||
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
String label = cols[i].getLabel();
|
||||
DtoReadSet property = findProperty(label);
|
||||
if (property == null || property.isReadOnly()) {
|
||||
if (request.isRelaxedMode()) {
|
||||
property = DtoReadSetColumnSkip.INSTANCE;
|
||||
} else {
|
||||
throw new IllegalStateException("Unable to map DB column " + cols[i] + " to a property with a setter method on " + dtoType);
|
||||
}
|
||||
}
|
||||
setterProps[i] = property;
|
||||
}
|
||||
|
||||
DtoReadSet[] setterProps = request.mapSetters(this);
|
||||
return new DtoQueryPlanConSetter(request, defaultConstructor, setterProps);
|
||||
}
|
||||
|
||||
private DtoReadSet findProperty(String label) {
|
||||
|
||||
DtoReadSet findProperty(String label) {
|
||||
String upperLabel = label.toUpperCase();
|
||||
DtoMetaProperty property = propMap.get(upperLabel);
|
||||
if (property == null && upperLabel.startsWith("IS_")) {
|
||||
@@ -131,4 +92,8 @@ class DtoMeta {
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
Class<?> dtoType() {
|
||||
return dtoType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,8 +346,9 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> orderBy(String orderBy) {
|
||||
return query.order(orderBy);
|
||||
public ExpressionList<T> orderBy(String orderBy) {
|
||||
query.order(orderBy);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -145,8 +145,9 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> orderBy(String orderBy) {
|
||||
return rootQuery.orderBy(orderBy);
|
||||
public ExpressionList<T> orderBy(String orderByClause) {
|
||||
this.orderByClause = orderByClause;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -809,7 +809,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> orderBy(String orderBy) {
|
||||
public ExpressionList<T> orderBy(String orderBy) {
|
||||
return exprList.orderBy(orderBy);
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -18,6 +18,8 @@ public class DbExpressionHandlerFactory {
|
||||
case POSTGRES:
|
||||
case POSTGRES9:
|
||||
return new PostgresDbExpression();
|
||||
case MARIADB:
|
||||
return new MariaDbExpression();
|
||||
case MYSQL55:
|
||||
case MYSQL:
|
||||
return new MySqlDbExpression();
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
* MariaDB specific handling of platform specific expressions.
|
||||
*/
|
||||
class MariaDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("(").append(propName).append(" ->> '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,6 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
// A synchronized (this) is effectively held by EntityBeanIntercept.loadBean()
|
||||
|
||||
if (context.desc.lazyLoadMany(ebi)) {
|
||||
// lazy load property was a Many
|
||||
return;
|
||||
@@ -183,7 +182,6 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
|
||||
if (context.hitCache) {
|
||||
Set<EntityBeanIntercept> hits = context.desc.cacheBeanLoadAll(list, persistenceContext, ebi.getLazyLoadPropertyIndex(), ebi.getLazyLoadProperty());
|
||||
|
||||
list.removeAll(hits);
|
||||
if (list.isEmpty() || hits.contains(ebi)) {
|
||||
// successfully hit the L2 cache so don't invoke DB lazy loading
|
||||
@@ -193,6 +191,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
|
||||
LoadBeanRequest req = new LoadBeanRequest(this, ebi, context.hitCache);
|
||||
context.desc.getEbeanServer().loadBean(req);
|
||||
list.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@ public class DLoadContext implements LoadContext {
|
||||
* Construct for use with JSON marshalling (doc store).
|
||||
*/
|
||||
public DLoadContext(BeanDescriptor<?> rootDescriptor, PersistenceContext persistenceContext) {
|
||||
|
||||
this.useDocStore = true;
|
||||
this.rootDescriptor = rootDescriptor;
|
||||
this.ebeanServer = rootDescriptor.getEbeanServer();
|
||||
@@ -100,7 +99,6 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
public DLoadContext(OrmQueryRequest<?> request, SpiQuerySecondary secondaryQueries) {
|
||||
|
||||
this.tenantId = request.getTenantId();
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
this.ebeanServer = request.getServer();
|
||||
@@ -131,7 +129,6 @@ public class DLoadContext implements LoadContext {
|
||||
|
||||
// initialise rootBeanContext after origin and relativePath have been set
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, defaultBatchSize, null);
|
||||
|
||||
registerSecondaryQueries(secondaryQueries);
|
||||
}
|
||||
|
||||
@@ -153,14 +150,12 @@ public class DLoadContext implements LoadContext {
|
||||
* Register the +query and +lazy secondary queries with their appropriate LoadBeanContext or LoadManyContext.
|
||||
*/
|
||||
private void registerSecondaryQueries(SpiQuerySecondary secondaryQueries) {
|
||||
|
||||
this.secQuery = secondaryQueries.getQueryJoins();
|
||||
if (secQuery != null) {
|
||||
for (OrmQueryProperties pathProperties : secQuery) {
|
||||
registerSecondaryQuery(pathProperties);
|
||||
}
|
||||
}
|
||||
|
||||
List<OrmQueryProperties> lazyJoins = secondaryQueries.getLazyJoins();
|
||||
if (lazyJoins != null) {
|
||||
for (OrmQueryProperties lazyJoin : lazyJoins) {
|
||||
@@ -174,9 +169,7 @@ public class DLoadContext implements LoadContext {
|
||||
* used to build the appropriate query for +query or +lazy loading.
|
||||
*/
|
||||
private void registerSecondaryQuery(OrmQueryProperties props) {
|
||||
|
||||
ElPropertyValue elGetValue = rootDescriptor.getElGetValue(props.getPath());
|
||||
|
||||
boolean many = elGetValue.getBeanProperty().containsMany();
|
||||
registerSecondaryNode(many, props);
|
||||
}
|
||||
@@ -190,11 +183,9 @@ public class DLoadContext implements LoadContext {
|
||||
*/
|
||||
@Override
|
||||
public int getSecondaryQueriesMinBatchSize(int defaultQueryBatch) {
|
||||
|
||||
if (secQuery == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int maxBatch = 0;
|
||||
for (OrmQueryProperties aSecQuery : secQuery) {
|
||||
int batchSize = aSecQuery.getQueryFetchBatch();
|
||||
@@ -211,7 +202,6 @@ public class DLoadContext implements LoadContext {
|
||||
*/
|
||||
@Override
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (secQuery != null) {
|
||||
for (OrmQueryProperties aSecQuery : secQuery) {
|
||||
LoadSecondaryQuery load = getLoadSecondaryQuery(aSecQuery.getPath());
|
||||
@@ -234,7 +224,6 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
private ObjectGraphNode createObjectGraphNode(String path) {
|
||||
|
||||
if (relativePath != null) {
|
||||
if (path == null) {
|
||||
path = relativePath;
|
||||
@@ -311,7 +300,6 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
private void registerSecondaryNode(boolean many, OrmQueryProperties props) {
|
||||
|
||||
int batchSize;
|
||||
if (props.isQueryFetch()) {
|
||||
batchSize = 100;
|
||||
@@ -319,7 +307,6 @@ public class DLoadContext implements LoadContext {
|
||||
int lazyJoinBatch = props.getLazyFetchBatch();
|
||||
batchSize = lazyJoinBatch > 0 ? lazyJoinBatch : defaultBatchSize;
|
||||
}
|
||||
|
||||
String path = props.getPath();
|
||||
if (many) {
|
||||
manyMap.put(path, createManyContext(path, batchSize, props));
|
||||
@@ -336,7 +323,6 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
BeanPropertyAssocMany<?> p = (BeanPropertyAssocMany<?>) getBeanProperty(rootDescriptor, path);
|
||||
return new DLoadManyContext(this, p, path, batchSize, queryProps);
|
||||
}
|
||||
|
||||
@@ -53,8 +53,9 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
/**
|
||||
* Create with a given statement.
|
||||
*/
|
||||
public BatchedPstmt(PreparedStatement pstmt, boolean isGenKeys, String sql, SpiTransaction transaction) {
|
||||
public BatchedPstmt(PreparedStatement pstmt, boolean isGenKeys, String sql, SpiTransaction transaction) throws SQLException {
|
||||
this.pstmt = pstmt;
|
||||
this.pstmt.clearBatch();
|
||||
this.isGenKeys = isGenKeys;
|
||||
this.sql = sql;
|
||||
this.transaction = transaction;
|
||||
@@ -92,7 +93,7 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
private void flushStatementBatch() throws SQLException {
|
||||
final int[] rows = pstmt.executeBatch();
|
||||
if (rows.length != list.size()) {
|
||||
throw new IllegalStateException("Invalid state? rows:" + rows.length + " != " + list.size());
|
||||
throw new IllegalStateException("Invalid state on executeBatch, rows:" + rows.length + " != " + list.size());
|
||||
}
|
||||
for (BatchPostExecute item : list) {
|
||||
item.postExecute();
|
||||
@@ -156,8 +157,7 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
try {
|
||||
results = pstmt.executeBatch();
|
||||
if (results.length != list.size()) {
|
||||
String s = "results array error " + results.length + " " + list.size();
|
||||
throw new SQLException(s);
|
||||
throw new SQLException("Invalid state on executeBatch, rows:" + results.length + " != " + list.size());
|
||||
}
|
||||
// check for concurrency exceptions...
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
|
||||
@@ -13,6 +13,9 @@ import io.ebeaninternal.server.persist.dmlbind.BindableList;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static io.ebean.annotation.Platform.MARIADB;
|
||||
import static io.ebean.annotation.Platform.MYSQL;
|
||||
|
||||
/**
|
||||
* Meta data for insert handler. The meta data is for a particular bean type. It
|
||||
* is considered immutable and is thread safe.
|
||||
@@ -166,12 +169,7 @@ final class InsertMeta {
|
||||
|
||||
request.append("insert into ").append(table);
|
||||
if (nullId && noColumnsForInsert(draftTable)) {
|
||||
if (this.platform.base() == Platform.MYSQL) {
|
||||
request.append(" values (default)");
|
||||
} else {
|
||||
request.append(" default values");
|
||||
}
|
||||
return request.toString();
|
||||
return request.append(defaultValues()).toString();
|
||||
}
|
||||
|
||||
request.append(" (");
|
||||
@@ -199,6 +197,10 @@ final class InsertMeta {
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
private String defaultValues() {
|
||||
return platform.base() == MYSQL || platform.base() == MARIADB ? " values (default)" : " default values";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the insert actually contains no columns.
|
||||
*/
|
||||
|
||||
@@ -608,12 +608,10 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
}
|
||||
|
||||
QueryIterator<T> readIterate(int bufferSize, OrmQueryRequest<T> request) {
|
||||
|
||||
if (bufferSize > 0) {
|
||||
return new CQueryIteratorWithBuffer<>(this, request, bufferSize);
|
||||
|
||||
} else {
|
||||
if (bufferSize == 1) {
|
||||
return new CQueryIteratorSimple<>(this, request);
|
||||
} else {
|
||||
return new CQueryIteratorWithBuffer<>(this, request, bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ class CQueryBuilder {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
String rootTableAlias = query.getAlias();
|
||||
query.setupForDeleteOrUpdate(deleteRequest);
|
||||
query.setupForDeleteOrUpdate();
|
||||
|
||||
CQueryPredicates predicates = new CQueryPredicates(binder, request);
|
||||
CQueryPlan queryPlan = request.getQueryPlan();
|
||||
@@ -125,7 +125,7 @@ class CQueryBuilder {
|
||||
private <T> String buildDeleteSql(OrmQueryRequest<T> request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) {
|
||||
|
||||
String alias = alias(rootTableAlias);
|
||||
if (sqlTree.noJoins()) {
|
||||
if (sqlTree.noJoins() && !request.getQuery().hasMaxRowsOrFirstRow()) {
|
||||
if (dbPlatform.isSupportsDeleteTableAlias()) {
|
||||
// delete from table <alias> ...
|
||||
return aliasReplace(buildSqlDelete("delete", request, predicates, sqlTree).getSql(), alias);
|
||||
|
||||
@@ -201,26 +201,20 @@ public class CQueryEngine {
|
||||
* when you have finished).
|
||||
*/
|
||||
public <T> QueryIterator<T> findIterate(OrmQueryRequest<T> request) {
|
||||
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
request.setCancelableQuery(cquery);
|
||||
try {
|
||||
if (defaultFetchSizeFindEach > 0) {
|
||||
request.setDefaultFetchBuffer(defaultFetchSizeFindEach);
|
||||
}
|
||||
if (request.isIterateSingleContext()) {
|
||||
// expected relatively small number of results, single persistence context
|
||||
cquery.prepareBindExecuteQuery();
|
||||
} else if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
|
||||
if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (request.isLogSql()) {
|
||||
logSql(cquery);
|
||||
}
|
||||
|
||||
// first check batch sizes set on query joins
|
||||
int iterateBufferSize = request.getSecondaryQueriesMinBatchSize(defaultSecondaryQueryBatchSize);
|
||||
if (iterateBufferSize < 1) {
|
||||
@@ -228,20 +222,19 @@ public class CQueryEngine {
|
||||
int queryBatch = request.getQuery().getLazyLoadBatchSize();
|
||||
if (queryBatch > 0) {
|
||||
iterateBufferSize = queryBatch;
|
||||
} else {
|
||||
iterateBufferSize = 100;
|
||||
}
|
||||
}
|
||||
|
||||
QueryIterator<T> readIterate = cquery.readIterate(iterateBufferSize, request);
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
logFindManySummary(cquery);
|
||||
}
|
||||
|
||||
if (request.isAuditReads()) {
|
||||
// indicates we need to audit as the iterator progresses
|
||||
cquery.auditFindIterate();
|
||||
}
|
||||
|
||||
return readIterate;
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* A QueryIterator that uses a buffer to execute secondary queries periodically.
|
||||
@@ -17,6 +18,7 @@ class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
private final OrmQueryRequest<T> request;
|
||||
private final ArrayList<T> buffer;
|
||||
|
||||
private boolean closed;
|
||||
private boolean moreToLoad = true;
|
||||
|
||||
CQueryIteratorWithBuffer(CQuery<T> cquery, OrmQueryRequest<T> request, int bufferSize) {
|
||||
@@ -29,6 +31,7 @@ class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean hasNext() {
|
||||
boolean ret = false;
|
||||
try {
|
||||
if (buffer.isEmpty() && moreToLoad) {
|
||||
// load buffer
|
||||
@@ -44,23 +47,33 @@ class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
}
|
||||
request.executeSecondaryQueries(true);
|
||||
}
|
||||
return !buffer.isEmpty();
|
||||
|
||||
ret = !buffer.isEmpty();
|
||||
return ret;
|
||||
} catch (SQLException e) {
|
||||
throw cquery.createPersistenceException(e);
|
||||
} finally {
|
||||
if (!ret) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
if (buffer.isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
return buffer.remove(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
cquery.updateExecutionStatisticsIterator();
|
||||
cquery.close();
|
||||
request.endTransIfRequired();
|
||||
if (!closed) {
|
||||
closed = true;
|
||||
cquery.updateExecutionStatisticsIterator();
|
||||
cquery.close();
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -328,11 +328,9 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendRawColumn(String rawcolumnWithTableAlias) {
|
||||
public void appendRawColumn(String rawColumnWithAlias) {
|
||||
sb.append(COMMA);
|
||||
sb.append(rawcolumnWithTableAlias);
|
||||
|
||||
appendColumnAlias();
|
||||
sb.append(rawColumnWithAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -133,7 +133,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
|
||||
if (request.isBeanCachePut()) {
|
||||
if (request.isBeanCachePutMany()) {
|
||||
// load the individual beans into the bean cache
|
||||
BeanDescriptor<T> descriptor = request.getBeanDescriptor();
|
||||
Collection<T> c = result.getActualDetails();
|
||||
|
||||
@@ -684,13 +684,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* Setup to be a delete or update query.
|
||||
*/
|
||||
@Override
|
||||
public void setupForDeleteOrUpdate(boolean deleteRequest) {
|
||||
// unset any paging and select on the id in the case where the query
|
||||
// includes joins and we use - delete ... where id in (...)
|
||||
if (deleteRequest) {
|
||||
maxRows = 0;
|
||||
}
|
||||
firstRow = 0;
|
||||
public void setupForDeleteOrUpdate() {
|
||||
forUpdate = null;
|
||||
rootTableAlias = "${RTA}"; // alias we remove later
|
||||
setSelectId();
|
||||
@@ -1721,8 +1715,10 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setManualId(boolean manualId) {
|
||||
this.manualId = manualId;
|
||||
public void setManualId() {
|
||||
if (detail != null && detail.hasSelectClause()) {
|
||||
this.manualId = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,18 +34,62 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
|
||||
private final Monitor monitor = new Monitor();
|
||||
|
||||
private int putCount;
|
||||
|
||||
/**
|
||||
* Create a new PersistenceContext.
|
||||
*/
|
||||
public DefaultPersistenceContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create as a shallow copy with initial or types that have not been added to.
|
||||
*/
|
||||
private DefaultPersistenceContext(DefaultPersistenceContext parent, boolean initial) {
|
||||
for (Map.Entry<Class<?>, ClassContext> entry : parent.typeCache.entrySet()) {
|
||||
typeCache.put(entry.getKey(), entry.getValue().copy(initial));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the initial shallow copy with each ClassContext noting it's initialSize (to detect additions).
|
||||
*/
|
||||
@Override
|
||||
public PersistenceContext forIterate() {
|
||||
return new DefaultPersistenceContext(this, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a shallow copy including each ClassContext that has had no additions (still at initialSize).
|
||||
*/
|
||||
@Override
|
||||
public PersistenceContext forIterateReset() {
|
||||
return new DefaultPersistenceContext(this, false);
|
||||
}
|
||||
|
||||
public boolean resetLimit() {
|
||||
synchronized (monitor) {
|
||||
if (putCount < 100) {
|
||||
return false;
|
||||
}
|
||||
putCount = 0;
|
||||
for (ClassContext value : typeCache.values()) {
|
||||
if (value.resetLimit()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// checking after another 100 puts
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object into the PersistenceContext.
|
||||
*/
|
||||
@Override
|
||||
public void put(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
putCount++;
|
||||
getClassContext(rootType).put(id, bean);
|
||||
}
|
||||
}
|
||||
@@ -53,6 +97,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
@Override
|
||||
public Object putIfAbsent(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
putCount++;
|
||||
return getClassContext(rootType).putIfAbsent(id, bean);
|
||||
}
|
||||
}
|
||||
@@ -133,7 +178,6 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
|
||||
private ClassContext getClassContext(Class<?> rootType) {
|
||||
|
||||
return typeCache.computeIfAbsent(rootType, k -> new ClassContext());
|
||||
}
|
||||
|
||||
@@ -143,9 +187,45 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
|
||||
private Set<Object> deleteSet;
|
||||
|
||||
private int initialSize;
|
||||
|
||||
private ClassContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create as a shallow copy.
|
||||
*/
|
||||
private ClassContext(ClassContext parent, boolean initial) {
|
||||
if (initial || parent.isInitialSize()) {
|
||||
this.map.putAll(parent.map);
|
||||
this.initialSize = map.size();
|
||||
if (parent.deleteSet != null) {
|
||||
this.deleteSet = new HashSet<>(parent.deleteSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the map has not changed from it's initial size (no additions).
|
||||
*/
|
||||
private boolean isInitialSize() {
|
||||
return map.size() == initialSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a shallow copy if initial copy or it has not grown (still at initialSize).
|
||||
*/
|
||||
private ClassContext copy(boolean initial) {
|
||||
return new ClassContext(this, initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if grown above the reset limit size.
|
||||
*/
|
||||
private boolean resetLimit() {
|
||||
return map.size() > initialSize + 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "size:" + map.size();
|
||||
@@ -164,7 +244,6 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
|
||||
private Object putIfAbsent(Object id, Object bean) {
|
||||
|
||||
Object existingValue = map.get(id);
|
||||
if (existingValue != null) {
|
||||
// it is not absent
|
||||
|
||||
@@ -140,6 +140,11 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCacheExplicit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSkipCache(boolean skipCache) {
|
||||
}
|
||||
|
||||
@@ -293,6 +293,11 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCacheExplicit() {
|
||||
return (skipCache != null && !skipCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
if (skipCache != null) return skipCache;
|
||||
|
||||
@@ -200,6 +200,11 @@ class NoTransaction implements SpiTransaction {
|
||||
public void setSkipCache(boolean skipCache) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCacheExplicit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSkipCache() {
|
||||
return false;
|
||||
|
||||
@@ -191,6 +191,7 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
this.txnMain = metricFactory.createTimedMetric("txn.main");
|
||||
this.txnReadOnly = metricFactory.createTimedMetric("txn.readonly");
|
||||
this.txnNamed = metricFactory.createTimedMetricMap("txn.named.");
|
||||
// Add gauges for db pool size
|
||||
|
||||
scopeManager.register(this);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.function.Predicate;
|
||||
public class NoneDocStore implements DocumentStore {
|
||||
|
||||
public static IllegalStateException implementationNotInClassPath() {
|
||||
throw new IllegalStateException("DocStore implementation not included in the classPath. You need to add the maven dependency for avaje-ebeanorm-elastic");
|
||||
throw new IllegalStateException("DocStore implementation not included in the classPath. You need to add the maven dependency for io.ebean:ebean-elastic");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -206,6 +206,10 @@ public abstract class BaseTestCase {
|
||||
return Platform.MYSQL == platform();
|
||||
}
|
||||
|
||||
public boolean isMariaDB() {
|
||||
return Platform.MARIADB == platform();
|
||||
}
|
||||
|
||||
public boolean isHana() {
|
||||
return Platform.HANA == platform();
|
||||
}
|
||||
|
||||
@@ -140,6 +140,32 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDto_withoutSelectClause() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
DtoQuery<ContactDto2> query = DB.find(Contact.class)
|
||||
.where().isNotNull("email").order().asc("lastName")
|
||||
.asDto(ContactDto2.class)
|
||||
.setRelaxedMode();
|
||||
|
||||
List<ContactDto2> dtos = query.findList();
|
||||
assertThat(dtos).isNotEmpty();
|
||||
|
||||
for (ContactDto2 dto : dtos) {
|
||||
assertThat(dto.getEmail()).isNotNull();
|
||||
assertThat(dto.getFirstName()).isNotNull();
|
||||
assertThat(dto.getLastName()).isNotNull();
|
||||
assertThat(dto.getId()).isGreaterThan(0);
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertSql(sql.get(0)).contains("select t0.id, t0.first_name, t0.last_name");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDto_withoutExplicitId() {
|
||||
|
||||
@@ -326,6 +352,46 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ContactDto2 {
|
||||
|
||||
int id;
|
||||
String firstName;
|
||||
String lastName;
|
||||
String email;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ContactDto {
|
||||
|
||||
String email;
|
||||
|
||||
@@ -116,7 +116,11 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(rows).isEqualTo(0);
|
||||
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = ? where id in (?,?,?,?,?)"); // bind padding to 5
|
||||
if (isPostgres()) {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = ? where id = any(?)");
|
||||
} else {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = ? where id in (?,?,?,?,?)"); // bind padding to 5
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -164,7 +168,7 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
assertSql(query).contains("update o_customer cust set status=?, updtime=? where id > ?");
|
||||
}
|
||||
|
||||
@IgnorePlatform(Platform.MYSQL)
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB})
|
||||
@Test
|
||||
public void withJoin() {
|
||||
|
||||
@@ -210,7 +214,7 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status=? where id in (select t0.id from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id where t1.country_code = ? and t0.id > ? limit 100)");
|
||||
}
|
||||
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES, Platform.MYSQL})
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES, Platform.MYSQL, Platform.MARIADB})
|
||||
@Test
|
||||
public void simpleWithLimit() {
|
||||
|
||||
@@ -226,7 +230,7 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
.update();
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
if (isMySql() || isH2()) {
|
||||
if (isMySql() || isH2() || isMariaDB()) {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status=? where id > ? limit 100");
|
||||
} else {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status=? where id in (select t0.id from o_customer t0 where t0.id > ? limit 100)");
|
||||
|
||||
@@ -24,7 +24,7 @@ public class DbMigrationTest extends BaseTestCase {
|
||||
server().script().runScript(scriptName, content, useAutoCommit);
|
||||
}
|
||||
|
||||
@IgnorePlatform({Platform.ORACLE, Platform.NUODB})
|
||||
@IgnorePlatform({Platform.ORACLE, Platform.NUODB, Platform.MARIADB})
|
||||
@Test
|
||||
public void testRunMigration() throws IOException {
|
||||
// first clean up previously created objects
|
||||
|
||||
@@ -154,6 +154,16 @@ public class ModelContainerTest {
|
||||
container.applyChange(dropHistoryTable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void apply_renameColumn() {
|
||||
ModelContainer container = new ModelContainer();
|
||||
container.apply(mig("6.0__renameColumn.model.xml"), ver("6.0"));
|
||||
|
||||
final MTable table = container.getTable("document");
|
||||
assertThat(table.getColumn("title")).isNotNull();
|
||||
assertThat(table.getColumn("short_title")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSchemas() {
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DtoQueryRequestTest {
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
|
||||
assertEquals("foo", DtoQueryRequest.parseColumn("foo"));
|
||||
assertEquals("bar", DtoQueryRequest.parseColumn("_e_t0_bar"));
|
||||
assertEquals("BAR", DtoQueryRequest.parseColumn("_E_T0_BAR"));
|
||||
assertEquals("baz", DtoQueryRequest.parseColumn("_e_t42_baz"));
|
||||
assertEquals("BAZ", DtoQueryRequest.parseColumn("_E_T42_BAZ"));
|
||||
|
||||
assertEquals("e_t42_nope", DtoQueryRequest.parseColumn("e_t42_nope"));
|
||||
assertEquals("_f_t42_nope", DtoQueryRequest.parseColumn("_f_t42_nope"));
|
||||
}
|
||||
}
|
||||
@@ -308,12 +308,19 @@ public class OrmQueryPlanKeyTest extends BaseExpressionTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_manualId() {
|
||||
public void equals_when_manualId_andSelectClause() {
|
||||
DefaultOrmQuery<Customer> q1 = query().select("name");
|
||||
q1.setManualId();
|
||||
|
||||
assertDifferent(q1, query().select("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_manualId_andNoSelectClause() {
|
||||
DefaultOrmQuery<Customer> q1 = query();
|
||||
q1.setManualId(true);
|
||||
q1.setManualId();
|
||||
|
||||
assertDifferent(q1, query());
|
||||
assertSame(q1, query());
|
||||
}
|
||||
|
||||
private CQueryPlanKey planKey(ExpressionList<Customer> id) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebeaninternal.server.rawsql;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
@@ -52,7 +52,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
.parse(sql)
|
||||
.create();
|
||||
|
||||
List<Customer> list = Ebean.createQuery(Customer.class)
|
||||
List<Customer> list = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.setParameter("name", "Rob")
|
||||
.findList();
|
||||
@@ -67,7 +67,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
|
||||
RawSql sql = RawSqlBuilder.parse("SELECT id, name FROM o_customer ${where}").create();
|
||||
|
||||
List<Customer> customers = Ebean.createQuery(Customer.class)
|
||||
List<Customer> customers = DB.find(Customer.class)
|
||||
.setRawSql(sql)
|
||||
.where().gt("id", 1)
|
||||
.findList();
|
||||
@@ -91,7 +91,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse(sql).create();
|
||||
|
||||
Query<Customer> query = Ebean.createQuery(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5);
|
||||
@@ -103,6 +103,70 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
}
|
||||
|
||||
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES})
|
||||
@Test
|
||||
public void testUnion_explicitWhere() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql =
|
||||
"select id, name from (" +
|
||||
" select id, name from o_customer where name <= 'f' " +
|
||||
" union all " +
|
||||
" select id, name from o_customer where name > 'f' " +
|
||||
") all_split ${where}";
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse(sql).create();
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5);
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query)).contains(") all_split limit 5 offset 1");
|
||||
|
||||
Query<Customer> query1 = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.where().gt("id", 2)
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5)
|
||||
.query();
|
||||
query1.findList();
|
||||
|
||||
assertThat(sqlOf(query1)).contains("all_split where id > ? limit 5 offset 1");
|
||||
}
|
||||
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES})
|
||||
@Test
|
||||
public void testUnion_explicitAndhere() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql =
|
||||
"select id, name from (" +
|
||||
" select id, name from o_customer where name <= 'f' " +
|
||||
" union all " +
|
||||
" select id, name from o_customer where name > 'f' " +
|
||||
") all_split where 1=1 ${andWhere}";
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse(sql).create();
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5);
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query)).contains(") all_split where 1=1 limit 5 offset 1");
|
||||
|
||||
Query<Customer> query1 = DB.find(Customer.class)
|
||||
.setRawSql(rawSql)
|
||||
.where().gt("id", 2)
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5)
|
||||
.query();
|
||||
query1.findList();
|
||||
|
||||
assertThat(sqlOf(query1)).contains("all_split where 1=1 and id > ? limit 5 offset 1");
|
||||
}
|
||||
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES})
|
||||
@Test
|
||||
public void testColumnName2() {
|
||||
@@ -113,7 +177,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse(sql).create();
|
||||
|
||||
Query<A2Customer> query = Ebean.createQuery(A2Customer.class)
|
||||
Query<A2Customer> query = DB.find(A2Customer.class)
|
||||
.setRawSql(rawSql);
|
||||
|
||||
final List<A2Customer> list = query.findList();
|
||||
@@ -135,7 +199,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse(sql).create();
|
||||
|
||||
Query<ACustomer> query = Ebean.createQuery(ACustomer.class)
|
||||
Query<ACustomer> query = DB.find(ACustomer.class)
|
||||
.setRawSql(rawSql);
|
||||
|
||||
final List<ACustomer> list = query.findList();
|
||||
@@ -159,7 +223,7 @@ public class TestRawSqlParsing extends BaseTestCase {
|
||||
.columnMapping("v.customerName", "custName")
|
||||
.create();
|
||||
|
||||
Query<ACustomer> query = Ebean.createQuery(ACustomer.class)
|
||||
Query<ACustomer> query = DB.find(ACustomer.class)
|
||||
.setRawSql(rawSql);
|
||||
|
||||
final List<ACustomer> list = query.findList();
|
||||
|
||||
+114
-20
@@ -2,12 +2,16 @@ package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.deploy.PersistenceContextUtil;
|
||||
import org.tests.model.basic.Car;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Vehicle;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Car;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Product;
|
||||
import org.tests.model.basic.Vehicle;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DefaultPersistenceContextTest {
|
||||
|
||||
@@ -23,12 +27,12 @@ public class DefaultPersistenceContextTest {
|
||||
car1.setId(1);
|
||||
}
|
||||
|
||||
PersistenceContext pc() {
|
||||
private DefaultPersistenceContext pc() {
|
||||
return new DefaultPersistenceContext();
|
||||
}
|
||||
|
||||
PersistenceContext pcWith42() {
|
||||
PersistenceContext pc = pc();
|
||||
private DefaultPersistenceContext pcWith42() {
|
||||
DefaultPersistenceContext pc = pc();
|
||||
pc.put(Customer.class, 42, customer42);
|
||||
return pc;
|
||||
}
|
||||
@@ -38,7 +42,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void put_get_withInheritance() throws Exception {
|
||||
public void put_get_withInheritance() {
|
||||
|
||||
PersistenceContext pc = pc();
|
||||
pc.put(root(Vehicle.class), 1, car1);
|
||||
@@ -48,7 +52,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void put_get() throws Exception {
|
||||
public void put_get() {
|
||||
|
||||
PersistenceContext pc = pc();
|
||||
pc.put(Customer.class, customer42.getId(), customer42);
|
||||
@@ -58,7 +62,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putIfAbsent_when_absent() throws Exception {
|
||||
public void putIfAbsent_when_absent() {
|
||||
|
||||
PersistenceContext pc = pc();
|
||||
Object existing = pc.putIfAbsent(Customer.class, customer42.getId(), customer42);
|
||||
@@ -67,7 +71,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putIfAbsent_when_notAbsent() throws Exception {
|
||||
public void putIfAbsent_when_notAbsent() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
Object existing = pc.putIfAbsent(Customer.class, customer42.getId(), new Customer());
|
||||
@@ -76,21 +80,21 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get_when_empty() throws Exception {
|
||||
public void get_when_empty() {
|
||||
PersistenceContext pc = pc();
|
||||
Object found = pc.get(Customer.class, 42);
|
||||
assertThat(found).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void get_when_there() throws Exception {
|
||||
public void get_when_there() {
|
||||
PersistenceContext pc = pcWith42();
|
||||
Object found = pc.get(Customer.class, 42);
|
||||
assertThat(found).isSameAs(customer42);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWithOption_when_empty() throws Exception {
|
||||
public void getWithOption_when_empty() {
|
||||
|
||||
PersistenceContext pc = pc();
|
||||
PersistenceContext.WithOption withOption = pc.getWithOption(Customer.class, 42);
|
||||
@@ -98,7 +102,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWithOption_when_there() throws Exception {
|
||||
public void getWithOption_when_there() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
|
||||
@@ -107,7 +111,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getWithOption_when_deleted() throws Exception {
|
||||
public void getWithOption_when_deleted() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
pc.deleted(Customer.class, 42);
|
||||
@@ -118,21 +122,21 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void size_when_empty() throws Exception {
|
||||
public void size_when_empty() {
|
||||
|
||||
PersistenceContext pc = pc();
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void size_when_some() throws Exception {
|
||||
public void size_when_some() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clear() throws Exception {
|
||||
public void clear() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
pc.clear();
|
||||
@@ -140,7 +144,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearClass() throws Exception {
|
||||
public void clearClass() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
pc.clear(Customer.class);
|
||||
@@ -148,7 +152,7 @@ public class DefaultPersistenceContextTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearClassAndId() throws Exception {
|
||||
public void clearClassAndId() {
|
||||
|
||||
PersistenceContext pc = pcWith42();
|
||||
pc.put(Customer.class, 43, new Customer());
|
||||
@@ -159,4 +163,94 @@ public class DefaultPersistenceContextTest {
|
||||
pc.clear(Customer.class, 43);
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forIterate() {
|
||||
final DefaultPersistenceContext pc = pcWith42();
|
||||
// act
|
||||
final PersistenceContext pcIterate = pc.forIterate();
|
||||
assertThat(pc).isNotSameAs(pcIterate);
|
||||
assertThat(pcIterate.size(Customer.class)).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forIterate_many() {
|
||||
DefaultPersistenceContext pc = new DefaultPersistenceContext();
|
||||
addCustomers(pc, 1, 100);
|
||||
addContacts(pc, 1, 1010);
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(100);
|
||||
assertThat(pc.size(Contact.class)).isEqualTo(1010);
|
||||
|
||||
// act
|
||||
final PersistenceContext pcIterate = pc.forIterate();
|
||||
assertThat(pcIterate.size(Customer.class)).isEqualTo(100);
|
||||
assertThat(pcIterate.size(Contact.class)).isEqualTo(1010);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forIterate_resetLimit_forIterateReset() {
|
||||
DefaultPersistenceContext initialPc = new DefaultPersistenceContext();
|
||||
addCustomers(initialPc, 1, 100);
|
||||
addContacts(initialPc, 1, 1010);
|
||||
|
||||
final PersistenceContext pcIterate = initialPc.forIterate();
|
||||
assertFalse(pcIterate.resetLimit());
|
||||
|
||||
// added 900 NEW contact beans
|
||||
addContacts(pcIterate, 2000, 900);
|
||||
assertThat(pcIterate.size(Contact.class)).isEqualTo(1910);
|
||||
assertFalse(pcIterate.resetLimit());
|
||||
|
||||
// boundary, added 1000 NEW contact beans (still false)
|
||||
addContacts(pcIterate, 3000, 100);
|
||||
assertFalse(pcIterate.resetLimit());
|
||||
|
||||
addContacts(pcIterate, 4000, 1);
|
||||
addProducts(pcIterate, 1, 100);
|
||||
// ACT - over 1000 added beans boundary for contacts so returns true
|
||||
assertTrue(pcIterate.resetLimit());
|
||||
|
||||
assertThat(pcIterate.size(Contact.class)).isEqualTo(2011);
|
||||
assertThat(pcIterate.size(Customer.class)).isEqualTo(100);
|
||||
assertThat(pcIterate.size(Product.class)).isEqualTo(100);
|
||||
|
||||
// ACT - obtain new PC forIterateReset
|
||||
PersistenceContext pcReset = pcIterate.forIterateReset();
|
||||
|
||||
// keeps original customer beans as new added beans there
|
||||
assertThat(pcReset.size(Customer.class)).isEqualTo(100); // customers didn't change
|
||||
// added beans to contacts and products so those where reset
|
||||
assertThat(pcReset.size(Contact.class)).isEqualTo(0);
|
||||
assertThat(pcReset.size(Product.class)).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toString_sillyTest() {
|
||||
DefaultPersistenceContext pc = pcWith42();
|
||||
assertThat(pc.toString()).contains("org.tests.model.basic.Customer");
|
||||
}
|
||||
|
||||
private void addCustomers(PersistenceContext pc, int start, int loop) {
|
||||
for (int i = start; i < start + loop; i++) {
|
||||
Customer bean = new Customer();
|
||||
bean.setId(i);
|
||||
pc.put(Customer.class, i, bean);
|
||||
}
|
||||
}
|
||||
|
||||
private void addContacts(PersistenceContext pc, int start, int loop) {
|
||||
for (int i = start; i < start + loop; i++) {
|
||||
Contact bean = new Contact();
|
||||
bean.setId(i);
|
||||
pc.put(Contact.class, i, bean);
|
||||
}
|
||||
}
|
||||
|
||||
private void addProducts(PersistenceContext pc, int start, int loop) {
|
||||
for (int i = start; i < start + loop; i++) {
|
||||
Product bean = new Product();
|
||||
bean.setId(i);
|
||||
pc.put(Product.class, i, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package main;
|
||||
|
||||
import io.ebean.docker.commands.MariaDBConfig;
|
||||
import io.ebean.docker.commands.MariaDBContainer;
|
||||
|
||||
public class StartMariaDb {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
MariaDBConfig config = new MariaDBConfig("10.5");
|
||||
config.setDbName("unit");
|
||||
config.setUser("unit");
|
||||
config.setPassword("unit");
|
||||
|
||||
MariaDBContainer container = new MariaDBContainer(config);
|
||||
container.startWithDropCreate();
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class TestAggregateFormula extends BaseTestCase {
|
||||
|
||||
@IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.NUODB})
|
||||
@IgnorePlatform({Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB, Platform.NUODB})
|
||||
@Test
|
||||
public void minDistinctOrderByNulls() {
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ public class TestMetaAnnotation extends BaseTestCase {
|
||||
* This test writes 101 spaces to "line1" which is annotated with @Size(max=100).
|
||||
*/
|
||||
@Test
|
||||
@IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL}) // pg & mssql does not fail if string is too long.
|
||||
@IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB}) // pg & mssql does not fail if string is too long.
|
||||
public void testWrite101SpacesToLine1() {
|
||||
|
||||
Address address = new Address();
|
||||
@@ -66,7 +66,7 @@ public class TestMetaAnnotation extends BaseTestCase {
|
||||
* This test writes 101 spaces to "line1" which is meta-annotated with {@link SizeMedium}.
|
||||
*/
|
||||
@Test
|
||||
@IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL})
|
||||
@IgnorePlatform({Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testWrite101SpacesToLine2() {
|
||||
|
||||
Address address = new Address();
|
||||
|
||||
@@ -23,7 +23,7 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
|
||||
|
||||
@Test
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL})
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
@@ -41,7 +41,7 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL})
|
||||
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate_when_alreadyInPC() {
|
||||
|
||||
EBasic basic = new EBasic("test PC cache");
|
||||
|
||||
@@ -55,6 +55,49 @@ public class TestEncrypt extends BaseTestCase {
|
||||
assertThat(loggedSql.get(1)).contains("left join e_basicenc t1 on t1.id = t0.other_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDto() {
|
||||
DB.find(EBasicEncrypt.class).delete();
|
||||
|
||||
EBasicEncrypt e = new EBasicEncrypt();
|
||||
e.setName("name2");
|
||||
e.setDescription("descEncrypted2");
|
||||
e.setDob(new Date(System.currentTimeMillis() - 100000));
|
||||
|
||||
DB.save(e);
|
||||
|
||||
final EDto dto = DB.find(EBasicEncrypt.class)
|
||||
.select("name, description")
|
||||
.asDto(EDto.class)
|
||||
.findOne();
|
||||
|
||||
assertThat(dto).isNotNull();
|
||||
assertThat(dto.getName()).isEqualTo("name2");
|
||||
assertThat(dto.getDescription()).isEqualTo("descEncrypted2");
|
||||
}
|
||||
|
||||
public static class EDto {
|
||||
String name;
|
||||
String description;
|
||||
public EDto(){
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.H2)
|
||||
public void test() {
|
||||
|
||||
+45
-17
@@ -2,7 +2,7 @@ package org.tests.cache;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheStatistics;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
@@ -27,37 +27,66 @@ public class TestBeanCache extends BaseTestCase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TestBeanCache.class);
|
||||
|
||||
private ServerCache beanCache = DB.getDefault().getServerCacheManager().getBeanCache(OCachedBean.class);
|
||||
private final ServerCache beanCache = DB.getDefault().getServerCacheManager().getBeanCache(OCachedBean.class);
|
||||
|
||||
@Test
|
||||
public void findById_when_idTypeConverted() {
|
||||
|
||||
OCachedBean bean = new OCachedBean();
|
||||
bean.setName("findById");
|
||||
Ebean.save(bean);
|
||||
DB.save(bean);
|
||||
|
||||
OCachedBean bean0 = Ebean.find(OCachedBean.class, bean.getId());
|
||||
OCachedBean bean0 = DB.find(OCachedBean.class, bean.getId());
|
||||
assertNotNull(bean0);
|
||||
|
||||
// expect to hit the cache, no SQL
|
||||
LoggedSqlCollector.start();
|
||||
OCachedBean bean1 = Ebean.find(OCachedBean.class, bean.getId());
|
||||
OCachedBean bean1 = DB.find(OCachedBean.class, bean.getId());
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertNotNull(bean1);
|
||||
assertThat(sql).isEmpty();
|
||||
|
||||
// expect to hit the cache, no SQL
|
||||
LoggedSqlCollector.start();
|
||||
OCachedBean bean2 = Ebean.find(OCachedBean.class).setReadOnly(true).setId(String.valueOf(bean.getId())).findOne();
|
||||
OCachedBean bean2 = DB.find(OCachedBean.class).setReadOnly(true).setId(String.valueOf(bean.getId())).findOne();
|
||||
sql = LoggedSqlCollector.stop();
|
||||
assertNotNull(bean2);
|
||||
assertThat(sql).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idsIn_explicitCache_expect_cachePut() {
|
||||
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("k0","k1"));
|
||||
List<Long> ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList());
|
||||
|
||||
beanCache.clear();
|
||||
beanCache.getStatistics(true);
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
|
||||
// skipCacheAfterWrite set after this write ...
|
||||
final OCachedBean junk = createBean("junk");
|
||||
DB.save(junk);
|
||||
|
||||
List<OCachedBean> list = DB.find(OCachedBean.class)
|
||||
.where().idIn(ids)
|
||||
.setUseCache(true)
|
||||
.findList();
|
||||
|
||||
assertThat(list).hasSize(2);
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
ServerCacheStatistics statistics = beanCache.getStatistics(true);
|
||||
assertThat(statistics.getHitCount()).isEqualTo(0);
|
||||
assertThat(statistics.getMissCount()).isEqualTo(2);
|
||||
assertThat(statistics.getPutCount()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idsInExpression() {
|
||||
|
||||
List<OCachedBean> beans = createBeans();
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("z0", "z1", "z2"));
|
||||
List<Long> ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList());
|
||||
|
||||
beanCache.clear();
|
||||
@@ -134,26 +163,25 @@ public class TestBeanCache extends BaseTestCase {
|
||||
assertThat(statistics.getMissCount()).isEqualTo(missCount);
|
||||
}
|
||||
|
||||
private List<OCachedBean> createBeans() {
|
||||
|
||||
List<String> names = Arrays.asList("z0", "z1", "z2");
|
||||
|
||||
private List<OCachedBean> createBeans(List<String> names) {
|
||||
List<OCachedBean> beans = new ArrayList<>();
|
||||
for (String name : names) {
|
||||
OCachedBean bean = new OCachedBean();
|
||||
bean.setName(name);
|
||||
beans.add(bean);
|
||||
beans.add(createBean(name));
|
||||
}
|
||||
|
||||
DB.saveAll(beans);
|
||||
|
||||
return beans;
|
||||
}
|
||||
|
||||
private OCachedBean createBean(String name) {
|
||||
OCachedBean bean = new OCachedBean();
|
||||
bean.setName(name);
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void find_whenNotExits() {
|
||||
|
||||
Country country = Ebean.find(Country.class)
|
||||
Country country = DB.find(Country.class)
|
||||
.where()
|
||||
.eq("name","NotValid")
|
||||
.findOne();
|
||||
|
||||
@@ -26,7 +26,7 @@ public class TestDefaults extends BaseTestCase {
|
||||
final List<String> current = LoggedSqlCollector.current();
|
||||
|
||||
assertThat(current).isNotEmpty();
|
||||
if (isMySql()) {
|
||||
if (isMySql() || isMariaDB()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft values (default);");
|
||||
} else if (isSqlServer()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft (id) values (?)");
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.tests.delete;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
@@ -21,15 +21,54 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
private void createUser(String name) {
|
||||
BBookmarkUser u1 = new BBookmarkUser(name);
|
||||
DB.save(u1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB})
|
||||
public void deleteWithLimit() {
|
||||
createUser("deleteWithLimit1");
|
||||
createUser("deleteWithLimit2");
|
||||
createUser("deleteWithLimit3");
|
||||
createUser("deleteWithLimit4");
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
final int rows = DB.find(BBookmarkUser.class)
|
||||
.where().startsWith("name", "deleteWithLimit")
|
||||
.setMaxRows(3)
|
||||
.delete();
|
||||
|
||||
assertThat(rows).isEqualTo(3);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
if (isSqlServer()) {
|
||||
assertSql(sql.get(0)).contains("delete from bbookmark_user where id in (select top 3 t0.id from bbookmark_user t0 where t0.name like ");
|
||||
} else {
|
||||
assertSql(sql.get(0)).contains("delete from bbookmark_user where id in (select t0.id from bbookmark_user t0 where t0.name like");
|
||||
if (isH2() || isPostgres()) {
|
||||
assertSql(sql.get(0)).contains("limit 3");
|
||||
}
|
||||
}
|
||||
|
||||
final int rowsAfter = DB.find(BBookmarkUser.class)
|
||||
.where().startsWith("name", "deleteWithLimit")
|
||||
.setMaxRows(3)
|
||||
.delete();
|
||||
|
||||
assertThat(rowsAfter).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.MYSQL)
|
||||
// FIXME: MySql does not the sub query selecting from the delete table
|
||||
public void deleteWithSubquery() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database server = DB.getDefault();
|
||||
|
||||
BBookmarkUser u1 = new BBookmarkUser("u1");
|
||||
Ebean.save(u1);
|
||||
DB.save(u1);
|
||||
|
||||
Query<BBookmarkUser> query = server.find(BBookmarkUser.class)
|
||||
.where().eq("org.name", "NahYeahMaybe")
|
||||
@@ -71,7 +110,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
// FIXME: MySql does not the sub query selecting from the delete table
|
||||
public void deleteWithSubquery_withEscalation() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database server = DB.getDefault();
|
||||
|
||||
Query<Contact> query = server.find(Contact.class).where().eq("group.name", "NahYeahMaybe").query();
|
||||
|
||||
@@ -104,8 +143,8 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(BBookmarkUser.class).where().eq("id", 7000).delete();
|
||||
Ebean.find(BBookmarkUser.class).setId(7000).delete();
|
||||
DB.find(BBookmarkUser.class).where().eq("id", 7000).delete();
|
||||
DB.find(BBookmarkUser.class).setId(7000).delete();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
if (isPlatformSupportsDeleteTableAlias()) {
|
||||
@@ -117,7 +156,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
}
|
||||
|
||||
// and note this is the easiest option
|
||||
Ebean.delete(BBookmarkUser.class, 7000);
|
||||
DB.delete(BBookmarkUser.class, 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,8 +164,8 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(Contact.class).where().eq("id", 7000).delete();
|
||||
Ebean.find(Contact.class).setId(7000).delete();
|
||||
DB.find(Contact.class).where().eq("id", 7000).delete();
|
||||
DB.find(Contact.class).setId(7000).delete();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
// escalate to fetch ids then delete ... but no rows found
|
||||
@@ -134,7 +173,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
assertSql(sql.get(1)).contains("select t0.id from contact t0 where t0.id = ?");
|
||||
|
||||
// and note this is the easiest option
|
||||
Ebean.delete(Contact.class, 7000);
|
||||
DB.delete(Contact.class, 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,10 +181,10 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setPersistCascade(false);
|
||||
|
||||
Ebean.find(Contact.class).where().eq("id", 7001).delete();
|
||||
DB.find(Contact.class).where().eq("id", 7001).delete();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
@@ -163,7 +202,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(Customer.class)
|
||||
DB.find(Customer.class)
|
||||
.where().eq("name", "Don Roberto")
|
||||
.query().forUpdate()
|
||||
.delete();
|
||||
@@ -181,11 +220,11 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
public void deleteByPredicate() {
|
||||
|
||||
BBookmarkUser ud = new BBookmarkUser("deleteQueryByPredicate");
|
||||
Ebean.save(ud);
|
||||
DB.save(ud);
|
||||
|
||||
Ebean.find(BBookmarkUser.class).where().eq("name", "deleteQueryByPredicate").delete();
|
||||
DB.find(BBookmarkUser.class).where().eq("name", "deleteQueryByPredicate").delete();
|
||||
|
||||
BBookmarkUser found = Ebean.find(BBookmarkUser.class, ud.getId());
|
||||
BBookmarkUser found = DB.find(BBookmarkUser.class, ud.getId());
|
||||
assertThat(found).isNull();
|
||||
}
|
||||
|
||||
@@ -200,11 +239,11 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
contact.setLastName("deleteMe");
|
||||
contact.setCustomer(all.get(0));
|
||||
|
||||
Ebean.save(contact);
|
||||
DB.save(contact);
|
||||
|
||||
Ebean.find(Contact.class).where().eq("firstName", "DelByQueryFirstName").delete();
|
||||
DB.find(Contact.class).where().eq("firstName", "DelByQueryFirstName").delete();
|
||||
|
||||
Contact contactFind = Ebean.find(Contact.class, contact.getId());
|
||||
Contact contactFind = DB.find(Contact.class, contact.getId());
|
||||
assertThat(contactFind).isNull();
|
||||
}
|
||||
|
||||
@@ -214,13 +253,13 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
Country country = new Country();
|
||||
country.setCode("XX");
|
||||
country.setName("SecretName");
|
||||
Ebean.save(country);
|
||||
Query<Country> query = Ebean.find(Country.class).where().eq("name", "SecretName").setUseQueryCache(true);
|
||||
DB.save(country);
|
||||
Query<Country> query = DB.find(Country.class).where().eq("name", "SecretName").setUseQueryCache(true);
|
||||
|
||||
assertThat(query.findList()).hasSize(1);
|
||||
assertThat(query.findCount()).isEqualTo(1);
|
||||
|
||||
Ebean.find(Country.class).where().eq("name", "SecretName").delete();
|
||||
DB.find(Country.class).where().eq("name", "SecretName").delete();
|
||||
//Ebean.getDefaultServer().getPluginApi().getBeanType(Country.class).clearQueryCache();
|
||||
assertThat(query.findList()).hasSize(0);
|
||||
assertThat(query.findCount()).isEqualTo(0);
|
||||
|
||||
@@ -1,40 +1,80 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.o2m.OmBasicChild;
|
||||
import org.tests.o2m.OmBasicParent;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class TestQueryFindEach extends BaseTestCase {
|
||||
|
||||
private final Random random = new Random();
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query
|
||||
= server.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).order("id")
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.fetch("contacts", new FetchConfig().query(2))
|
||||
.where().gt("id", 0).order("id")
|
||||
.setMaxRows(2).query();
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
query.findEach(customer -> {
|
||||
counter.incrementAndGet();
|
||||
customer.getName();
|
||||
assertNotNull(customer.getName());
|
||||
});
|
||||
|
||||
Assert.assertEquals(2, counter.get());
|
||||
assertEquals(2, counter.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void persistenceContext_scope() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Contact> query = DB.find(Contact.class);
|
||||
|
||||
try (final Transaction transaction = DB.beginTransaction()) {
|
||||
// effectively loads customers into persistence context
|
||||
final List<Customer> customerList = DB.find(Customer.class)
|
||||
.select("name")
|
||||
.findList();
|
||||
|
||||
SpiTransaction spiTxn = (SpiTransaction) transaction;
|
||||
PersistenceContext pc = spiTxn.getPersistenceContext();
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(customerList.size());
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
query.findEach(contact -> {
|
||||
// use customer from persistence context (otherwise would invoke lazy loading)
|
||||
assertNotNull(contact.getCustomer().getName());
|
||||
});
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,10 +85,9 @@ public class TestQueryFindEach extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class).setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).order("id")
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.fetch("contacts", new FetchConfig().query(2))
|
||||
.where().gt("id", 0).order("id")
|
||||
.setMaxRows(2).query();
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
@@ -60,6 +99,47 @@ public class TestQueryFindEach extends BaseTestCase {
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertFalse("Never get here - exception thrown", true);
|
||||
fail("Never get here - exception thrown");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void iterateResetLimit() {
|
||||
|
||||
DB.find(OmBasicChild.class).delete();
|
||||
DB.find(OmBasicParent.class).delete();
|
||||
insertData();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
try (final Transaction transaction = DB.beginTransaction()) {
|
||||
// DB.find(OmBasicParent.class).findList();
|
||||
DB.find(OmBasicChild.class)
|
||||
.setLazyLoadBatchSize(100)
|
||||
//.fetchQuery("parent","name")
|
||||
//.fetch("parent","name")
|
||||
.findEach(child -> {
|
||||
assertNotNull(child.getParent().getName());
|
||||
});
|
||||
}
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.size()).isLessThan(50);
|
||||
}
|
||||
|
||||
@Transactional(batchSize = 40)
|
||||
private void insertData() {
|
||||
for (int i = 0; i < 150; i++) {
|
||||
insertData2(i);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertData2(int i) {
|
||||
OmBasicParent p = new OmBasicParent("bl_" + i);
|
||||
DB.save(p);
|
||||
|
||||
int children = 20 + random.nextInt(10);
|
||||
for (int j = 0; j < children; j++) {
|
||||
OmBasicChild c = new OmBasicChild("bl_" + i + "_" + j, p);
|
||||
DB.save(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.Query;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class TestQueryFindEachWhile extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
@@ -19,10 +21,8 @@ public class TestQueryFindEachWhile extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query
|
||||
= server.find(Customer.class)
|
||||
= DB.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).order("id")
|
||||
.setMaxRows(2).query();
|
||||
@@ -31,11 +31,11 @@ public class TestQueryFindEachWhile extends BaseTestCase {
|
||||
|
||||
query.findEachWhile(customer -> {
|
||||
counter.incrementAndGet();
|
||||
customer.getName();
|
||||
assertNotNull(customer.getName());
|
||||
return true;
|
||||
});
|
||||
|
||||
Assert.assertEquals(2, counter.get());
|
||||
assertEquals(2, counter.get());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,9 +46,7 @@ public class TestQueryFindEachWhile extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class).setAutoTune(false)
|
||||
Query<Customer> query = DB.find(Customer.class).setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).order("id")
|
||||
.setMaxRows(2).query();
|
||||
|
||||
@@ -62,6 +60,6 @@ public class TestQueryFindEachWhile extends BaseTestCase {
|
||||
return true;
|
||||
});
|
||||
|
||||
Assert.assertFalse("Never get here - exception thrown", true);
|
||||
fail("Never get here - exception thrown");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.datasource.DataSourcePool;
|
||||
@@ -32,9 +31,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setMaxRows(2);
|
||||
|
||||
final AtomicInteger count = new AtomicInteger();
|
||||
@@ -54,9 +51,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
public void test_hasNext_hasNext() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
QueryIterator<Customer> queryIterator = server.find(Customer.class)
|
||||
QueryIterator<Customer> queryIterator = DB.find(Customer.class)
|
||||
.where()
|
||||
.isNotNull("name")
|
||||
.setMaxRows(3)
|
||||
@@ -89,9 +84,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
//.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).orderBy("id")
|
||||
.setMaxRows(2);
|
||||
@@ -108,7 +101,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Ebean.find(Order.class)
|
||||
DB.find(Order.class)
|
||||
//.select("orderDate")
|
||||
.where().gt("id", 0).le("id", 10)
|
||||
.findEach(order -> {
|
||||
@@ -129,7 +122,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(Order.class)
|
||||
DB.find(Order.class)
|
||||
.setLazyLoadBatchSize(10)
|
||||
.select("status, orderDate")
|
||||
.fetch("customer", "name")
|
||||
@@ -159,10 +152,10 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
// make sure we don't hit the L2 cache for order shipments
|
||||
Ebean.getServerCacheManager().clear(Order.class);
|
||||
Ebean.getServerCacheManager().clear(OrderShipment.class);
|
||||
DB.getServerCacheManager().clear(Order.class);
|
||||
DB.getServerCacheManager().clear(OrderShipment.class);
|
||||
|
||||
Ebean.find(Order.class)
|
||||
DB.find(Order.class)
|
||||
.setLazyLoadBatchSize(10)
|
||||
.setUseCache(false)
|
||||
.select("status, orderDate")
|
||||
@@ -190,10 +183,8 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
// intentionally a query with incorrect type binding
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.where().gt("id", "JUNK_NOT_A_LONG")
|
||||
.setMaxRows(2).query();
|
||||
@@ -203,11 +194,11 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
});
|
||||
|
||||
if (!server.getName().equals("h2")) {
|
||||
if (!DB.getDefault().getName().equals("h2")) {
|
||||
// MySql allows the query with type conversion?
|
||||
throw new PersistenceException("H2 does expected thing but MySql does not");
|
||||
}
|
||||
assertTrue("Never get here as exception thrown", false);
|
||||
fail("Never get here as exception thrown");
|
||||
}
|
||||
|
||||
|
||||
@@ -216,9 +207,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.setAutoTune(false)
|
||||
.where().gt("id", 0)
|
||||
.setMaxRows(2).query();
|
||||
@@ -231,7 +220,16 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseConnection() {
|
||||
public void testCloseConnection_findIterate() {
|
||||
findIterateCloseConnection(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseConnection_findIterate_withBatchLoad() {
|
||||
findIterateCloseConnection(true);
|
||||
}
|
||||
|
||||
public void findIterateCloseConnection(boolean withLoadBatch) {
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiServer pluginApi = server().getPluginApi();
|
||||
@@ -241,12 +239,17 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
}
|
||||
|
||||
int startConns = dsPool.getStatus(false).getBusy();
|
||||
QueryIterator<Customer> queryIterator = server().find(Customer.class)
|
||||
.where()
|
||||
.isNotNull("name")
|
||||
.setMaxRows(3)
|
||||
.order().asc("id")
|
||||
.findIterate();
|
||||
final Query<Customer> query = server().find(Customer.class)
|
||||
.where()
|
||||
.isNotNull("name")
|
||||
.setMaxRows(3)
|
||||
.order().asc("id");
|
||||
|
||||
if (withLoadBatch) {
|
||||
query.setLazyLoadBatchSize(1);
|
||||
}
|
||||
|
||||
QueryIterator<Customer> queryIterator = query.findIterate();
|
||||
|
||||
assertThat(dsPool.getStatus(false).getBusy()).isEqualTo(startConns + 1);
|
||||
|
||||
@@ -267,7 +270,8 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
try {
|
||||
queryIterator.next();
|
||||
fail("noSuchElementException expected");
|
||||
} catch (NoSuchElementException e) {}
|
||||
|
||||
} catch (NoSuchElementException e) {
|
||||
logger.debug("Expected NoSuchElementException");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.Query;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class TestQueryFindVisit extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class).setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0)
|
||||
.order("id")
|
||||
.setMaxRows(2).query();
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
query.findEach(bean -> counter.incrementAndGet());
|
||||
|
||||
Assert.assertEquals(2, counter.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the behaviour when an exception is thrown inside the findVisit().
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testVisitThrowingException() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class).setAutoTune(false)
|
||||
.fetch("contacts", new FetchConfig().query(2)).where().gt("id", 0).order("id")
|
||||
.setMaxRows(2).query();
|
||||
|
||||
final AtomicInteger counter = new AtomicInteger(0);
|
||||
|
||||
query.findEach(bean -> {
|
||||
counter.incrementAndGet();
|
||||
if (counter.intValue() > 0) {
|
||||
throw new IllegalStateException("cause a failure");
|
||||
}
|
||||
});
|
||||
|
||||
Assert.assertFalse("Never get here - exception thrown", true);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -17,7 +17,7 @@ public class TestQueryInIdTypeConversion extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<Customer> list = Ebean.find(Customer.class).where().idIn("1", "2").findList();
|
||||
List<Customer> list = DB.find(Customer.class).where().idIn("1", "2").findList();
|
||||
assertThat(list).isNotEmpty();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,13 @@ public class TestQueryInIdTypeConversion extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<Customer> list = Ebean.find(Customer.class).where().idIn().findList();
|
||||
List<Customer> list = DB.find(Customer.class).where().idIn().findList();
|
||||
assertThat(list).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_emptyList_idIn() {
|
||||
List<Customer> list = DB.find(Customer.class).where().idIn(new Object[] {}).findList();
|
||||
assertThat(list).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Expr;
|
||||
import io.ebean.Query;
|
||||
@@ -57,7 +58,7 @@ public class TestWhereRawClause extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = Ebean.find(Customer.class)
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.where()
|
||||
.raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
|
||||
.query();
|
||||
|
||||
@@ -41,7 +41,7 @@ public class TestOrderByWithDistinct extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.SQLSERVER, Platform.NUODB}) // do not support nulls first/last
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB, Platform.SQLSERVER, Platform.NUODB}) // do not support nulls first/last
|
||||
public void testDistinctOn() {
|
||||
|
||||
MRole role = Ebean.getReference(MRole.class, 1);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package org.tests.query.other;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -12,6 +11,7 @@ import org.tests.model.basic.ResetBasicData;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class TestQueryRowCountWithMany extends BaseTestCase {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class TestQueryRowCountWithMany extends BaseTestCase {
|
||||
|
||||
Long productId = 1L;
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.fetch("details")
|
||||
.where().eq("details.product.id", productId)
|
||||
.order("cretime asc").query();
|
||||
@@ -66,8 +66,8 @@ public class TestQueryRowCountWithMany extends BaseTestCase {
|
||||
|
||||
List<String> sqlLogged = LoggedSqlCollector.stop();
|
||||
|
||||
Assert.assertEquals(list.size(), rowCount);
|
||||
Assert.assertEquals(2, sqlLogged.size());
|
||||
assertEquals(list.size(), rowCount);
|
||||
assertEquals(2, sqlLogged.size());
|
||||
assertThat(trimSql(sqlLogged.get(1), 1)).contains(
|
||||
"select count(*) from ( select distinct t0.id from o_order t0 join o_order_detail u1 on u1.order_id = t0.id where u1.product_id = ?)");
|
||||
|
||||
@@ -81,19 +81,20 @@ public class TestQueryRowCountWithMany extends BaseTestCase {
|
||||
|
||||
Long productId = 1L;
|
||||
|
||||
Query<Order> query = Ebean.find(Order.class)
|
||||
Query<Order> query = DB.find(Order.class)
|
||||
.fetch("details")
|
||||
.where().eq("details.product.id", productId)
|
||||
.setFirstRow(2)
|
||||
.setMaxRows(20)
|
||||
.orderBy("cretime asc");
|
||||
.orderBy("cretime asc")
|
||||
.query();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
query.findCount();
|
||||
|
||||
List<String> sqlLogged = LoggedSqlCollector.stop();
|
||||
|
||||
Assert.assertEquals(1, sqlLogged.size());
|
||||
assertEquals(1, sqlLogged.size());
|
||||
assertThat(trimSql(sqlLogged.get(0), 1)).contains("select count(*) from ( select distinct t0.id from o_order t0 join o_order_detail u1 on u1.order_id = t0.id where u1.product_id = ?)");
|
||||
|
||||
query.findList();
|
||||
|
||||
@@ -26,7 +26,7 @@ public class TestWhereLikeWithSlash extends BaseTestCase {
|
||||
Query<EBasic> query1 = Ebean.find(EBasic.class).where().like("name", "slash\\mon%").query();
|
||||
List<EBasic> list1 = query1.findList();
|
||||
|
||||
if (!isMySql() && !isNuoDb()) {
|
||||
if (!isMySql() && !isNuoDb() && !isMariaDB()) {
|
||||
// For mysql this assert depends on no_backslash_escapes setting so we won't assert here
|
||||
// Still good on Postgres which was the original issue
|
||||
assertEquals(1, list1.size());
|
||||
|
||||
@@ -117,7 +117,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.SQLSERVER})
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB, Platform.SQLSERVER})
|
||||
public void test_upperCaseSql() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.tests.text.csv;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import org.junit.Test;
|
||||
@@ -10,7 +10,6 @@ import org.tests.model.basic.ResetBasicData;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TestCsvReader extends TransactionalTestCase {
|
||||
|
||||
@@ -25,7 +24,7 @@ public class TestCsvReader extends TransactionalTestCase {
|
||||
|
||||
FileReader reader = new FileReader(f);
|
||||
|
||||
CsvReader<Customer> csvReader = Ebean.createCsvReader(Customer.class);
|
||||
CsvReader<Customer> csvReader = DB.getDefault().createCsvReader(Customer.class);
|
||||
|
||||
csvReader.setPersistBatchSize(2);
|
||||
|
||||
@@ -33,7 +32,7 @@ public class TestCsvReader extends TransactionalTestCase {
|
||||
// csvReader.addProperty("id");
|
||||
csvReader.addProperty("status");
|
||||
csvReader.addProperty("name");
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.GERMAN);
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
|
||||
csvReader.addProperty("billingAddress.line1");
|
||||
csvReader.addProperty("billingAddress.city");
|
||||
csvReader.addProperty("billingAddress.country.code");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.tests.text.csv;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.csv.DefaultCsvCallback;
|
||||
@@ -11,7 +10,6 @@ import org.tests.model.basic.Customer;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -25,9 +23,7 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
|
||||
FileReader reader = new FileReader(f);
|
||||
|
||||
final EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
CsvReader<Customer> csvReader = server.createCsvReader(Customer.class);
|
||||
CsvReader<Customer> csvReader = DB.getDefault().createCsvReader(Customer.class);
|
||||
|
||||
csvReader.setPersistBatchSize(2);
|
||||
csvReader.setLogInfoFrequency(3);
|
||||
@@ -36,13 +32,13 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
// csvReader.addProperty("id");
|
||||
csvReader.addProperty("status");
|
||||
csvReader.addProperty("name");
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.GERMAN);
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
|
||||
csvReader.addProperty("billingAddress.line1");
|
||||
csvReader.addProperty("billingAddress.city");
|
||||
// processor.addReference("billingAddress.country.code");
|
||||
csvReader.addProperty("billingAddress.country.code");
|
||||
|
||||
int before = Ebean.find(Customer.class).findCount();
|
||||
int before = DB.find(Customer.class).findCount();
|
||||
|
||||
csvReader.process(reader, new DefaultCsvCallback<Customer>() {
|
||||
|
||||
@@ -56,9 +52,8 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
|
||||
});
|
||||
|
||||
int after = Ebean.find(Customer.class).findCount();
|
||||
int after = DB.find(Customer.class).findCount();
|
||||
assertThat(after).isEqualTo(before + 9);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ public class TestNewTypes extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testInsertUpdate() throws InterruptedException {
|
||||
|
||||
DB.find(SomeNewTypesBean.class).delete();
|
||||
|
||||
SomeNewTypesBean bean = new SomeNewTypesBean();
|
||||
bean.setLocalDate(LocalDate.now());
|
||||
bean.setLocalDateTime(LocalDateTime.now());
|
||||
@@ -65,55 +68,55 @@ public class TestNewTypes extends BaseTestCase {
|
||||
DB.save(bean);
|
||||
Thread.sleep(DB_CLOCK_DELTA); // wait, to ensure that instant < Instant.now()
|
||||
List<SomeNewTypesBean> list = DB.find(SomeNewTypesBean.class).where().lt("instant", Instant.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("localDate", LocalDate.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().lt("localDateTime", LocalDateTime.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().lt("offsetDateTime", OffsetDateTime.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().lt("zonedDateTime", ZonedDateTime.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("sqlDate", bean.getSqlDate()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("sqlTime", bean.getSqlTime()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("localTime", LocalTime.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("zoneId", ZoneId.systemDefault().getId()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("zoneOffset", ZonedDateTime.now().getOffset()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("yearMonth", YearMonth.of(2014, 9)).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("monthDay", MonthDay.of(9,22)).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("year", Year.now()).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().le("month", Month.SEPTEMBER).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("path", Paths.get(TEMP_PATH)).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("period", Period.of(4,3,2)).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
list = DB.find(SomeNewTypesBean.class).where().eq("duration", Duration.ofMinutes(5)).findList();
|
||||
assertTrue(!list.isEmpty());
|
||||
assertThat(list).isNotEmpty();
|
||||
|
||||
SomeNewTypesBean fetched = DB.find(SomeNewTypesBean.class, bean.getId());
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package org.tests.update;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
@@ -21,7 +20,7 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (:ids)");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (:ids)");
|
||||
|
||||
sqlUpdate.setParameter("ids", asList(9991, 9992, 9993));
|
||||
sqlUpdate.execute();
|
||||
@@ -39,7 +38,7 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
@Test
|
||||
public void positionParamsExpansion() {
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1)");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1)");
|
||||
|
||||
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
|
||||
sqlUpdate.execute();
|
||||
@@ -53,7 +52,7 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
|
||||
assertEquals("delete from o_customer where id in (?,?)", sqlUpdate.getGeneratedSql());
|
||||
|
||||
sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1)");
|
||||
sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1)");
|
||||
|
||||
sqlUpdate.setParameter(1, asList(9993));
|
||||
sqlUpdate.execute();
|
||||
@@ -64,30 +63,41 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
@Test
|
||||
public void positionParamsExpansion_withPrePost() {
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
|
||||
.setParameter(1, 90)
|
||||
.setParameter(2, asList(9991, 9992, 9993))
|
||||
.setParameter(3, 91);
|
||||
|
||||
sqlUpdate.setParameter(1, 90);
|
||||
sqlUpdate.setParameter(2, asList(9991, 9992, 9993));
|
||||
sqlUpdate.setParameter(3, 91);
|
||||
sqlUpdate.execute();
|
||||
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void positionParamsExpansion_withPrePost_2() {
|
||||
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
|
||||
.setParameter(90)
|
||||
.setParameter(asList(9991, 9992, 9993))
|
||||
.setParameter(91);
|
||||
|
||||
sqlUpdate.execute();
|
||||
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void positionParamsExpansion_withPrePost_usingParam() {
|
||||
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?");
|
||||
sqlUpdate.setParameters(90, asList(9991, 9992, 9993), 91);
|
||||
sqlUpdate.execute();
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
|
||||
.setParameters(90, asList(9991, 9992, 9993), 91);
|
||||
|
||||
sqlUpdate.execute();
|
||||
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void positionParamsExpansion_withPre() {
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where name = ? and id in (?2)");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)");
|
||||
|
||||
sqlUpdate.setParameter(1, "Foo");
|
||||
sqlUpdate.setParameter(2, asList(9991, 9992, 9993));
|
||||
@@ -120,7 +130,7 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
@Test
|
||||
public void positionParamsExpansion_withPost() {
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (?1) and name = ?");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1) and name = ?");
|
||||
|
||||
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
|
||||
sqlUpdate.setParameter(2, "Foo");
|
||||
@@ -253,7 +263,7 @@ public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
|
||||
@Test
|
||||
public void test_multipleLists() {
|
||||
|
||||
SqlUpdate sqlUpdate = Ebean.createSqlUpdate("delete from o_customer where id in (:ids) and name in (:names)");
|
||||
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (:ids) and name in (:names)");
|
||||
|
||||
sqlUpdate.setParameter("ids", asList(9991, 9992, 9993));
|
||||
sqlUpdate.setParameter("names", asList("rob", "jim"));
|
||||
|
||||
@@ -72,8 +72,8 @@ datasource.db.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
datasource.h2.databaseUrl=jdbc:h2:mem:tests
|
||||
datasource.h2.databaseDriver=org.h2.Driver
|
||||
datasource.h2.url=jdbc:h2:mem:tests
|
||||
#datasource.h2.driver=org.h2.Driver
|
||||
datasource.h2.minConnections=1
|
||||
datasource.h2.maxConnections=25
|
||||
#datasource.h2.heartbeatsql=select 1
|
||||
@@ -87,61 +87,57 @@ datasource.h2.poolListener=org.tests.basic.MyTestDataSourcePoolListener
|
||||
datasource.h2multitenant.username=sa
|
||||
datasource.h2multitenant.password=
|
||||
datasource.h2multitenant.url=jdbc:h2:mem:h2multitenant
|
||||
datasource.h2multitenant.driver=org.h2.Driver
|
||||
|
||||
datasource.h2autocommit.autoCommit=true
|
||||
datasource.h2autocommit.username=sa
|
||||
datasource.h2autocommit.password=
|
||||
datasource.h2autocommit.databaseUrl=jdbc:h2:mem:autocommittests
|
||||
datasource.h2autocommit.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2autocommit2.autoCommit=true
|
||||
datasource.h2autocommit2.username=sa
|
||||
datasource.h2autocommit2.password=
|
||||
datasource.h2autocommit2.databaseUrl=jdbc:h2:mem:autocommit2tests
|
||||
datasource.h2autocommit2.databaseDriver=org.h2.Driver
|
||||
datasource.h2autocommit2.url=jdbc:h2:mem:autocommit2tests
|
||||
|
||||
datasource.h2other.username=sa
|
||||
datasource.h2other.password=
|
||||
datasource.h2other.databaseUrl=jdbc:h2:mem:h2other
|
||||
datasource.h2other.databaseDriver=org.h2.Driver
|
||||
datasource.h2other.url=jdbc:h2:mem:h2other
|
||||
|
||||
datasource.h2otherfind.username=sa
|
||||
datasource.h2otherfind.password=
|
||||
datasource.h2otherfind.databaseUrl=jdbc:h2:mem:h2otherfind
|
||||
datasource.h2otherfind.databaseDriver=org.h2.Driver
|
||||
datasource.h2otherfind.url=jdbc:h2:mem:h2otherfind
|
||||
|
||||
datasource.h2ebasicver.username=sa
|
||||
datasource.h2ebasicver.password=
|
||||
datasource.h2ebasicver.databaseUrl=jdbc:h2:mem:h2ebasicver
|
||||
datasource.h2ebasicver.databaseDriver=org.h2.Driver
|
||||
datasource.h2ebasicver.url=jdbc:h2:mem:h2ebasicver
|
||||
|
||||
datasource.h2ebasicver2.username=sa
|
||||
datasource.h2ebasicver2.password=
|
||||
datasource.h2ebasicver2.databaseUrl=jdbc:h2:mem:h2ebasicver
|
||||
datasource.h2ebasicver2.databaseDriver=org.h2.Driver
|
||||
datasource.h2ebasicver2.url=jdbc:h2:mem:h2ebasicver
|
||||
|
||||
datasource.sqlite.username=
|
||||
datasource.sqlite.password=
|
||||
datasource.sqlite.databaseUrl=jdbc:sqlite:mydb.db
|
||||
datasource.sqlite.databaseDriver=org.sqlite.JDBC
|
||||
datasource.sqlite.url=jdbc:sqlite:mydb.db
|
||||
datasource.sqlite.driver=org.sqlite.JDBC
|
||||
datasource.sqlite.isolationlevel=read_uncommitted
|
||||
|
||||
datasource.hsqldb.username=sa
|
||||
datasource.hsqldb.password=
|
||||
datasource.hsqldb.databaseUrl=jdbc:hsqldb:mem:tests
|
||||
datasource.hsqldb.databaseDriver=org.hsqldb.jdbcDriver
|
||||
datasource.hsqldb.url=jdbc:hsqldb:mem:tests
|
||||
|
||||
# Set caseSensitiveCollation to false when using
|
||||
# MySql with case insensitive collation
|
||||
#ebean.mysql.caseSensitiveCollation=false
|
||||
datasource.mysql.username=unit
|
||||
datasource.mysql.password=unit
|
||||
datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/unit
|
||||
datasource.mysql.url=jdbc:mysql://127.0.0.1:4306/unit
|
||||
#datasource.mysql.username=test_ebean
|
||||
#datasource.mysql.password=test
|
||||
#datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/test_ebean
|
||||
datasource.mysql.databaseDriver=com.mysql.cj.jdbc.Driver
|
||||
#datasource.mysql.url=jdbc:mysql://127.0.0.1:4306/test_ebean
|
||||
#datasource.mysql.driver=com.mysql.cj.jdbc.Driver
|
||||
|
||||
datasource.mariadb.username=unit
|
||||
datasource.mariadb.password=unit
|
||||
datasource.mariadb.url=jdbc:mariadb://localhost:4306/unit
|
||||
|
||||
datasource.cockroach.username=root
|
||||
datasource.cockroach.password=
|
||||
@@ -150,23 +146,21 @@ datasource.cockroach.driver=org.postgresql.Driver
|
||||
|
||||
datasource.oracle.username=test_ebean
|
||||
datasource.oracle.password=test
|
||||
datasource.oracle.databaseUrl=jdbc:oracle:thin:@localhost:1521:XE
|
||||
datasource.oracle.databaseDriver=oracle.jdbc.driver.OracleDriver
|
||||
datasource.oracle.url=jdbc:oracle:thin:@localhost:1521:XE
|
||||
#datasource.oracle.driver=oracle.jdbc.driver.OracleDriver
|
||||
|
||||
## set this to use timestamp rather than timestamptz
|
||||
#ebean.postgres.timestamp=timestamp
|
||||
|
||||
datasource.pg.username=unit
|
||||
datasource.pg.password=unit
|
||||
datasource.pg.databaseUrl=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
datasource.pg.databaseDriver=org.postgresql.Driver
|
||||
datasource.pg.url=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
#datasource.pg.capturestacktrace=true
|
||||
datasource.pg.maxStackTraceSize=50
|
||||
|
||||
datasource.pg9.username=unit
|
||||
datasource.pg9.password=unit
|
||||
datasource.pg9.databaseUrl=jdbc:postgresql://127.0.0.1:9432/unit
|
||||
datasource.pg9.databaseDriver=org.postgresql.Driver
|
||||
datasource.pg9.url=jdbc:postgresql://127.0.0.1:9432/unit
|
||||
|
||||
|
||||
#ebean.sqlserver.idType=SEQUENCE
|
||||
@@ -179,29 +173,28 @@ ebean.sqlserver.databasePlatformName=sqlserver17
|
||||
datasource.sqlserver.username=test_ebean
|
||||
datasource.sqlserver.password=SqlS3rv#r
|
||||
datasource.sqlserver.url=jdbc:sqlserver://localhost:1433;databaseName=test_ebean;sendTimeAsDateTime=false
|
||||
datasource.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
#datasource.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
|
||||
datasource.nuodb.schema=test_user
|
||||
datasource.nuodb.username=test_user
|
||||
datasource.nuodb.password=test
|
||||
datasource.nuodb.url=jdbc:com.nuodb://localhost/testdb
|
||||
datasource.nuodb.driver=com.nuodb.jdbc.Driver
|
||||
#datasource.nuodb.driver=com.nuodb.jdbc.Driver
|
||||
|
||||
datasource.db2.username=db2admin
|
||||
datasource.db2.password=veryverysecret#1234
|
||||
datasource.db2.databaseUrl=jdbc:db2://127.0.0.1:50000/SAMPLE
|
||||
datasource.db2.databaseDriver=com.ibm.db2.jcc.DB2Driver
|
||||
datasource.db2.url=jdbc:db2://127.0.0.1:50000/SAMPLE
|
||||
#datasource.db2.driver=com.ibm.db2.jcc.DB2Driver
|
||||
|
||||
datasource.hana.username=EBEAN_TEST
|
||||
datasource.hana.password=Eb3an_test
|
||||
datasource.hana.databaseUrl=jdbc:sap://hxehost:39013/?databaseName=HXE
|
||||
datasource.hana.databaseDriver=com.sap.db.jdbc.Driver
|
||||
datasource.hana.url=jdbc:sap://hxehost:39013/?databaseName=HXE
|
||||
#datasource.hana.driver=com.sap.db.jdbc.Driver
|
||||
|
||||
# parameters for migration test
|
||||
datasource.migrationtest.username=SA
|
||||
datasource.migrationtest.password=SA
|
||||
datasource.migrationtest.databaseUrl=jdbc:h2:mem:migration
|
||||
datasource.migrationtest.databaseDriver=org.h2.Driver
|
||||
datasource.migrationtest.url=jdbc:h2:mem:migration
|
||||
ebean.migrationtest.applyPrefix=V
|
||||
ebean.migrationtest.ddl.generate=false
|
||||
ebean.migrationtest.ddl.run=false
|
||||
@@ -213,8 +206,7 @@ ebean.migrationtest.migration.strict=true
|
||||
# parameters for migration test
|
||||
datasource.migrationtest-history.username=SA
|
||||
datasource.migrationtest-history.password=SA
|
||||
datasource.migrationtest-history.databaseUrl=jdbc:h2:mem:migration
|
||||
datasource.migrationtest-history.databaseDriver=org.h2.Driver
|
||||
datasource.migrationtest-history.url=jdbc:h2:mem:migration
|
||||
ebean.migrationtest-history.applyPrefix=V
|
||||
ebean.migrationtest-history.ddl.generate=false
|
||||
ebean.migrationtest-history.ddl.run=false
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<migration xmlns="http://ebean-orm.github.io/xml/ns/dbmigration">
|
||||
<changeSet type="apply">
|
||||
|
||||
<createTable name="document" withHistory="true" pkName="pk_document">
|
||||
<column name="id" type="bigint" primaryKey="true" references="document_draft.id" foreignKeyName="fk_document_id"/>
|
||||
<column name="short_title" type="varchar(255)"/>
|
||||
</createTable>
|
||||
|
||||
<renameColumn tableName="document" oldName="short_title" newName="title" />
|
||||
|
||||
</changeSet>
|
||||
</migration>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user