mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
162
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddbad284ad | ||
|
|
1fcec429b0 | ||
|
|
c6062fe93e | ||
|
|
d8d35b7dd9 | ||
|
|
590cd07d67 | ||
|
|
5cd74bc468 | ||
|
|
502b20be67 | ||
|
|
b3077d44f6 | ||
|
|
d4b35cb445 | ||
|
|
91e7540a39 | ||
|
|
06bd60aaf7 | ||
|
|
3db2a69312 | ||
|
|
5a983b9e0d | ||
|
|
ab7b34779a | ||
|
|
c7aad6078e | ||
|
|
ccfe9c39cd | ||
|
|
dbdac04883 | ||
|
|
1d369c002d | ||
|
|
5a1be81603 | ||
|
|
dee73da1aa | ||
|
|
a7dde87c5f | ||
|
|
60fadd448d | ||
|
|
0140d09007 | ||
|
|
da5604a38d | ||
|
|
937df1395c | ||
|
|
89c05007c2 | ||
|
|
4cc9278183 | ||
|
|
9841a2c03a | ||
|
|
74929472d9 | ||
|
|
e274a4c512 | ||
|
|
5d93c44475 | ||
|
|
63b802d0b8 | ||
|
|
1d7e751b60 | ||
|
|
5f8690fb87 | ||
|
|
e093675444 | ||
|
|
a04594540c | ||
|
|
269f2de333 | ||
|
|
be12910aec | ||
|
|
996e582a85 | ||
|
|
aa4c6b7889 | ||
|
|
27a4e8951d | ||
|
|
1fc4082abe | ||
|
|
1c5d7a97e1 | ||
|
|
67c2e1d24c | ||
|
|
eb292e017e | ||
|
|
88839f7613 | ||
|
|
ca71fef74a | ||
|
|
6c91ed0c76 | ||
|
|
8761c0486d | ||
|
|
fee6a9f04a | ||
|
|
17ff04e2b9 | ||
|
|
aa11095d17 | ||
|
|
c2a30f786f | ||
|
|
9b0dd2b0c4 | ||
|
|
aa96d10491 | ||
|
|
dfefbecf44 | ||
|
|
738f19491a | ||
|
|
61257bea7f | ||
|
|
566a01d815 | ||
|
|
a7116d1606 | ||
|
|
615a2aea46 | ||
|
|
20d538c428 | ||
|
|
01054bf470 | ||
|
|
affd720390 | ||
|
|
7d77df58c5 | ||
|
|
51fad2dec6 | ||
|
|
997378ce72 | ||
|
|
1a8a43603e | ||
|
|
d2c88bf7c6 | ||
|
|
0929147b08 | ||
|
|
ecab219635 | ||
|
|
7a974320ed | ||
|
|
1b7dc83a9a | ||
|
|
9827d9056f | ||
|
|
c8d5d9b552 | ||
|
|
dac55ab8e9 | ||
|
|
de75bcdaf9 | ||
|
|
5785124a2b | ||
|
|
4d1c0bfaa8 | ||
|
|
9a29c988cd | ||
|
|
80309f844e | ||
|
|
56ddc49ab4 | ||
|
|
1e7de83019 | ||
|
|
1db1f0312a | ||
|
|
d27bf14887 | ||
|
|
d4e7d4eebc | ||
|
|
30c44d0928 | ||
|
|
443c5dba58 | ||
|
|
f24b4dba71 | ||
|
|
a474880735 | ||
|
|
4cfab3a2de | ||
|
|
4807070147 | ||
|
|
e00aa479ae | ||
|
|
b665d8375c | ||
|
|
4e74c68603 | ||
|
|
2694aa3fe1 | ||
|
|
f7a28aa904 | ||
|
|
4bc2559e8e | ||
|
|
c2faf0e0a7 | ||
|
|
895b331e8f | ||
|
|
8890079b80 | ||
|
|
20dd33ebca | ||
|
|
e2a1489743 | ||
|
|
d6bab46ac3 | ||
|
|
573673ef2b | ||
|
|
eb69499ca3 | ||
|
|
d9323b8ab6 | ||
|
|
a01ba128e5 | ||
|
|
fdc67b3ce5 | ||
|
|
5d433ff603 | ||
|
|
a3f9c4c889 | ||
|
|
769fc485ec | ||
|
|
61ef4fa420 | ||
|
|
8cf37e2f0a | ||
|
|
80a764a448 | ||
|
|
6621c5dfbb | ||
|
|
5e7dda1ec8 | ||
|
|
7bc6368f69 | ||
|
|
fb5a69adea | ||
|
|
0e7607bb27 | ||
|
|
1098b572fe | ||
|
|
7a6662a2dc | ||
|
|
1c6c812d4d | ||
|
|
e58a85f0af | ||
|
|
e3551152bb | ||
|
|
5138d1723f | ||
|
|
9b5ab542d7 | ||
|
|
f0bc4c786c | ||
|
|
b98739bb49 | ||
|
|
fcadc63338 | ||
|
|
3574479627 | ||
|
|
cecf2fc650 | ||
|
|
a1dab24414 | ||
|
|
c12ea28ea9 | ||
|
|
a2b418df8b | ||
|
|
2fb533a606 | ||
|
|
5d89897bbd | ||
|
|
9640e02b6a | ||
|
|
8a0ef33f79 | ||
|
|
d2ece76ca8 | ||
|
|
3495d03706 | ||
|
|
bc90fa50d7 | ||
|
|
777fc0ff30 | ||
|
|
9413f72939 | ||
|
|
1416647d04 | ||
|
|
63bddb4d54 | ||
|
|
6fddd418a1 | ||
|
|
faba55d772 | ||
|
|
ac6db11e3d | ||
|
|
ca7d8ecfc1 | ||
|
|
46eeee68c9 | ||
|
|
c1487daea8 | ||
|
|
b329ae42db | ||
|
|
13429daddc | ||
|
|
98a80295fe | ||
|
|
f8587368ee | ||
|
|
8ae2ae7f8b | ||
|
|
46f3b74b38 | ||
|
|
df51ccd2c4 | ||
|
|
730d43c008 | ||
|
|
81c2c804a6 | ||
|
|
533be356f2 |
@@ -44,4 +44,3 @@ Goto [https://ebean.io/docs/](https://ebean.io/docs/)
|
||||
## Other versions
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent) - ebean-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin) - ebean-maven-plugin
|
||||
|
||||
|
||||
@@ -3,27 +3,27 @@
|
||||
|
||||
<parent>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>java8-parent</artifactId>
|
||||
<version>1.3</version>
|
||||
<artifactId>java8-oss</artifactId>
|
||||
<version>2.1</version>
|
||||
</parent>
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.43.3</version>
|
||||
<version>12.1.8</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
<url>http://ebean-orm.github.io/</url>
|
||||
|
||||
<properties>
|
||||
<jackson-core.version>2.9.9</jackson-core.version>
|
||||
<jackson-databind.version>2.9.9.2</jackson-databind.version>
|
||||
<jackson-core.version>2.10.0</jackson-core.version>
|
||||
<jackson-databind.version>2.10.0</jackson-databind.version>
|
||||
<snakeyaml.version>1.21</snakeyaml.version>
|
||||
</properties>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.43.3</tag>
|
||||
<tag>ebean-12.1.8</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -118,13 +118,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>4.12</version>
|
||||
<version>6.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-types</artifactId>
|
||||
<version>1.3</version>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -133,16 +133,10 @@
|
||||
<version>4.6.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-classpath-scanner</artifactId>
|
||||
<version>3.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>11.20.1</version>
|
||||
<version>12.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -199,7 +193,7 @@
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.4.0-b180830.0438</version>
|
||||
<version>2.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -301,10 +295,9 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>avaje-composite-testing</artifactId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -315,9 +308,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.moduuid</groupId>
|
||||
<artifactId>avaje-moduuid</artifactId>
|
||||
<version>2.1</version>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>mod-uuid</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -330,13 +323,13 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>11.43.2</version>
|
||||
<version>12.1.6</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<transformArgs>debug=1</transformArgs>
|
||||
<transformArgs>debug=0</transformArgs>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>testEnhance</goal>
|
||||
@@ -387,9 +380,9 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 11</doctitle>
|
||||
<doctitle>Ebean 12</doctitle>
|
||||
<overview>src/main/java/io/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
@@ -399,6 +392,8 @@
|
||||
<artifactId>pygments-doclet</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</docletArtifact>
|
||||
<!-- for people using JDK11, our javadoc doclet isn't 11 compatible yet -->
|
||||
<javadocExecutable>${env.JAVA8_HOME}/bin/javadoc</javadocExecutable>
|
||||
<additionalparam>
|
||||
-Xdoclint:none
|
||||
-include-basedir ${project.basedir}
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebean;
|
||||
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.json.JsonContext;
|
||||
@@ -396,15 +395,6 @@ public class DB {
|
||||
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link DatabaseConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
|
||||
* OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
|
||||
* that are in the database but are not in the collection are deleted.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link DatabaseConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
|
||||
* controls if only the changed properties are included in the update or if all the loaded
|
||||
* properties are included instead.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // A 'stateless update' example
|
||||
@@ -414,9 +404,6 @@ public class DB {
|
||||
* database.update(customer);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see DatabaseConfig#setUpdatesDeleteMissingChildren(boolean)
|
||||
* @see DatabaseConfig#setUpdateChangesOnly(boolean)
|
||||
*/
|
||||
public static void update(Object bean) throws OptimisticLockException {
|
||||
getDefault().update(bean);
|
||||
@@ -749,8 +736,11 @@ public class DB {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to sqlQuery().
|
||||
* <p>
|
||||
* This is an alias for {@link #sqlQuery(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlQuery createSqlQuery(String sql) {
|
||||
return sqlQuery(sql);
|
||||
}
|
||||
@@ -773,8 +763,11 @@ public class DB {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to sqlUpdate().
|
||||
* <p>
|
||||
* This is an alias for {@link #sqlUpdate(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return sqlUpdate(sql);
|
||||
}
|
||||
@@ -1215,6 +1208,13 @@ public class DB {
|
||||
return getDefault().getBeanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the Id property for a given bean.
|
||||
*/
|
||||
public static Object getBeanId(Object bean) {
|
||||
return getDefault().getBeanId(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the manager of the level 2 cache ("L2" cache).
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.ebean;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.meta.MetaInfoManager;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
@@ -465,8 +464,11 @@ public interface Database {
|
||||
SqlQuery sqlQuery(String sql);
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to sqlQuery().
|
||||
* <p>
|
||||
* This is an alias for {@link #sqlQuery(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
SqlQuery createSqlQuery(String sql);
|
||||
|
||||
/**
|
||||
@@ -485,8 +487,11 @@ public interface Database {
|
||||
SqlUpdate sqlUpdate(String sql);
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to sqlUpdate().
|
||||
* <p>
|
||||
* This is an alias for {@link #sqlUpdate(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
SqlUpdate createSqlUpdate(String sql);
|
||||
|
||||
/**
|
||||
@@ -856,7 +861,7 @@ public interface Database {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -1051,7 +1056,6 @@ public interface Database {
|
||||
* Integer returnValue = (Integer) cs.getObject(3);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*/
|
||||
int execute(CallableSql callableSql);
|
||||
|
||||
@@ -1196,17 +1200,6 @@ public interface Database {
|
||||
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
|
||||
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
|
||||
* OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
|
||||
* that are in the database but are not in the collection are deleted.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link ServerConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
|
||||
* controls if only the changed properties are included in the update or if all the loaded
|
||||
* properties are included instead.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // A 'stateless update' example
|
||||
@@ -1216,9 +1209,6 @@ public interface Database {
|
||||
* database.update(customer);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
|
||||
* @see ServerConfig#setUpdateChangesOnly(boolean)
|
||||
*/
|
||||
void update(Object bean) throws OptimisticLockException;
|
||||
|
||||
@@ -1227,16 +1217,6 @@ public interface Database {
|
||||
*/
|
||||
void update(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a bean additionally specifying a transaction and the deleteMissingChildren setting.
|
||||
*
|
||||
* @param bean the bean to update
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @param deleteMissingChildren specify false if you do not want 'missing children' of a OneToMany
|
||||
* or ManyToMany to be automatically deleted.
|
||||
*/
|
||||
void update(Object bean, Transaction transaction, boolean deleteMissingChildren) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a collection of beans. If there is no current transaction one is created and used to
|
||||
* update all the beans in the collection.
|
||||
@@ -1323,7 +1303,7 @@ public interface Database {
|
||||
* public void run() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1372,7 +1352,7 @@ public interface Database {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Ebean will be Deprecated - please migrate to use DB.
|
||||
* <p>
|
||||
* Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
|
||||
* <p>
|
||||
* Ebean is effectively this is an alias for {@link DB} which is the new and improved name for Ebean.
|
||||
@@ -462,7 +464,7 @@ public final class Ebean {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -548,9 +550,6 @@ public final class Ebean {
|
||||
* DB.update(customer);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
|
||||
* @see ServerConfig#setUpdateChangesOnly(boolean)
|
||||
*/
|
||||
public static void update(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().update(bean);
|
||||
@@ -868,6 +867,8 @@ public final class Ebean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to DB.sqlQuery().
|
||||
* <p>
|
||||
* Create a SqlQuery for executing native sql
|
||||
* query statements.
|
||||
* <p>
|
||||
@@ -875,22 +876,24 @@ public final class Ebean {
|
||||
* annotation for examples.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlQuery createSqlQuery(String sql) {
|
||||
return serverMgr.getDefaultServer().createSqlQuery(sql);
|
||||
return serverMgr.getDefaultServer().sqlQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to DB.sqlUpdate().
|
||||
* <p>
|
||||
* Create a sql update for executing native dml statements.
|
||||
* <p>
|
||||
* Use this to execute a Insert Update or Delete statement. The statement will
|
||||
* be native to the database and contain database table and column names.
|
||||
* </p>
|
||||
* <p>
|
||||
* See {@link SqlUpdate} for example usage.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return serverMgr.getDefaultServer().createSqlUpdate(sql);
|
||||
return serverMgr.getDefaultServer().sqlUpdate(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1196,7 +1199,7 @@ public final class Ebean {
|
||||
* public void run() {
|
||||
* User u1 = Ebean.find(User.class, 1);
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1248,7 +1251,7 @@ public final class Ebean {
|
||||
* User u1 = Ebean.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* }
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
|
||||
@@ -21,7 +21,7 @@ public class EbeanVersion {
|
||||
static {
|
||||
try {
|
||||
Properties prop = new Properties();
|
||||
try (InputStream in = Ebean.class.getResourceAsStream("/META-INF/maven/io.ebean/ebean/pom.properties")) {
|
||||
try (InputStream in = DB.class.getResourceAsStream("/META-INF/maven/io.ebean/ebean/pom.properties")) {
|
||||
if (in != null) {
|
||||
prop.load(in);
|
||||
in.close();
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package io.ebean;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* An empty PagedList.
|
||||
* <p>
|
||||
* For use in application code when we need to return a PagedList but don't want to
|
||||
* execute a query.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Customer> empty = PagedList.emptyList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public class EmptyPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public void loadCount() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Future<Integer> getFutureCount() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<T> getList() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPageCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPageSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPageIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrev() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayXtoYofZ(String to, String of) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -34,14 +34,14 @@ public class Expr {
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
public static Expression eq(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().eq(propertyName, value);
|
||||
return DB.getExpressionFactory().eq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
public static Expression ne(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().ne(propertyName, value);
|
||||
return DB.getExpressionFactory().ne(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ public class Expr {
|
||||
* using a lower() function to make it case insensitive).
|
||||
*/
|
||||
public static Expression ieq(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().ieq(propertyName, value);
|
||||
return DB.getExpressionFactory().ieq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,28 +59,28 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
return Ebean.getExpressionFactory().inRange(propertyName, value1, value2);
|
||||
return DB.getExpressionFactory().inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
public static Expression between(String propertyName, Object value1, Object value2) {
|
||||
return Ebean.getExpressionFactory().between(propertyName, value1, value2);
|
||||
return DB.getExpressionFactory().between(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - value between two given properties.
|
||||
*/
|
||||
public static Expression between(String lowProperty, String highProperty, Object value) {
|
||||
return Ebean.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
return DB.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
public static Expression gt(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().gt(propertyName, value);
|
||||
return DB.getExpressionFactory().gt(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,42 +88,42 @@ public class Expr {
|
||||
* value.
|
||||
*/
|
||||
public static Expression ge(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().ge(propertyName, value);
|
||||
return DB.getExpressionFactory().ge(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
public static Expression lt(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().lt(propertyName, value);
|
||||
return DB.getExpressionFactory().lt(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
public static Expression le(String propertyName, Object value) {
|
||||
return Ebean.getExpressionFactory().le(propertyName, value);
|
||||
return DB.getExpressionFactory().le(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Null - property is null.
|
||||
*/
|
||||
public static Expression isNull(String propertyName) {
|
||||
return Ebean.getExpressionFactory().isNull(propertyName);
|
||||
return DB.getExpressionFactory().isNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Not Null - property is not null.
|
||||
*/
|
||||
public static Expression isNotNull(String propertyName) {
|
||||
return Ebean.getExpressionFactory().isNotNull(propertyName);
|
||||
return DB.getExpressionFactory().isNotNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive {@link #exampleLike(Object)}
|
||||
*/
|
||||
public static ExampleExpression iexampleLike(Object example) {
|
||||
return Ebean.getExpressionFactory().iexampleLike(example);
|
||||
return DB.getExpressionFactory().iexampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,14 +131,14 @@ public class Expr {
|
||||
* LikeType.RAW (you need to add you own wildcards % and _).
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example) {
|
||||
return Ebean.getExpressionFactory().exampleLike(example);
|
||||
return DB.getExpressionFactory().exampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
|
||||
return Ebean.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
|
||||
return DB.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +146,7 @@ public class Expr {
|
||||
* characters % (percentage) and _ (underscore).
|
||||
*/
|
||||
public static Expression like(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().like(propertyName, value);
|
||||
return DB.getExpressionFactory().like(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,14 +155,14 @@ public class Expr {
|
||||
* a lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression ilike(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().ilike(propertyName, value);
|
||||
return DB.getExpressionFactory().ilike(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts With - property like value%.
|
||||
*/
|
||||
public static Expression startsWith(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().startsWith(propertyName, value);
|
||||
return DB.getExpressionFactory().startsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,14 +170,14 @@ public class Expr {
|
||||
* lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression istartsWith(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().istartsWith(propertyName, value);
|
||||
return DB.getExpressionFactory().istartsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends With - property like %value.
|
||||
*/
|
||||
public static Expression endsWith(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().endsWith(propertyName, value);
|
||||
return DB.getExpressionFactory().endsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,14 +185,14 @@ public class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression iendsWith(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().iendsWith(propertyName, value);
|
||||
return DB.getExpressionFactory().iendsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - property like %value%.
|
||||
*/
|
||||
public static Expression contains(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().contains(propertyName, value);
|
||||
return DB.getExpressionFactory().contains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,42 +200,42 @@ public class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression icontains(String propertyName, String value) {
|
||||
return Ebean.getExpressionFactory().icontains(propertyName, value);
|
||||
return DB.getExpressionFactory().icontains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are empty (have not existing elements).
|
||||
*/
|
||||
public static Expression isEmpty(String propertyName) {
|
||||
return Ebean.getExpressionFactory().isEmpty(propertyName);
|
||||
return DB.getExpressionFactory().isEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are not empty (have existing elements).
|
||||
*/
|
||||
public static Expression isNotEmpty(String propertyName) {
|
||||
return Ebean.getExpressionFactory().isNotEmpty(propertyName);
|
||||
return DB.getExpressionFactory().isNotEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Object[] values) {
|
||||
return Ebean.getExpressionFactory().in(propertyName, values);
|
||||
return DB.getExpressionFactory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
public static Expression in(String propertyName, Query<?> subQuery) {
|
||||
return Ebean.getExpressionFactory().in(propertyName, subQuery);
|
||||
return DB.getExpressionFactory().in(propertyName, subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Collection<?> values) {
|
||||
return Ebean.getExpressionFactory().in(propertyName, values);
|
||||
return DB.getExpressionFactory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,14 +272,14 @@ public class Expr {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return Ebean.getExpressionFactory().inOrEmpty(propertyName, values);
|
||||
return DB.getExpressionFactory().inOrEmpty(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Id Equal to - ID property is equal to the value.
|
||||
*/
|
||||
public static Expression idEq(Object value) {
|
||||
return Ebean.getExpressionFactory().idEq(value);
|
||||
return DB.getExpressionFactory().idEq(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,7 +292,7 @@ public class Expr {
|
||||
* @param propertyMap a map keyed by property names.
|
||||
*/
|
||||
public static Expression allEq(Map<String, Object> propertyMap) {
|
||||
return Ebean.getExpressionFactory().allEq(propertyMap);
|
||||
return DB.getExpressionFactory().allEq(propertyMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +303,7 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object value) {
|
||||
return Ebean.getExpressionFactory().raw(raw, value);
|
||||
return DB.getExpressionFactory().raw(raw, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,14 +314,14 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object[] values) {
|
||||
return Ebean.getExpressionFactory().raw(raw, values);
|
||||
return DB.getExpressionFactory().raw(raw, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add raw expression with no parameters.
|
||||
*/
|
||||
public static Expression raw(String raw) {
|
||||
return Ebean.getExpressionFactory().raw(raw);
|
||||
return DB.getExpressionFactory().raw(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,7 +329,7 @@ public class Expr {
|
||||
*/
|
||||
public static Expression and(Expression expOne, Expression expTwo) {
|
||||
|
||||
return Ebean.getExpressionFactory().and(expOne, expTwo);
|
||||
return DB.getExpressionFactory().and(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,7 +337,7 @@ public class Expr {
|
||||
*/
|
||||
public static Expression or(Expression expOne, Expression expTwo) {
|
||||
|
||||
return Ebean.getExpressionFactory().or(expOne, expTwo);
|
||||
return DB.getExpressionFactory().or(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,7 +345,7 @@ public class Expr {
|
||||
*/
|
||||
public static Expression not(Expression exp) {
|
||||
|
||||
return Ebean.getExpressionFactory().not(exp);
|
||||
return DB.getExpressionFactory().not(exp);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,7 +353,7 @@ public class Expr {
|
||||
*/
|
||||
public static <T> Junction<T> conjunction(Query<T> query) {
|
||||
|
||||
return Ebean.getExpressionFactory().conjunction(query);
|
||||
return DB.getExpressionFactory().conjunction(query);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -361,6 +361,6 @@ public class Expr {
|
||||
*/
|
||||
public static <T> Junction<T> disjunction(Query<T> query) {
|
||||
|
||||
return Ebean.getExpressionFactory().disjunction(query);
|
||||
return DB.getExpressionFactory().disjunction(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The extended API for Database.
|
||||
@@ -107,6 +108,24 @@ public interface ExtendedServer {
|
||||
@Nonnull
|
||||
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the query result as a Stream using a single persistence context.
|
||||
* <p>
|
||||
* Note that the stream needs to be closed so use with try with resources.
|
||||
* </p>
|
||||
*/
|
||||
@Nonnull
|
||||
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the query result as a Stream (with multiple persistence contexts).
|
||||
* <p>
|
||||
* Note that the stream needs to be closed so use with try with resources.
|
||||
* </p>
|
||||
*/
|
||||
@Nonnull
|
||||
<T> Stream<T> findLargeStream(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query visiting the each bean one at a time.
|
||||
* <p>
|
||||
|
||||
@@ -86,7 +86,7 @@ public interface Filter<T> {
|
||||
* expressions.
|
||||
* </p>
|
||||
* <p>
|
||||
* Refer to {@link Ebean#sort(List, String)} for more detail.
|
||||
* Refer to {@link DB#sort(List, String)} for more detail.
|
||||
* </p>
|
||||
*/
|
||||
Filter<T> sort(String sortByClause);
|
||||
|
||||
@@ -60,6 +60,13 @@ import java.util.concurrent.Future;
|
||||
*/
|
||||
public interface PagedList<T> {
|
||||
|
||||
/**
|
||||
* Return an empty PagedList.
|
||||
*/
|
||||
static <B> PagedList<B> emptyList() {
|
||||
return new EmptyPagedList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the loading of the total row count in the background.
|
||||
* <pre>{@code
|
||||
|
||||
@@ -38,7 +38,7 @@ public interface ProfileLocation {
|
||||
/**
|
||||
* Return a short version of the location description.
|
||||
*/
|
||||
String shortDescription();
|
||||
String location();
|
||||
|
||||
/**
|
||||
* Return the short label.
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Object relational query for finding a List, Set, Map or single entity bean.
|
||||
@@ -702,6 +703,49 @@ public interface Query<T> {
|
||||
@Nonnull
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use try with resources to ensure Stream is closed
|
||||
*
|
||||
* try (Stream<Customer> stream = query.findStream()) {
|
||||
* stream
|
||||
* .map(...)
|
||||
* .collect(...);
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Nonnull
|
||||
Stream<T> findStream();
|
||||
|
||||
/**
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this uses multiple persistence contexts such that we can use
|
||||
* it with a large number of results.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use try with resources to ensure Stream is closed
|
||||
*
|
||||
* try (Stream<Customer> stream = query.findLargeStream()) {
|
||||
* stream
|
||||
* .map(...)
|
||||
* .collect(...);
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Nonnull
|
||||
Stream<T> findLargeStream();
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.ebean;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Thrown at SERIALIZABLE isolation level for non-recoverable concurrent conflict.
|
||||
*/
|
||||
public class SerializableConflictException extends OptimisticLockException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Create with a message and cause.
|
||||
*/
|
||||
public SerializableConflictException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@@ -126,8 +126,6 @@ public interface SqlUpdate {
|
||||
* {@link Transaction#setBatchMode(boolean)} and
|
||||
* {@link Transaction#setBatchSize(int)}.
|
||||
* </p>
|
||||
*
|
||||
* @see Ebean#execute(SqlUpdate)
|
||||
*/
|
||||
int execute();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* @see Database#currentTransaction()
|
||||
*/
|
||||
static Transaction current() {
|
||||
return Ebean.currentTransaction();
|
||||
return DB.currentTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,16 +12,16 @@ import java.util.concurrent.Callable;
|
||||
* <p>
|
||||
* This information matches the features of the Transactional annotation. You
|
||||
* can use it directly with Runnable or Callable via
|
||||
* {@link Ebean#execute(TxScope, Runnable)} or
|
||||
* {@link Ebean#executeCall(TxScope, Callable)}.
|
||||
* {@link DB#execute(TxScope, Runnable)} or
|
||||
* {@link DB#executeCall(TxScope, Callable)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* This object is used internally with the enhancement of a method with
|
||||
* Transactional annotation.
|
||||
* </p>
|
||||
*
|
||||
* @see Ebean#execute(TxScope, Runnable)
|
||||
* @see Ebean#executeCall(TxScope, Callable)
|
||||
* @see DB#execute(TxScope, Runnable)
|
||||
* @see DB#executeCall(TxScope, Callable)
|
||||
*/
|
||||
public final class TxScope {
|
||||
|
||||
|
||||
@@ -20,29 +20,23 @@ class XServiceProvider {
|
||||
private static SpiFetchGroupService fetchGroupService = initSpiFetchGroupService();
|
||||
|
||||
private static SpiFetchGroupService initSpiFetchGroupService() {
|
||||
Iterator<SpiFetchGroupService> loader = ServiceLoader.load(SpiFetchGroupService.class).iterator();
|
||||
if (loader.hasNext()) {
|
||||
return loader.next();
|
||||
}
|
||||
throw new IllegalStateException("No service implementation found for SpiFetchGroupService?");
|
||||
return loadFirstService(SpiFetchGroupService.class);
|
||||
}
|
||||
|
||||
private static SpiRawSqlService initRawSql() {
|
||||
|
||||
Iterator<SpiRawSqlService> loader = ServiceLoader.load(SpiRawSqlService.class).iterator();
|
||||
if (loader.hasNext()) {
|
||||
return loader.next();
|
||||
}
|
||||
throw new IllegalStateException("No service implementation found for SpiRawSqlService?");
|
||||
return loadFirstService(SpiRawSqlService.class);
|
||||
}
|
||||
|
||||
private static SpiProfileLocationFactory initProfileLocation() {
|
||||
return loadFirstService(SpiProfileLocationFactory.class);
|
||||
}
|
||||
|
||||
Iterator<SpiProfileLocationFactory> loader = ServiceLoader.load(SpiProfileLocationFactory.class).iterator();
|
||||
private static <T> T loadFirstService(Class<T> cls) {
|
||||
Iterator<T> loader = ServiceLoader.load(cls).iterator();
|
||||
if (loader.hasNext()) {
|
||||
return loader.next();
|
||||
}
|
||||
throw new IllegalStateException("No service implementation found for SpiProfileLocationFactory?");
|
||||
throw new IllegalStateException("No service implementation found for " + cls);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
@@ -821,7 +821,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
synchronized (this) {
|
||||
if (beanLoader == null) {
|
||||
BeanLoader serverLoader = (BeanLoader) Ebean.getServer(ebeanServerName);
|
||||
BeanLoader serverLoader = (BeanLoader) DB.byName(ebeanServerName);
|
||||
if (serverLoader == null) {
|
||||
throw new PersistenceException("Server [" + ebeanServerName + "] was not found?");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.BeanCollectionLoader;
|
||||
@@ -93,7 +93,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
void lazyLoadCollection(boolean onlyIds) {
|
||||
if (loader == null) {
|
||||
loader = (BeanCollectionLoader) Ebean.getServer(ebeanServerName);
|
||||
loader = (BeanCollectionLoader) DB.byName(ebeanServerName);
|
||||
}
|
||||
loader.loadMany(this, onlyIds);
|
||||
checkEmptyLazyLoad();
|
||||
|
||||
@@ -83,10 +83,13 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSequenceName(String tableName, String pkColumn) {
|
||||
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableName));
|
||||
public String getSequenceName(String rawTableName, String pkColumn) {
|
||||
final String tableNameUnquoted = databasePlatform.unQuote(rawTableName);
|
||||
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableNameUnquoted));
|
||||
if (pkColumn == null) {
|
||||
pkColumn = "";
|
||||
} else {
|
||||
pkColumn = databasePlatform.unQuote(pkColumn);
|
||||
}
|
||||
return COLUMN_REPLACE.matcher(s).replaceAll(Matcher.quoteReplacement(pkColumn));
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ public class MatchingNamingConvention extends AbstractNamingConvention {
|
||||
|
||||
@Override
|
||||
public TableName getTableNameByConvention(Class<?> beanClass) {
|
||||
|
||||
return new TableName(getCatalog(), getSchema(), beanClass.getSimpleName());
|
||||
return new TableName(quoteIdentifiers(getCatalog()), quoteIdentifiers(getSchema()), quoteIdentifiers(beanClass.getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Used by generated code to hold entity classes to register with Ebean.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ModuleInfo {
|
||||
|
||||
/**
|
||||
* Returns the entity classes with db name prefix.
|
||||
* <p>
|
||||
* The db name prefix is added to entity classes for non default databases.
|
||||
*/
|
||||
String[] entities() default {};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Loads and returns entity classes to register with Ebean databases.
|
||||
*/
|
||||
public interface ModuleInfoLoader {
|
||||
|
||||
/**
|
||||
* Return the entity classes to register with the default DB.
|
||||
*/
|
||||
List<Class<?>> entityClasses();
|
||||
|
||||
/**
|
||||
* Return entity classes to register for a named DB (not default DB).
|
||||
*/
|
||||
List<Class<?>> entityClassesFor(String dbName);
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.meta.MetaInfoManager;
|
||||
import io.ebean.migration.MigrationRunner;
|
||||
import io.ebean.util.StringHelper;
|
||||
|
||||
@@ -133,6 +132,15 @@ public class ServerConfig {
|
||||
|
||||
private TenantCatalogProvider tenantCatalogProvider;
|
||||
|
||||
/**
|
||||
* When true will load entity classes via ModuleInfoLoader.
|
||||
* <p>
|
||||
* NB: ModuleInfoLoader implementations are generated by querybean generator.
|
||||
* Having this on and registering entity classes means we don't need to manually
|
||||
* write that code or use classpath scanning to find entity classes.
|
||||
*/
|
||||
private boolean loadModuleInfo;
|
||||
|
||||
/**
|
||||
* List of interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers etc.
|
||||
@@ -350,21 +358,11 @@ public class ServerConfig {
|
||||
*/
|
||||
private DbConstraintNaming constraintNaming = new DbConstraintNaming();
|
||||
|
||||
/**
|
||||
* Behaviour of update to include on the change properties.
|
||||
*/
|
||||
private boolean updateChangesOnly = true;
|
||||
|
||||
/**
|
||||
* Behaviour of updates in JDBC batch to by default include all properties.
|
||||
*/
|
||||
private boolean updateAllPropertiesInBatch;
|
||||
|
||||
/**
|
||||
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
|
||||
*/
|
||||
private boolean updatesDeleteMissingChildren = true;
|
||||
|
||||
/**
|
||||
* Database platform configuration.
|
||||
*/
|
||||
@@ -425,10 +423,6 @@ public class ServerConfig {
|
||||
|
||||
private ServerCachePlugin serverCachePlugin;
|
||||
|
||||
private boolean collectQueryStatsByNode = true;
|
||||
|
||||
private boolean collectQueryOrigins = true;
|
||||
|
||||
/**
|
||||
* The default PersistenceContextScope used if one is not explicitly set on a query.
|
||||
*/
|
||||
@@ -2291,12 +2285,18 @@ public class ServerConfig {
|
||||
* server.
|
||||
*/
|
||||
public void addClass(Class<?> cls) {
|
||||
if (classes == null) {
|
||||
classes = new ArrayList<>();
|
||||
}
|
||||
classes.add(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all the classes (typically entity classes).
|
||||
*/
|
||||
public void addAll(List<Class<?>> classList) {
|
||||
if (classList != null && !classList.isEmpty()) {
|
||||
classes.addAll(classList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a package to search for entities via class path search.
|
||||
* <p>
|
||||
@@ -2304,9 +2304,6 @@ public class ServerConfig {
|
||||
* </p>
|
||||
*/
|
||||
public void addPackage(String packageName) {
|
||||
if (packages == null) {
|
||||
packages = new ArrayList<>();
|
||||
}
|
||||
packages.add(packageName);
|
||||
}
|
||||
|
||||
@@ -2409,20 +2406,6 @@ public class ServerConfig {
|
||||
this.skipCacheAfterWrite = skipCacheAfterWrite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true to only update changed properties.
|
||||
*/
|
||||
public boolean isUpdateChangesOnly() {
|
||||
return updateChangesOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to only update changed properties.
|
||||
*/
|
||||
public void setUpdateChangesOnly(boolean updateChangesOnly) {
|
||||
this.updateChangesOnly = updateChangesOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if updates in JDBC batch default to include all properties by default.
|
||||
*/
|
||||
@@ -2442,68 +2425,6 @@ public class ServerConfig {
|
||||
this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if updates by default delete missing children when cascading save to a OneToMany or
|
||||
* ManyToMany. When not set this defaults to true.
|
||||
*/
|
||||
public boolean isUpdatesDeleteMissingChildren() {
|
||||
return updatesDeleteMissingChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if updates by default delete missing children when cascading save to a OneToMany or
|
||||
* ManyToMany. When not set this defaults to true.
|
||||
*/
|
||||
public void setUpdatesDeleteMissingChildren(boolean updatesDeleteMissingChildren) {
|
||||
this.updatesDeleteMissingChildren = updatesDeleteMissingChildren;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if query statistics should be collected by ObjectGraphNode.
|
||||
*/
|
||||
public boolean isCollectQueryStatsByNode() {
|
||||
return collectQueryStatsByNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to collection query execution statistics by ObjectGraphNode.
|
||||
* <p>
|
||||
* These statistics can be used to highlight code/query 'origin points' that result in lots of lazy loading.
|
||||
* </p>
|
||||
* <p>
|
||||
* It is considered safe/fine to have this set to true for production.
|
||||
* </p>
|
||||
* <p>
|
||||
* This information can be later retrieved via {@link MetaInfoManager}.
|
||||
* </p>
|
||||
*
|
||||
* @see MetaInfoManager
|
||||
*/
|
||||
public void setCollectQueryStatsByNode(boolean collectQueryStatsByNode) {
|
||||
this.collectQueryStatsByNode = collectQueryStatsByNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if query plans should also collect their 'origins'. This means for a given query plan you
|
||||
* can identify the code/origin points where this query resulted from including lazy loading origins.
|
||||
*/
|
||||
public boolean isCollectQueryOrigins() {
|
||||
return collectQueryOrigins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if query plans should collect their 'origin' points. This means for a given query plan you
|
||||
* can identify the code/origin points where this query resulted from including lazy loading origins.
|
||||
* <p>
|
||||
* This information can be later retrieved via {@link MetaInfoManager}.
|
||||
* </p>
|
||||
*
|
||||
* @see MetaInfoManager
|
||||
*/
|
||||
public void setCollectQueryOrigins(boolean collectQueryOrigins) {
|
||||
this.collectQueryOrigins = collectQueryOrigins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource directory.
|
||||
*/
|
||||
@@ -2929,6 +2850,7 @@ public class ServerConfig {
|
||||
}
|
||||
loadDocStoreSettings(p);
|
||||
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
@@ -2961,15 +2883,8 @@ public class ServerConfig {
|
||||
String packagesProp = p.get("search.packages", p.get("packages", null));
|
||||
packages = getSearchList(packagesProp, packages);
|
||||
|
||||
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
|
||||
collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
|
||||
|
||||
skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
|
||||
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
|
||||
updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
|
||||
|
||||
boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
|
||||
updatesDeleteMissingChildren = p.getBoolean("updatesDeleteMissingChildren", defaultDeleteMissingChildren);
|
||||
|
||||
if (p.get("batch.mode") != null || p.get("persistBatching") != null) {
|
||||
throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
|
||||
@@ -3060,20 +2975,20 @@ public class ServerConfig {
|
||||
return classes;
|
||||
}
|
||||
|
||||
List<Class<?>> classes = new ArrayList<>();
|
||||
List<Class<?>> classList = new ArrayList<>();
|
||||
|
||||
String[] split = StringHelper.splitNames(classNames);
|
||||
for (String cn : split) {
|
||||
if (!"class".equalsIgnoreCase(cn)) {
|
||||
try {
|
||||
classes.add(Class.forName(cn));
|
||||
classList.add(Class.forName(cn));
|
||||
} catch (ClassNotFoundException e) {
|
||||
String msg = "Error registering class [" + cn + "] from [" + classNames + "]";
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return classes;
|
||||
return classList;
|
||||
}
|
||||
|
||||
private List<String> getSearchList(String searchNames, List<String> defaultValue) {
|
||||
@@ -3357,6 +3272,17 @@ public class ServerConfig {
|
||||
this.dumpMetricsOptions = dumpMetricsOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if entity classes should be loaded and registered via ModuleInfoLoader.
|
||||
* <p>
|
||||
* When false we either register entity classes via application code or use classpath
|
||||
* scanning to find and register entity classes.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isAutoLoadModuleInfo() {
|
||||
return loadModuleInfo && classes.isEmpty();
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -18,5 +18,10 @@ public enum DataErrorType {
|
||||
/**
|
||||
* Data integrity error like an invalid foreign key.
|
||||
*/
|
||||
DataIntegrity
|
||||
DataIntegrity,
|
||||
|
||||
/**
|
||||
* Non recoverable concurrency conflict.
|
||||
*/
|
||||
SerializableConflict
|
||||
}
|
||||
|
||||
@@ -75,6 +75,11 @@ public class DatabasePlatform {
|
||||
|
||||
protected boolean caseSensitiveCollation = true;
|
||||
|
||||
/**
|
||||
* Set true if the Database support LIMIT clause on sql update.
|
||||
*/
|
||||
protected boolean inlineSqlUpdateLimit;
|
||||
|
||||
/**
|
||||
* For limit/offset, row_number etc limiting of SQL queries.
|
||||
*/
|
||||
@@ -143,8 +148,6 @@ public class DatabasePlatform {
|
||||
|
||||
protected String columnAliasPrefix = "c";
|
||||
|
||||
protected String tableAliasPlaceHolder = "${ta}";
|
||||
|
||||
/**
|
||||
* Use a BackTick ` at the beginning and end of table or column names that you
|
||||
* want to use quoted identifiers for. The backticks get converted to the
|
||||
@@ -171,13 +174,14 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Characters escaped for startsWith, endsWith and contains.
|
||||
*/
|
||||
protected char[] likeSpecialCharacters = { '%', '_', '|' };
|
||||
protected char[] likeSpecialCharacters = {'%', '_', '|'};
|
||||
|
||||
protected DbEncrypt dbEncrypt;
|
||||
|
||||
protected boolean idInExpandedForm;
|
||||
|
||||
protected boolean selectCountWithAlias;
|
||||
protected boolean selectCountWithColumnAlias;
|
||||
|
||||
/**
|
||||
* If set then use the FORWARD ONLY hint when creating ResultSets for
|
||||
@@ -187,7 +191,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* If set then use the CONCUR_UPDATABLE hint when creating ResultSets.
|
||||
*
|
||||
* <p>
|
||||
* This is {@code false} for HANA
|
||||
*/
|
||||
protected boolean supportsResultSetConcurrencyModeUpdatable = true;
|
||||
@@ -339,6 +343,13 @@ public class DatabasePlatform {
|
||||
return supportsSavepointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports LIMIT with sql update.
|
||||
*/
|
||||
public boolean isInlineSqlUpdateLimit() {
|
||||
return inlineSqlUpdateLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum table name length.
|
||||
* <p>
|
||||
@@ -370,11 +381,11 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return a DB Sequence based IdGenerator.
|
||||
*
|
||||
* @param be the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds the DataSource
|
||||
* @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
|
||||
* @param seqName the name of the sequence
|
||||
* @param be the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds the DataSource
|
||||
* @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
|
||||
* @param seqName the name of the sequence
|
||||
*/
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return null;
|
||||
@@ -466,20 +477,6 @@ public class DatabasePlatform {
|
||||
this.columnAliasPrefix = columnAliasPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the table alias placeholder.
|
||||
*/
|
||||
public String getTableAliasPlaceHolder() {
|
||||
return tableAliasPlaceHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table alias placeholder.
|
||||
*/
|
||||
public void setTableAliasPlaceHolder(String tableAliasPlaceHolder) {
|
||||
this.tableAliasPlaceHolder = tableAliasPlaceHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the close quote for quoted identifiers.
|
||||
*/
|
||||
@@ -659,7 +656,7 @@ public class DatabasePlatform {
|
||||
if (dbName != null && !dbName.isEmpty()) {
|
||||
if (dbName.startsWith(openQuote)) {
|
||||
// trim off the open and close quotes
|
||||
return dbName.substring(1, dbName.length()-1);
|
||||
return dbName.substring(1, dbName.length() - 1);
|
||||
}
|
||||
}
|
||||
return dbName;
|
||||
@@ -672,6 +669,14 @@ public class DatabasePlatform {
|
||||
return selectCountWithAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if select count with subquery needs column alias (SQL Server).
|
||||
*/
|
||||
public boolean isSelectCountWithColumnAlias() {
|
||||
return selectCountWithColumnAlias;
|
||||
}
|
||||
|
||||
|
||||
public String completeSql(String sql, Query<?> query) {
|
||||
if (query.isForUpdate()) {
|
||||
sql = withForUpdate(sql, query.getForUpdateMode());
|
||||
@@ -786,7 +791,7 @@ public class DatabasePlatform {
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char ch = value.charAt(i);
|
||||
boolean escaped = false;
|
||||
for (char escapeChar: likeSpecialCharacters) {
|
||||
for (char escapeChar : likeSpecialCharacters) {
|
||||
if (ch == escapeChar) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder(value.substring(0, i));
|
||||
|
||||
@@ -29,6 +29,8 @@ public class DbPlatformTypeMapping {
|
||||
|
||||
private static final DbPlatformType INET_NATIVE = new DbPlatformType("inet", false);
|
||||
private static final DbPlatformType INET_VARCHAR = new DbPlatformType("varchar", 50);
|
||||
private static final DbPlatformType CIDR_NATIVE = new DbPlatformType("cidr", false);
|
||||
private static final DbPlatformType CIDR_VARCHAR = new DbPlatformType("varchar", 50);
|
||||
|
||||
private static final DbPlatformType UUID_NATIVE = new DbPlatformType("uuid", false);
|
||||
@SuppressWarnings("unused")
|
||||
@@ -110,6 +112,7 @@ public class DbPlatformTypeMapping {
|
||||
put(DbType.JSONVARCHAR, new DbPlatformType("jsonvarchar", 1000));
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
put(DbType.INET, INET_NATIVE);
|
||||
put(DbType.CIDR, CIDR_NATIVE);
|
||||
|
||||
} else {
|
||||
put(DbType.VARCHAR, new DbPlatformType("varchar", 255));
|
||||
@@ -126,6 +129,7 @@ public class DbPlatformTypeMapping {
|
||||
// default to native UUID and override on platform configure()
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
put(DbType.INET, INET_VARCHAR);
|
||||
put(DbType.CIDR, CIDR_VARCHAR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ public enum DbType {
|
||||
|
||||
UUID(ExtraDbTypes.UUID),
|
||||
INET(ExtraDbTypes.INET),
|
||||
CDIR(ExtraDbTypes.CDIR),
|
||||
CIDR(ExtraDbTypes.CIDR),
|
||||
|
||||
POINT(ExtraDbTypes.POINT),
|
||||
POLYGON(ExtraDbTypes.POLYGON),
|
||||
|
||||
@@ -41,7 +41,7 @@ public interface ExtraDbTypes {
|
||||
int JSONBlob = 5005;
|
||||
|
||||
int INET = 5020;
|
||||
int CDIR = 5021;
|
||||
int CIDR = 5021;
|
||||
|
||||
/**
|
||||
* Geo Point
|
||||
|
||||
@@ -12,9 +12,10 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* Database sequence based IdGenerator.
|
||||
@@ -42,7 +43,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
|
||||
protected final BackgroundExecutor backgroundExecutor;
|
||||
|
||||
protected final ArrayList<Long> idList = new ArrayList<>(50);
|
||||
protected final NavigableSet<Long> idList = new TreeSet<>();
|
||||
|
||||
protected final int allocationSize;
|
||||
|
||||
@@ -97,15 +98,13 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
@Override
|
||||
public Object nextId(Transaction t) {
|
||||
synchronized (monitor) {
|
||||
|
||||
int size = idList.size();
|
||||
if (size > 0) {
|
||||
maybeLoadMoreInBackground(size);
|
||||
} else {
|
||||
loadMore(allocationSize);
|
||||
}
|
||||
|
||||
return idList.remove(0);
|
||||
return idList.pollFirst();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebean.config.dbplatform;
|
||||
import io.ebean.AcquireLockException;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.DuplicateKeyException;
|
||||
import io.ebean.SerializableConflictException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.SQLException;
|
||||
@@ -14,12 +15,12 @@ import java.util.Map;
|
||||
*/
|
||||
public class SqlCodeTranslator implements SqlExceptionTranslator {
|
||||
|
||||
private final Map<String,DataErrorType> map;
|
||||
private final Map<String, DataErrorType> map;
|
||||
|
||||
/**
|
||||
* Create given the map of SQLState codes to error types.
|
||||
*/
|
||||
public SqlCodeTranslator(Map<String,DataErrorType> map) {
|
||||
public SqlCodeTranslator(Map<String, DataErrorType> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@@ -46,6 +47,8 @@ public class SqlCodeTranslator implements SqlExceptionTranslator {
|
||||
return new DuplicateKeyException(message, e);
|
||||
case DataIntegrity:
|
||||
return new DataIntegrityException(message, e);
|
||||
case SerializableConflict:
|
||||
return new SerializableConflictException(message, e);
|
||||
}
|
||||
}
|
||||
// return a generic exception
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class SqlErrorCodes {
|
||||
|
||||
private final Map<String,DataErrorType> map = new HashMap<>();
|
||||
private final Map<String, DataErrorType> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map the codes to AcquireLockException.
|
||||
@@ -31,6 +31,13 @@ public class SqlErrorCodes {
|
||||
return add(DataErrorType.DuplicateKey, codes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the codes to SerializableConflictException.
|
||||
*/
|
||||
public SqlErrorCodes addSerializableConflict(String... codes) {
|
||||
return add(DataErrorType.SerializableConflict, codes);
|
||||
}
|
||||
|
||||
private SqlErrorCodes add(DataErrorType type, String... codes) {
|
||||
for (String code : codes) {
|
||||
map.put(code, type);
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ClickHousePlatform extends DatabasePlatform {
|
||||
|
||||
dbTypeMap.put(DbType.UUID, new DbPlatformType("UUID", false));
|
||||
dbTypeMap.put(DbType.INET, new DbPlatformType("String", false));
|
||||
dbTypeMap.put(DbType.CDIR, new DbPlatformType("String", false));
|
||||
dbTypeMap.put(DbType.CIDR, new DbPlatformType("String", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Clickhouse DB specific support.
|
||||
*/
|
||||
package io.ebean.config.dbplatform.clickhouse;
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Cockroach DB specific support.
|
||||
*/
|
||||
package io.ebean.config.dbplatform.cockroach;
|
||||
@@ -24,6 +24,7 @@ public class H2Platform extends DatabasePlatform {
|
||||
this.historySupport = new H2HistorySupport();
|
||||
this.nativeUuidType = true;
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
this.columnAliasPrefix = null;
|
||||
this.exceptionTranslator =
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebean.config.dbplatform.mysql;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
|
||||
public class MySql55Platform extends MySqlPlatform {
|
||||
|
||||
public MySql55Platform() {
|
||||
super();
|
||||
this.platform = Platform.MYSQL55;
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime"));
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
this.useExtraTransactionOnIterateSecondaryQueries = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.supportsSavepointId = false;
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
this.historySupport = new MySqlHistorySupport();
|
||||
this.columnAliasPrefix = null;
|
||||
@@ -51,8 +52,8 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
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.likeClauseRaw = "like ? escape''";
|
||||
this.likeClauseEscaped = "like ? escape'|'";
|
||||
|
||||
this.forwardOnlyHintOnFindIterate = true;
|
||||
this.booleanDbType = Types.BIT;
|
||||
|
||||
@@ -37,6 +37,7 @@ public class NuoDbPlatform extends DatabasePlatform {
|
||||
new SqlErrorCodes()
|
||||
//.addAcquireLock("")
|
||||
.addDuplicateKey("23000")
|
||||
.addSerializableConflict("40002")
|
||||
.build();
|
||||
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* NuoDB specific support.
|
||||
*/
|
||||
package io.ebean.config.dbplatform.nuodb;
|
||||
@@ -48,6 +48,7 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
//.addAcquireLock("")
|
||||
.addDuplicateKey("1")
|
||||
.addDataIntegrity("2291")
|
||||
.addSerializableConflict("72000")
|
||||
.build();
|
||||
|
||||
this.openQuote = "\"";
|
||||
|
||||
@@ -51,7 +51,8 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("55P03")
|
||||
.addDuplicateKey("23505")
|
||||
.addDataIntegrity("23000","23502","23503","23514")
|
||||
.addDataIntegrity("23000", "23502", "23503", "23514")
|
||||
.addSerializableConflict("40001")
|
||||
.build();
|
||||
|
||||
this.openQuote = "\"";
|
||||
@@ -62,6 +63,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
|
||||
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
|
||||
dbTypeMap.put(DbType.INET, new DbPlatformType("inet", false));
|
||||
dbTypeMap.put(DbType.CIDR, new DbPlatformType("cidr", false));
|
||||
dbTypeMap.put(DbType.HSTORE, new DbPlatformType("hstore", false));
|
||||
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbPlatformType("jsonb", false));
|
||||
@@ -126,7 +128,6 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
|
||||
@Override
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("select count(*) from pg_inherits i WHERE i.inhparent = ?::regclass")) {
|
||||
statement.setString(1, table);
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
@@ -137,18 +138,15 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return SQL using built in partition helper functions to create some initial partitions.
|
||||
*
|
||||
* <p>
|
||||
* Only use this if extra-ddl doesn't have some initial partitions defined (which it should).
|
||||
*/
|
||||
@Override
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String pkey) {
|
||||
if (property == null) {
|
||||
property = "";
|
||||
}
|
||||
if (pkey == null) {
|
||||
pkey = "";
|
||||
}
|
||||
return "select partition('" + mode.name().toLowerCase() + "','" + tableName + "','" + pkey + "','" + property + "',1);";
|
||||
// default partition required pg11 but this is only used for testing but bumped test docker container to pg11 by default
|
||||
return
|
||||
"create table " + tableName + "_default" + " partition of " + tableName + " default;\n" +
|
||||
"select partition('" + mode.name().toLowerCase() + "','" + tableName + "',1);";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.idInExpandedForm = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.selectCountWithColumnAlias = true;
|
||||
this.sqlLimiter = new SqlServerSqlLimiter();
|
||||
this.basicSqlLimiter = new SqlServerBasicSqlLimiter();
|
||||
this.historySupport = new SqlServerHistorySupport();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean.dbmigration;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -66,7 +66,7 @@ public interface DbMigration {
|
||||
* Set the server to use to determine the current model.
|
||||
* Typically this is not called explicitly.
|
||||
*/
|
||||
void setServer(EbeanServer ebeanServer);
|
||||
void setServer(Database database);
|
||||
|
||||
/**
|
||||
* Set the serverConfig to use. Typically this is not called explicitly.
|
||||
@@ -136,6 +136,23 @@ public interface DbMigration {
|
||||
*/
|
||||
void setGeneratePendingDrop(String generatePendingDrop);
|
||||
|
||||
/**
|
||||
* Set to true if ALTER TABLE ADD FOREIGN KEY should be generated with an option to skip validation.
|
||||
* <p>
|
||||
* Currently this is only useful for Postgres DDL adding the <code>NOT VALID</code> option.
|
||||
* </p>
|
||||
*/
|
||||
void setAddForeignKeySkipCheck(boolean addForeignKeySkipCheck);
|
||||
|
||||
/**
|
||||
* Set the lock timeout to be included with the DDL generation.
|
||||
* <p>
|
||||
* Currently this is only useful for Postgres migrations adding a <code>set lock_timeout</code>
|
||||
* statement to the generated database migration.
|
||||
* </p>
|
||||
*/
|
||||
void setLockTimeout(int seconds);
|
||||
|
||||
/**
|
||||
* Add an additional platform to write the migration DDL.
|
||||
* <p>
|
||||
@@ -198,6 +215,7 @@ public interface DbMigration {
|
||||
* An "init" migration can only be executed and used on a database that has had no
|
||||
* prior migrations run on it.
|
||||
* </p>
|
||||
*
|
||||
* @return the version of the generated migration
|
||||
*/
|
||||
String generateInitMigration() throws IOException;
|
||||
|
||||
@@ -41,6 +41,11 @@ public interface BeanPersistRequest<T> {
|
||||
*/
|
||||
Set<String> getUpdatedProperties();
|
||||
|
||||
/**
|
||||
* Flags set for dirty properties (used by ElasticSearch integration).
|
||||
*/
|
||||
boolean[] getDirtyProperties();
|
||||
|
||||
/**
|
||||
* Return true for an update request if at least one of dirty properties is contained
|
||||
* in the given set of property names.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Set;
|
||||
* Listen for bulk table events that occur.
|
||||
* <p>
|
||||
* These events can be triggered via
|
||||
* {@link Ebean#externalModification(String, boolean, boolean, boolean)} or
|
||||
* {@link DB#externalModification(String, boolean, boolean, boolean)} or
|
||||
* automatically determined from Ebean bulk update statements.
|
||||
*/
|
||||
public interface BulkTableEventListener {
|
||||
|
||||
@@ -9,9 +9,8 @@ import java.util.List;
|
||||
public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerMetrics {
|
||||
|
||||
private final List<MetaTimedMetric> timed = new ArrayList<>();
|
||||
private final List<MetaQueryMetric> dtoQuery = new ArrayList<>();
|
||||
private final List<MetaOrmQueryMetric> ormQuery = new ArrayList<>();
|
||||
private final List<MetaCountMetric> countMetrics = new ArrayList<>();
|
||||
private final List<MetaQueryMetric> query = new ArrayList<>();
|
||||
private final List<MetaCountMetric> count = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Construct to reset and collect everything.
|
||||
@@ -27,33 +26,19 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
|
||||
super(reset, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
|
||||
*/
|
||||
@Override
|
||||
public List<MetaTimedMetric> getTimedMetrics() {
|
||||
return timed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DTO query metrics.
|
||||
*/
|
||||
@Override
|
||||
public List<MetaQueryMetric> getDtoQueryMetrics() {
|
||||
return dtoQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ORM query metrics.
|
||||
*/
|
||||
@Override
|
||||
public List<MetaOrmQueryMetric> getOrmQueryMetrics() {
|
||||
return ormQuery;
|
||||
public List<MetaQueryMetric> getQueryMetrics() {
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetaCountMetric> getCountMetrics() {
|
||||
return countMetrics;
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,16 +48,11 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
|
||||
|
||||
@Override
|
||||
public void visitQuery(MetaQueryMetric metric) {
|
||||
dtoQuery.add(metric);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOrmQuery(MetaOrmQueryMetric metric) {
|
||||
ormQuery.add(metric);
|
||||
query.add(metric);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCount(MetaCountMetric metric) {
|
||||
countMetrics.add(metric);
|
||||
count.add(metric);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
/**
|
||||
* Count metrics.
|
||||
* Count metrics. For example L2 cache hits.
|
||||
*/
|
||||
public interface MetaCountMetric {
|
||||
|
||||
/**
|
||||
* Return the metric type.
|
||||
*/
|
||||
MetricType getMetricType();
|
||||
|
||||
/**
|
||||
* Return the metric name.
|
||||
*/
|
||||
String getName();
|
||||
public interface MetaCountMetric extends MetaMetric {
|
||||
|
||||
/**
|
||||
* Return the total count.
|
||||
|
||||
@@ -16,6 +16,23 @@ public interface MetaInfoManager {
|
||||
*/
|
||||
ServerMetrics collectMetrics();
|
||||
|
||||
/**
|
||||
* Collect the metrics in raw JSON form.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String metricsJson = database.getMetaInfoManager()
|
||||
* .collectMetricsAsJson()
|
||||
* .json();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ServerMetricsAsJson collectMetricsAsJson();
|
||||
|
||||
/**
|
||||
* Return the metrics as a list of MetricData.
|
||||
*/
|
||||
List<MetricData> collectMetricsAsData();
|
||||
|
||||
/**
|
||||
* Collect query plans.
|
||||
*/
|
||||
@@ -37,16 +54,4 @@ public interface MetaInfoManager {
|
||||
*/
|
||||
void resetAllMetrics();
|
||||
|
||||
/**
|
||||
* Collect and return the ObjectGraphNode statistics.
|
||||
* <p>
|
||||
* These show query executions based on an origin point and relative path.
|
||||
* This is used to look at the amount of lazy loading occurring for a given
|
||||
* query origin point and highlight potential for tuning a query.
|
||||
* </p>
|
||||
*
|
||||
* @param reset Set to true to reset the underlying statistics after collection.
|
||||
*/
|
||||
List<MetaOrmQueryNode> collectNodeStatistics(boolean reset);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
/**
|
||||
* Metrics collected by Ebean including timed metrics and counters.
|
||||
*/
|
||||
public interface MetaMetric {
|
||||
|
||||
/**
|
||||
* Return the metric type.
|
||||
*/
|
||||
MetricType getMetricType();
|
||||
|
||||
/**
|
||||
* Return the metric name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Query execution statistics for Orm queries.
|
||||
*/
|
||||
public interface MetaOrmQueryMetric extends MetaQueryMetric {
|
||||
|
||||
/**
|
||||
* Return true if this query plan was tuned by AutoTune.
|
||||
*/
|
||||
boolean isAutoTuned();
|
||||
|
||||
/**
|
||||
* Return the hash of the sql.
|
||||
*/
|
||||
String getSqlHash();
|
||||
|
||||
/**
|
||||
* Return the time of the last query executed using this plan.
|
||||
*/
|
||||
long getLastQueryTime();
|
||||
|
||||
/**
|
||||
* Return the 'origin' points and paths that resulted in the query being
|
||||
* executed and the associated number of times the query was executed via that
|
||||
* path.
|
||||
* <p>
|
||||
* This includes direct and lazy loading paths.
|
||||
* </p>
|
||||
*/
|
||||
List<MetaOrmQueryOrigin> getOrigins();
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
|
||||
/**
|
||||
* Statistics for query execution based on object graph origin and paths.
|
||||
* <p>
|
||||
* These statistics can be used to identify origin queries that result in lots
|
||||
* of lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
public interface MetaOrmQueryNode {
|
||||
|
||||
/**
|
||||
* Return the ObjectGraphNode which has the origin point and relative path.
|
||||
*/
|
||||
ObjectGraphNode getNode();
|
||||
|
||||
/**
|
||||
* Return the startTime of statistics collection.
|
||||
*/
|
||||
long getStartTime();
|
||||
|
||||
/**
|
||||
* Return the total count of queries executed for this node.
|
||||
*/
|
||||
long getCount();
|
||||
|
||||
/**
|
||||
* Return the total time of queries executed for this node.
|
||||
*/
|
||||
long getTotalTime();
|
||||
|
||||
/**
|
||||
* Return the total beans loaded by queries for this node.
|
||||
*/
|
||||
long getTotalBeans();
|
||||
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
|
||||
/**
|
||||
* Holds a query 'origin' point and count for the number of queries executed for
|
||||
* this 'origin'.
|
||||
* <p>
|
||||
* This basically points to the bit of original code and query that results in
|
||||
* this query directly or via lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
public interface MetaOrmQueryOrigin {
|
||||
|
||||
/**
|
||||
* The 'origin' and path which this query belongs to.
|
||||
* <p>
|
||||
* For lazy loading queries this points to the original query and associated
|
||||
* navigation path that resulted in this query being executed.
|
||||
* </p>
|
||||
*/
|
||||
ObjectGraphNode getObjectGraphNode();
|
||||
|
||||
/**
|
||||
* The number of times a query was fired for this node since the counter was
|
||||
* last reset.
|
||||
*/
|
||||
long getCount();
|
||||
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
|
||||
/**
|
||||
* Query execution metrics.
|
||||
*/
|
||||
@@ -17,14 +15,14 @@ public interface MetaQueryMetric extends MetaTimedMetric {
|
||||
*/
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* Return the profile location.
|
||||
*/
|
||||
ProfileLocation getProfileLocation();
|
||||
|
||||
/**
|
||||
* The actual SQL of the query.
|
||||
*/
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Return the hash of the plan.
|
||||
*/
|
||||
String getHash();
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@ package io.ebean.meta;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
|
||||
/**
|
||||
* Meta data for captured query plan.
|
||||
*/
|
||||
public interface MetaQueryPlan {
|
||||
|
||||
/**
|
||||
@@ -25,9 +28,9 @@ public interface MetaQueryPlan {
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Return the hash of the sql.
|
||||
* Return the hash of the plan.
|
||||
*/
|
||||
String getSqlHash();
|
||||
String getHash();
|
||||
|
||||
/**
|
||||
* Return a description of the bind values.
|
||||
|
||||
@@ -4,28 +4,13 @@ package io.ebean.meta;
|
||||
/**
|
||||
* Timed execution statistics.
|
||||
*/
|
||||
public interface MetaTimedMetric {
|
||||
|
||||
/**
|
||||
* Return the metric type.
|
||||
*/
|
||||
MetricType getMetricType();
|
||||
|
||||
/**
|
||||
* Return the metric name.
|
||||
*/
|
||||
String getName();
|
||||
public interface MetaTimedMetric extends MetaMetric {
|
||||
|
||||
/**
|
||||
* Return the metric location if defined.
|
||||
*/
|
||||
String getLocation();
|
||||
|
||||
/**
|
||||
* Return the time the counters started from.
|
||||
*/
|
||||
long getStartTime();
|
||||
|
||||
/**
|
||||
* Return the total count.
|
||||
*/
|
||||
@@ -47,9 +32,11 @@ public interface MetaTimedMetric {
|
||||
long getMean();
|
||||
|
||||
/**
|
||||
* Return the total beans or rows processed or loaded.
|
||||
*
|
||||
* This will be 0 if the metric isn't a query plan (like transaction execution statistics).
|
||||
* Return true if this is the first metrics collection for this query.
|
||||
* <p>
|
||||
* This can be used to suppress including the SQL and location from metrics
|
||||
* content.
|
||||
* </p>
|
||||
*/
|
||||
long getBeanCount();
|
||||
boolean initialCollection();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
/**
|
||||
* An individual metric.
|
||||
*/
|
||||
public class MetricData {
|
||||
|
||||
private String name;
|
||||
private String type;
|
||||
private String hash;
|
||||
private String loc;
|
||||
private String sql;
|
||||
|
||||
private Long count;
|
||||
private Long mean;
|
||||
private Long max;
|
||||
private Long total;
|
||||
|
||||
public MetricData(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public MetricData() {
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getHash() {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public void setHash(String hash) {
|
||||
this.hash = hash;
|
||||
}
|
||||
|
||||
public String getLoc() {
|
||||
return loc;
|
||||
}
|
||||
|
||||
public void setLoc(String loc) {
|
||||
this.loc = loc;
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
|
||||
public Long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(Long count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public Long getMean() {
|
||||
return mean;
|
||||
}
|
||||
|
||||
public void setMean(Long mean) {
|
||||
this.mean = mean;
|
||||
}
|
||||
|
||||
public Long getMax() {
|
||||
return max;
|
||||
}
|
||||
|
||||
public void setMax(Long max) {
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
public Long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public void setTotal(Long total) {
|
||||
this.total = total;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,11 @@ public enum MetricType {
|
||||
*/
|
||||
TXN,
|
||||
|
||||
/**
|
||||
* ORM Insert Update or Delete.
|
||||
*/
|
||||
IUD,
|
||||
|
||||
/**
|
||||
* ORM queries.
|
||||
*/
|
||||
|
||||
@@ -40,11 +40,6 @@ public interface MetricVisitor {
|
||||
*/
|
||||
void visitQuery(MetaQueryMetric metric);
|
||||
|
||||
/**
|
||||
* Visit ORM query metrics.
|
||||
*/
|
||||
void visitOrmQuery(MetaOrmQueryMetric metric);
|
||||
|
||||
/**
|
||||
* Visit a Counter metric.
|
||||
*/
|
||||
|
||||
@@ -13,14 +13,9 @@ public interface ServerMetrics {
|
||||
List<MetaTimedMetric> getTimedMetrics();
|
||||
|
||||
/**
|
||||
* Return the DTO query metrics.
|
||||
* Return the query metrics.
|
||||
*/
|
||||
List<MetaQueryMetric> getDtoQueryMetrics();
|
||||
|
||||
/**
|
||||
* Return the ORM query metrics.
|
||||
*/
|
||||
List<MetaOrmQueryMetric> getOrmQueryMetrics();
|
||||
List<MetaQueryMetric> getQueryMetrics();
|
||||
|
||||
/**
|
||||
* Return the Counter metrics.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Collect the metrics in raw JSON form.
|
||||
*/
|
||||
public interface ServerMetricsAsJson {
|
||||
|
||||
/**
|
||||
* Set to false to exclude profile location and sql.
|
||||
*/
|
||||
ServerMetricsAsJson withExtraAttributes(boolean withLocation);
|
||||
|
||||
/**
|
||||
* Set to false to exclude SQL hash.
|
||||
*/
|
||||
ServerMetricsAsJson withHash(boolean withHash);
|
||||
|
||||
/**
|
||||
* Set the sort property - see SortMetric
|
||||
* @see SortMetric
|
||||
*/
|
||||
ServerMetricsAsJson withSort(Comparator<MetaTimedMetric> sortBy);
|
||||
|
||||
/**
|
||||
* Set the new line character to use.
|
||||
*/
|
||||
ServerMetricsAsJson withNewLine(boolean withNewLine);
|
||||
|
||||
/**
|
||||
* Set to include a heading of the database name.
|
||||
* <p>
|
||||
* When this is false the metrics are written without json array start or array end.
|
||||
*/
|
||||
ServerMetricsAsJson withHeader(boolean withHeader);
|
||||
|
||||
/**
|
||||
* Collect and write metrics as JSON to the given buffer.
|
||||
*/
|
||||
void write(Appendable buffer);
|
||||
|
||||
/**
|
||||
* Return the metrics in raw JSON.
|
||||
*/
|
||||
String json();
|
||||
}
|
||||
@@ -13,20 +13,15 @@ public interface TimedMetric {
|
||||
void add(long micros);
|
||||
|
||||
/**
|
||||
* Add a time event with the number of loaded beans or rows.
|
||||
* Add a time event for a batch of beans.
|
||||
*/
|
||||
void add(long micros, long beans);
|
||||
void addBatchSince(long startNanos, int batch);
|
||||
|
||||
/**
|
||||
* Add a time event given the start nanos.
|
||||
*/
|
||||
void addSinceNanos(long startNanos);
|
||||
|
||||
/**
|
||||
* Add a time event given the start nanos and bean count.
|
||||
*/
|
||||
void addSinceNanos(long startNanos, long beans);
|
||||
|
||||
/**
|
||||
* Return true if there are no metrics collected since the last collection.
|
||||
*/
|
||||
|
||||
@@ -12,21 +12,11 @@ public interface TimedMetricMap {
|
||||
*/
|
||||
void addSinceNanos(String key, long startNanos);
|
||||
|
||||
/**
|
||||
* Add a time event given the start nanos and beans.
|
||||
*/
|
||||
void addSinceNanos(String key, long startNanos, int beans);
|
||||
|
||||
/**
|
||||
* Add an execution for the given key.
|
||||
*/
|
||||
void add(String key, long exeMicros);
|
||||
|
||||
/**
|
||||
* Add an execution for the given key including row/bean count.
|
||||
*/
|
||||
void add(String key, long exeMicros, int rows);
|
||||
|
||||
/**
|
||||
* Visit the metric.
|
||||
*/
|
||||
|
||||
@@ -11,4 +11,9 @@ public interface TimedMetricStats extends MetaTimedMetric {
|
||||
* Additionally set the location.
|
||||
*/
|
||||
void setLocation(String location);
|
||||
|
||||
/**
|
||||
* Override the name based on profile location.
|
||||
*/
|
||||
void setName(String name);
|
||||
}
|
||||
|
||||
@@ -149,6 +149,13 @@ public interface JsonContext {
|
||||
*/
|
||||
String toJson(Object value) throws JsonIOException;
|
||||
|
||||
/**
|
||||
* Return the bean or collection as JSON string in pretty format.
|
||||
*
|
||||
* @throws JsonIOException When IOException occurs
|
||||
*/
|
||||
String toJsonPretty(Object value) throws JsonIOException;
|
||||
|
||||
/**
|
||||
* Write the bean or collection in JSON format to the writer.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TxScope;
|
||||
|
||||
/**
|
||||
@@ -28,7 +28,7 @@ public class HelpScopeTrans {
|
||||
}
|
||||
|
||||
private static SpiEbeanServer server() {
|
||||
return (SpiEbeanServer) Ebean.getDefaultServer();
|
||||
return (SpiEbeanServer) DB.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
|
||||
/**
|
||||
* Controls the loading of reference objects for a query instance.
|
||||
@@ -47,6 +48,11 @@ public interface LoadContext {
|
||||
*/
|
||||
void register(String path, EntityBeanIntercept ebi);
|
||||
|
||||
/**
|
||||
* Register a Bean with inheritance.
|
||||
*/
|
||||
void register(String path, EntityBeanIntercept ebi, BeanPropertyAssocOne<?> property);
|
||||
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
|
||||
@@ -169,7 +169,7 @@ public class LoadManyRequest extends LoadRequest {
|
||||
Object parentId = desc.getId(ownerBean);
|
||||
logger.debug("BeanCollection after lazy load was empty. type:" + ownerBean.getClass().getName() + " id:" + parentId + " owner:" + ownerBean);
|
||||
}
|
||||
} else if (isLoadCache()) {
|
||||
} else if (isLoadCache() && many.isUseCache()) {
|
||||
Object parentId = desc.getId(bc.getOwnerBean());
|
||||
desc.cacheManyPropPut(many, bc, parentId);
|
||||
}
|
||||
|
||||
@@ -1,86 +1,17 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
|
||||
import io.ebean.Pairs;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Natural key entry with name value pairs for each of the properties making up the key.
|
||||
* An entry for natural key lookup.
|
||||
*/
|
||||
public class NaturalKeyEntry {
|
||||
|
||||
private final Map<String,Object> map = new HashMap<>();
|
||||
private final Object key;
|
||||
private Object inValue;
|
||||
|
||||
/**
|
||||
* Used when query query just has a series of EQ expressions (no IN clause).
|
||||
*/
|
||||
public NaturalKeyEntry(String[] naturalKey, List<NaturalKeyEq> eqList) {
|
||||
load(eqList);
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create when query uses an IN clause.
|
||||
*/
|
||||
public NaturalKeyEntry(String[] naturalKey, List<NaturalKeyEq> eqList, String inProperty, Object inValue) {
|
||||
load(eqList);
|
||||
if (inProperty != null) {
|
||||
map.put(inProperty, inValue);
|
||||
this.inValue = inValue;
|
||||
}
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create when query uses an IN PAIRS clause.
|
||||
*/
|
||||
public NaturalKeyEntry(String[] naturalKey, List<NaturalKeyEq> eqList,
|
||||
String inMapProperty0, String inMapProperty1, Pairs.Entry pair) {
|
||||
load(eqList);
|
||||
map.put(inMapProperty0, pair.getA());
|
||||
map.put(inMapProperty1, pair.getB());
|
||||
this.inValue = pair;
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
private void load(List<NaturalKeyEq> eqList) {
|
||||
if (eqList != null) {
|
||||
for (NaturalKeyEq eq : eqList) {
|
||||
map.put(eq.property, eq.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object calculateKey(String[] naturalKey) {
|
||||
|
||||
if (naturalKey.length == 1) {
|
||||
return map.get(naturalKey[0]);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String key : naturalKey) {
|
||||
sb.append(map.get(key)).append(";");
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
public interface NaturalKeyEntry {
|
||||
|
||||
/**
|
||||
* Return the natural cache key (String concatenation of values).
|
||||
*/
|
||||
public Object key() {
|
||||
return key;
|
||||
}
|
||||
String key();
|
||||
|
||||
/**
|
||||
* Return the inValue (used to remove from IN clause of original query).
|
||||
*/
|
||||
public Object getInValue() {
|
||||
return inValue;
|
||||
}
|
||||
Object getInValue();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
|
||||
import io.ebean.Pairs;
|
||||
import io.ebeaninternal.server.deploy.BeanNaturalKey;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Natural key entry with name value pairs for each of the properties making up the key.
|
||||
*/
|
||||
class NaturalKeyEntryBasic implements NaturalKeyEntry {
|
||||
|
||||
private final Map<String,Object> map = new HashMap<>();
|
||||
private final String key;
|
||||
private Object inValue;
|
||||
|
||||
/**
|
||||
* Used when query query just has a series of EQ expressions (no IN clause).
|
||||
*/
|
||||
NaturalKeyEntryBasic(BeanNaturalKey naturalKey, List<NaturalKeyEq> eqList) {
|
||||
load(eqList);
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create when query uses an IN clause.
|
||||
*/
|
||||
NaturalKeyEntryBasic(BeanNaturalKey naturalKey, List<NaturalKeyEq> eqList, String inProperty, Object inValue) {
|
||||
load(eqList);
|
||||
if (inProperty != null) {
|
||||
map.put(inProperty, inValue);
|
||||
this.inValue = inValue;
|
||||
}
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create when query uses an IN PAIRS clause.
|
||||
*/
|
||||
NaturalKeyEntryBasic(BeanNaturalKey naturalKey, List<NaturalKeyEq> eqList,
|
||||
String inMapProperty0, String inMapProperty1, Pairs.Entry pair) {
|
||||
load(eqList);
|
||||
map.put(inMapProperty0, pair.getA());
|
||||
map.put(inMapProperty1, pair.getB());
|
||||
this.inValue = pair;
|
||||
this.key = calculateKey(naturalKey);
|
||||
}
|
||||
|
||||
private void load(List<NaturalKeyEq> eqList) {
|
||||
if (eqList != null) {
|
||||
for (NaturalKeyEq eq : eqList) {
|
||||
map.put(eq.property, eq.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String calculateKey(BeanNaturalKey naturalKey) {
|
||||
return naturalKey.calculateKey(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getInValue() {
|
||||
return inValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
class NaturalKeyEntrySimple implements NaturalKeyEntry {
|
||||
|
||||
private final String key;
|
||||
private final Object val;
|
||||
|
||||
NaturalKeyEntrySimple(Object val) {
|
||||
this.key = val.toString();
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getInValue() {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.Pairs;
|
||||
import io.ebeaninternal.server.deploy.BeanNaturalKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -12,7 +13,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class NaturalKeyQueryData<T> {
|
||||
|
||||
private final String[] naturalKey;
|
||||
private final BeanNaturalKey naturalKey;
|
||||
|
||||
/**
|
||||
* Only one of IN or IN PAIRS is allowed.
|
||||
@@ -34,18 +35,12 @@ public class NaturalKeyQueryData<T> {
|
||||
|
||||
private int hitCount;
|
||||
|
||||
public NaturalKeyQueryData(String[] naturalKey) {
|
||||
public NaturalKeyQueryData(BeanNaturalKey naturalKey) {
|
||||
this.naturalKey = naturalKey;
|
||||
}
|
||||
|
||||
private boolean matchProperty(String propName) {
|
||||
|
||||
for (String key : naturalKey) {
|
||||
if (key.equals(propName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return naturalKey.matchProperty(propName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,37 +103,52 @@ public class NaturalKeyQueryData<T> {
|
||||
|
||||
this.set = new NaturalKeySet();
|
||||
if (inValues != null) {
|
||||
// a findList() with an IN clause so we project
|
||||
// for every IN value a natural key combination
|
||||
for (Object inValue : inValues) {
|
||||
set.add(new NaturalKeyEntry(naturalKey, eqList, inProperty, inValue));
|
||||
}
|
||||
addInValues();
|
||||
} else if (inPairs != null) {
|
||||
// a findList() with an IN Map clause so we project
|
||||
// for every IN value a natural key combination
|
||||
for (Pairs.Entry entry : inPairs) {
|
||||
set.add(new NaturalKeyEntry(naturalKey, eqList, inProperty0, inProperty1, entry));
|
||||
}
|
||||
|
||||
addInPairs();
|
||||
} else {
|
||||
// only one - a findOne()
|
||||
set.add(new NaturalKeyEntry(naturalKey, eqList));
|
||||
addEqualsKey();
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
private void addInPairs() {
|
||||
// a findList() with an IN Map clause so we project
|
||||
// for every IN value a natural key combination
|
||||
for (Pairs.Entry entry : inPairs) {
|
||||
set.add(new NaturalKeyEntryBasic(naturalKey, eqList, inProperty0, inProperty1, entry));
|
||||
}
|
||||
}
|
||||
|
||||
private void addInValues() {
|
||||
if (eqList == null) {
|
||||
// a single property IN expression
|
||||
for (Object inValue : inValues) {
|
||||
set.add(new NaturalKeyEntrySimple(inValue));
|
||||
}
|
||||
} else {
|
||||
// IN expression + EQ expression(s)
|
||||
for (Object inValue : inValues) {
|
||||
set.add(new NaturalKeyEntryBasic(naturalKey, eqList, inProperty, inValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addEqualsKey() {
|
||||
if (eqList.size() == 1) {
|
||||
// a single property EQ expression
|
||||
set.add(new NaturalKeyEntrySimple(eqList.get(0).value));
|
||||
} else {
|
||||
set.add(new NaturalKeyEntryBasic(naturalKey, eqList));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the properties match the natural key properties.
|
||||
*/
|
||||
private boolean matchProperties() {
|
||||
if (naturalKey.length == 1) {
|
||||
// simple single property case
|
||||
if (inProperty != null) {
|
||||
return inProperty.equals(naturalKey[0]);
|
||||
} else {
|
||||
return eqList.get(0).property.equals(naturalKey[0]);
|
||||
}
|
||||
if (naturalKey.isSingleProperty()) {
|
||||
naturalKey.matchSingleProperty((inProperty != null) ? inProperty : eqList.get(0).property);
|
||||
}
|
||||
|
||||
// multiple properties case
|
||||
@@ -157,27 +167,17 @@ public class NaturalKeyQueryData<T> {
|
||||
exprProps.add(eq.property);
|
||||
}
|
||||
}
|
||||
if (exprProps.size() != naturalKey.length) {
|
||||
return false;
|
||||
}
|
||||
for (String key : naturalKey) {
|
||||
if (!exprProps.remove(key)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return exprProps.isEmpty();
|
||||
return naturalKey.matchMultiProperties(exprProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all the natural key properties are defined.
|
||||
*/
|
||||
private boolean expressionCount() {
|
||||
|
||||
int defined = (inValues == null) ? 0 : 1;
|
||||
defined += (inPairs == null) ? 0 : 2;
|
||||
defined += (eqList == null) ? 0 : eqList.size();
|
||||
return defined == naturalKey.length;
|
||||
return defined == naturalKey.length();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ public class NaturalKeySet {
|
||||
|
||||
private final Map<Object, NaturalKeyEntry> map = new LinkedHashMap<>();
|
||||
|
||||
public NaturalKeySet() {
|
||||
NaturalKeySet() {
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@@ -24,8 +24,7 @@ public class NaturalKeySet {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public Object getInValue(Object naturalKey) {
|
||||
NaturalKeyEntry entry = map.get(naturalKey);
|
||||
return entry.getInValue();
|
||||
Object getInValue(Object naturalKey) {
|
||||
return map.get(naturalKey).getInValue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,11 +49,6 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanLoader,
|
||||
*/
|
||||
void shutdownManaged();
|
||||
|
||||
/**
|
||||
* Return true if query origins should be collected.
|
||||
*/
|
||||
boolean isCollectQueryOrigins();
|
||||
|
||||
/**
|
||||
* Return true if updates in JDBC batch should include all columns if unspecified on the transaction.
|
||||
*/
|
||||
@@ -201,11 +196,6 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanLoader,
|
||||
*/
|
||||
boolean isSupportedType(java.lang.reflect.Type genericType);
|
||||
|
||||
/**
|
||||
* Collect query statistics by ObjectGraphNode. Used for Lazy loading reporting.
|
||||
*/
|
||||
void collectQueryStats(ObjectGraphNode objectGraphNode, long loadedBeanCount, long timeMicros);
|
||||
|
||||
/**
|
||||
* Return the ReadAuditLogger to use for logging all read audit events.
|
||||
*/
|
||||
|
||||
@@ -458,7 +458,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
/**
|
||||
* Set the query to be a delete query.
|
||||
*/
|
||||
void setDelete();
|
||||
void setupForDeleteOrUpdate(boolean deleteRequest);
|
||||
|
||||
/**
|
||||
* Set the query to be delete by ids due to cascading delete.
|
||||
|
||||
@@ -33,4 +33,9 @@ public interface SpiSqlUpdate extends SqlUpdate {
|
||||
* Reset bind position to be ready for another bind execute.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Return a copy of the SqlUpdate with empty bind parameters.
|
||||
*/
|
||||
SpiSqlUpdate copy();
|
||||
}
|
||||
|
||||
@@ -75,9 +75,10 @@ public interface SpiTransaction extends Transaction {
|
||||
boolean isRegisteredDeleteBean(Integer hash);
|
||||
|
||||
/**
|
||||
* Unregister the persisted bean.
|
||||
* Unregister the persisted beans. Expected after persisting top level beans
|
||||
* and hence including all beans that were cascade persisted.
|
||||
*/
|
||||
void unregisterBean(Object bean);
|
||||
void unregisterBeans();
|
||||
|
||||
/**
|
||||
* Return true if this is a bean that has already been persisted in the
|
||||
|
||||
@@ -189,8 +189,8 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBean(Object bean) {
|
||||
transaction.unregisterBean(bean);
|
||||
public void unregisterBeans() {
|
||||
transaction.unregisterBeans();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -62,6 +62,16 @@ public interface SpiJsonWriter extends JsonWriter {
|
||||
*/
|
||||
void endAssocMany();
|
||||
|
||||
/**
|
||||
* Start a Many.
|
||||
*/
|
||||
void beginAssocManyMap(String name, boolean elementCollection);
|
||||
|
||||
/**
|
||||
* End a Many.
|
||||
*/
|
||||
void endAssocManyMap(boolean elementCollection);
|
||||
|
||||
/**
|
||||
* Write value using underlying Jaskson object mapper if available.
|
||||
*/
|
||||
|
||||
@@ -257,7 +257,9 @@ public class DdlGenerator {
|
||||
protected void runResourceScript(Connection connection, String sqlScript) throws IOException {
|
||||
if (sqlScript != null) {
|
||||
try (InputStream is = getClassLoader().getResourceAsStream(sqlScript)) {
|
||||
if (is != null) {
|
||||
if (is == null) {
|
||||
log.warn("sql script {} was not found as a resource", sqlScript);
|
||||
} else {
|
||||
String content = readContent(new InputStreamReader(is));
|
||||
runScript(connection, false, content, sqlScript);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
@@ -14,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.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
@@ -25,6 +27,7 @@ import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import io.ebean.dbmigration.DbMigration;
|
||||
import io.ebean.migration.MigrationVersion;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
import io.ebeaninternal.dbmigration.migrationreader.MigrationXmlWriter;
|
||||
@@ -105,6 +108,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
protected String version;
|
||||
protected String name;
|
||||
protected String generatePendingDrop;
|
||||
private boolean addForeignKeySkipCheck;
|
||||
private int lockTimeoutSeconds;
|
||||
|
||||
protected boolean includeBuiltInPartitioning = true;
|
||||
|
||||
@@ -138,8 +143,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
* Typically this is not called explicitly.
|
||||
*/
|
||||
@Override
|
||||
public void setServer(EbeanServer ebeanServer) {
|
||||
this.server = (SpiEbeanServer) ebeanServer;
|
||||
public void setServer(Database database) {
|
||||
this.server = (SpiEbeanServer) database;
|
||||
setServerConfig(server.getServerConfig());
|
||||
}
|
||||
|
||||
@@ -179,6 +184,16 @@ public class DefaultDbMigration implements DbMigration {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAddForeignKeySkipCheck(boolean addForeignKeySkipCheck) {
|
||||
this.addForeignKeySkipCheck = addForeignKeySkipCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLockTimeout(int seconds) {
|
||||
this.lockTimeoutSeconds = seconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGeneratePendingDrop(String generatePendingDrop) {
|
||||
this.generatePendingDrop = generatePendingDrop;
|
||||
@@ -564,7 +579,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
} else if (databasePlatform != null) {
|
||||
// writer needs the current model to provide table/column details for
|
||||
// history ddl generation (triggers, history tables etc)
|
||||
DdlWrite write = new DdlWrite(new MConfiguration(), request.current);
|
||||
DdlOptions options = new DdlOptions(addForeignKeySkipCheck);
|
||||
DdlWrite write = new DdlWrite(new MConfiguration(), request.current, options);
|
||||
PlatformDdlWriter writer = createDdlWriter(databasePlatform);
|
||||
writer.processMigration(dbMigration, write, request.migrationDir, fullVersion);
|
||||
}
|
||||
@@ -622,8 +638,9 @@ public class DefaultDbMigration implements DbMigration {
|
||||
*/
|
||||
private void writeExtraPlatformDdl(String fullVersion, CurrentModel currentModel, Migration dbMigration, File writePath) throws IOException {
|
||||
|
||||
DdlOptions options = new DdlOptions(addForeignKeySkipCheck);
|
||||
for (Pair pair : platforms) {
|
||||
DdlWrite platformBuffer = new DdlWrite(new MConfiguration(), currentModel.read());
|
||||
DdlWrite platformBuffer = new DdlWrite(new MConfiguration(), currentModel.read(), options);
|
||||
PlatformDdlWriter platformWriter = createDdlWriter(pair.platform);
|
||||
File subPath = platformWriter.subPath(writePath, pair.prefix);
|
||||
platformWriter.processMigration(dbMigration, platformBuffer, subPath, fullVersion);
|
||||
@@ -631,7 +648,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
}
|
||||
|
||||
private PlatformDdlWriter createDdlWriter(DatabasePlatform platform) {
|
||||
return new PlatformDdlWriter(platform, serverConfig, migrationConfig);
|
||||
return new PlatformDdlWriter(platform, serverConfig, migrationConfig, lockTimeoutSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -655,7 +672,7 @@ public class DefaultDbMigration implements DbMigration {
|
||||
*/
|
||||
private void setDefaults() {
|
||||
if (server == null) {
|
||||
setServer(Ebean.getDefaultServer());
|
||||
setServer(DB.getDefault());
|
||||
}
|
||||
if (vanillaPlatform || databasePlatform == null) {
|
||||
// not explicitly set so use the platform of the server
|
||||
@@ -787,6 +804,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
return new HsqldbPlatform();
|
||||
case POSTGRES:
|
||||
return new PostgresPlatform();
|
||||
case MYSQL55:
|
||||
return new MySql55Platform();
|
||||
case MYSQL:
|
||||
return new MySqlPlatform();
|
||||
case ORACLE:
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration;
|
||||
|
||||
/**
|
||||
* Options used when generated DDL.
|
||||
*/
|
||||
public class DdlOptions {
|
||||
|
||||
private boolean foreignKeySkipCheck;
|
||||
|
||||
public DdlOptions(boolean foreignKeySkipCheck) {
|
||||
this.foreignKeySkipCheck = foreignKeySkipCheck;
|
||||
}
|
||||
|
||||
public DdlOptions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if ADD FOREIGN KEY should use a skip check option.
|
||||
*/
|
||||
public boolean isForeignKeySkipCheck() {
|
||||
return foreignKeySkipCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if ADD FOREIGN KEY should use a skip check option.
|
||||
*/
|
||||
public void setForeignKeySkipCheck(boolean foreignKeySkipCheck) {
|
||||
this.foreignKeySkipCheck = foreignKeySkipCheck;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,17 +26,19 @@ public class DdlWrite {
|
||||
|
||||
private final DdlBuffer dropAll;
|
||||
|
||||
private final DdlOptions options;
|
||||
|
||||
/**
|
||||
* Create without any configuration or current model (no history support).
|
||||
*/
|
||||
public DdlWrite() {
|
||||
this(new MConfiguration(), new ModelContainer());
|
||||
this(new MConfiguration(), new ModelContainer(), new DdlOptions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with a configuration.
|
||||
*/
|
||||
public DdlWrite(MConfiguration configuration, ModelContainer currentModel) {
|
||||
public DdlWrite(MConfiguration configuration, ModelContainer currentModel, DdlOptions options) {
|
||||
this.currentModel = currentModel;
|
||||
this.applyDropDependencies = new BaseDdlBuffer(configuration);
|
||||
this.apply = new BaseDdlBuffer(configuration);
|
||||
@@ -45,6 +47,14 @@ public class DdlWrite {
|
||||
this.applyHistoryTrigger = new BaseDdlBuffer(configuration);
|
||||
this.dropAllForeignKeys = new BaseDdlBuffer(configuration);
|
||||
this.dropAll = new BaseDdlBuffer(configuration);
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DDL options.
|
||||
*/
|
||||
public DdlOptions getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.config.dbplatform.DbHistorySupport;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.TableDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.util.IndexSet;
|
||||
@@ -31,7 +32,6 @@ import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -462,7 +462,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
fkeyBuffer.appendStatement(platformDdl.createIndex(request.indexName(), tableName, request.cols()));
|
||||
}
|
||||
|
||||
alterTableAddForeignKey(fkeyBuffer, request);
|
||||
alterTableAddForeignKey(write.getOptions(), fkeyBuffer, request);
|
||||
fkeyBuffer.end();
|
||||
|
||||
write.dropAllForeignKeys().appendStatement(platformDdl.alterTableDropForeignKey(tableName, request.fkName()));
|
||||
@@ -473,9 +473,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
write.dropAllForeignKeys().end();
|
||||
}
|
||||
|
||||
protected void alterTableAddForeignKey(DdlBuffer buffer, WriteForeignKey request) throws IOException {
|
||||
protected void alterTableAddForeignKey(DdlOptions options, DdlBuffer buffer, WriteForeignKey request) throws IOException {
|
||||
|
||||
buffer.appendStatement(platformDdl.alterTableAddForeignKey(request));
|
||||
buffer.appendStatement(platformDdl.alterTableAddForeignKey(options, request));
|
||||
}
|
||||
|
||||
protected void appendColumns(String[] columns, DdlBuffer buffer) throws IOException {
|
||||
@@ -635,7 +635,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (DdlHelp.isDropForeignKey(alterForeignKey.getColumnNames())) {
|
||||
writer.apply().appendStatement(platformDdl.alterTableDropForeignKey(alterForeignKey.getTableName(), alterForeignKey.getName()));
|
||||
} else {
|
||||
writer.apply().appendStatement(platformDdl.alterTableAddForeignKey(new WriteForeignKey(alterForeignKey)));
|
||||
writer.apply().appendStatement(platformDdl.alterTableAddForeignKey(writer.getOptions(), new WriteForeignKey(alterForeignKey)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -899,7 +899,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
protected void alterColumnAddForeignKey(DdlWrite writer, AlterColumn alterColumn) throws IOException {
|
||||
|
||||
alterTableAddForeignKey(writer.apply(), new WriteForeignKey(alterColumn));
|
||||
alterTableAddForeignKey(writer.getOptions(), writer.apply(), new WriteForeignKey(alterColumn));
|
||||
}
|
||||
|
||||
protected void alterColumnDropForeignKey(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -40,7 +41,7 @@ public class ClickHouseDdl extends PlatformDdl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableAddForeignKey(WriteForeignKey request) {
|
||||
public String alterTableAddForeignKey(DdlOptions options, WriteForeignKey request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,16 +42,6 @@ public class MySqlDdl extends PlatformDdl {
|
||||
return "alter table " + tableName + " drop foreign key " + maxConstraintName(fkName);
|
||||
}
|
||||
|
||||
/**
|
||||
* It is rather complex to delete a column on MySql as there must not exist any foreign keys.
|
||||
* That's why we call a user stored procedure here
|
||||
*/
|
||||
@Override
|
||||
public void alterTableDropColumn(DdlBuffer buffer, String tableName, String columnName) throws IOException {
|
||||
|
||||
buffer.append("CALL usp_ebean_drop_column('").append(tableName).append("', '").append(columnName).append("')").endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createCheckConstraint(String ckName, String checkConstraint) {
|
||||
if (USE_CHECK_CONSTRAINT) {
|
||||
@@ -60,6 +50,7 @@ public class MySqlDdl extends PlatformDdl {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableAddCheckConstraint(String tableName, String checkConstraintName, String checkConstraint) {
|
||||
if (USE_CHECK_CONSTRAINT) {
|
||||
@@ -96,17 +87,13 @@ public class MySqlDdl extends PlatformDdl {
|
||||
|
||||
@Override
|
||||
public String alterColumnNotnull(String tableName, String columnName, boolean notnull) {
|
||||
|
||||
// can't alter itself - done in alterColumnBaseAttributes()
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) {
|
||||
|
||||
String suffix = DdlHelp.isDropDefault(defaultValue) ? columnDropDefault : columnSetDefault + " " + convertDefaultValue(defaultValue);
|
||||
|
||||
// use alter
|
||||
return "alter table " + tableName + " alter " + columnName + " " + suffix;
|
||||
}
|
||||
|
||||
@@ -124,7 +111,6 @@ public class MySqlDdl extends PlatformDdl {
|
||||
boolean notnull = (alter.isNotnull() != null) ? alter.isNotnull() : Boolean.TRUE.equals(alter.isCurrentNotnull());
|
||||
String notnullClause = notnull ? " not null" : "";
|
||||
|
||||
// use modify
|
||||
return "alter table " + tableName + " modify " + columnName + " " + type + notnullClause;
|
||||
}
|
||||
|
||||
@@ -161,7 +147,7 @@ public class MySqlDdl extends PlatformDdl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) throws IOException {
|
||||
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) {
|
||||
// alter comment currently not supported as it requires to repeat whole column definition
|
||||
}
|
||||
|
||||
@@ -182,7 +168,6 @@ public class MySqlDdl extends PlatformDdl {
|
||||
i++;
|
||||
}
|
||||
buffer.endOfStatement();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.BaseDdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.util.PlatformTypeConverter;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.util.VowelRemover;
|
||||
@@ -106,6 +107,8 @@ public class PlatformDdl {
|
||||
|
||||
protected String dropColumnSuffix = "";
|
||||
|
||||
protected String addForeignKeySkipCheck = "";
|
||||
|
||||
/**
|
||||
* Set false for MsSqlServer to allow multiple nulls for OneToOne mapping.
|
||||
*/
|
||||
@@ -208,6 +211,13 @@ public class PlatformDdl {
|
||||
return inlineForeignKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default this does nothing returning null / no lock timeout.
|
||||
*/
|
||||
public String setLockTimeout(int lockTimeoutSeconds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all the table columns converting to platform types as necessary.
|
||||
*/
|
||||
@@ -405,7 +415,7 @@ public class PlatformDdl {
|
||||
/**
|
||||
* Add foreign key.
|
||||
*/
|
||||
public String alterTableAddForeignKey(WriteForeignKey request) {
|
||||
public String alterTableAddForeignKey(DdlOptions options, WriteForeignKey request) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder(90);
|
||||
buffer
|
||||
@@ -418,6 +428,9 @@ public class PlatformDdl {
|
||||
.append(lowerTableName(request.refTable()));
|
||||
appendColumns(request.refCols(), buffer);
|
||||
appendForeignKeySuffix(request, buffer);
|
||||
if (options.isForeignKeySkipCheck()) {
|
||||
buffer.append(addForeignKeySkipCheck);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@ public class PostgresDdl extends PlatformDdl {
|
||||
this.columnSetType = "type ";
|
||||
this.alterTableIfExists = "if exists ";
|
||||
this.columnSetNull = "drop not null";
|
||||
this.addForeignKeySkipCheck = " not valid";
|
||||
}
|
||||
|
||||
public String setLockTimeout(int lockTimeoutSeconds) {
|
||||
return "set lock_timeout = " + (lockTimeoutSeconds * 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
|
||||
/**
|
||||
* DB2 platform specific DDL.
|
||||
@@ -25,7 +26,7 @@ public class SQLiteDdl extends PlatformDdl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterTableAddForeignKey(WriteForeignKey request) {
|
||||
public String alterTableAddForeignKey(DdlOptions options, WriteForeignKey request) {
|
||||
// not supported
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.dbmigration.model;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DefaultConstraintMaxLength;
|
||||
import io.ebeaninternal.dbmigration.migration.ChangeSet;
|
||||
@@ -37,6 +38,8 @@ public class CurrentModel {
|
||||
|
||||
private DdlWrite write;
|
||||
|
||||
private DdlOptions ddlOptions = new DdlOptions();
|
||||
|
||||
/**
|
||||
* Construct with a given EbeanServer instance for DDL create all generation, not migration.
|
||||
*/
|
||||
@@ -63,6 +66,10 @@ public class CurrentModel {
|
||||
this.jaxbPresent = server.getServerConfig().getClassLoadConfig().isJavaxJAXBPresent();
|
||||
}
|
||||
|
||||
public DdlOptions getDdlOptions() {
|
||||
return ddlOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the model contains tables that are partitioned.
|
||||
*/
|
||||
@@ -183,7 +190,7 @@ public class CurrentModel {
|
||||
if (write == null) {
|
||||
ChangeSet createChangeSet = getChangeSet();
|
||||
|
||||
write = new DdlWrite(new MConfiguration(), model);
|
||||
write = new DdlWrite(new MConfiguration(), model, ddlOptions);
|
||||
|
||||
DdlHandler handler = handler();
|
||||
handler.generateProlog(write);
|
||||
|
||||
@@ -261,6 +261,13 @@ public class MColumn {
|
||||
return !draftOnly && !historyExclude;
|
||||
}
|
||||
|
||||
public void clearForeignKey() {
|
||||
this.references = null;
|
||||
this.foreignKeyName = null;
|
||||
this.fkeyOnDelete = null;
|
||||
this.fkeyOnUpdate = null;
|
||||
}
|
||||
|
||||
public Column createColumn() {
|
||||
|
||||
Column c = new Column();
|
||||
|
||||
@@ -273,8 +273,7 @@ public class MTable {
|
||||
}
|
||||
|
||||
for (MCompoundUniqueConstraint constraint : uniqueConstraints) {
|
||||
UniqueConstraint uq = constraint.getUniqueConstraint();
|
||||
createTable.getUniqueConstraint().add(uq);
|
||||
createTable.getUniqueConstraint().add(constraint.getUniqueConstraint());
|
||||
}
|
||||
|
||||
return createTable;
|
||||
@@ -789,4 +788,20 @@ public class MTable {
|
||||
public void setPartitionMeta(PartitionMeta partitionMeta) {
|
||||
this.partitionMeta = partitionMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear foreign key as this element collection table logically references
|
||||
* back to multiple tables.
|
||||
*/
|
||||
public MIndex setReusedElementCollection() {
|
||||
MIndex index = null;
|
||||
for (MColumn column : columns.values()) {
|
||||
final String references = column.getReferences();
|
||||
if (references != null) {
|
||||
index = new MIndex(column.getForeignKeyIndex(), name, column.getName());
|
||||
column.clearForeignKey();
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,11 +312,29 @@ public class ModelContainer {
|
||||
return tables.put(table.getName(), table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an element table taking into account if it is reused/references back
|
||||
* to multiple bean types (and so can't have foreign key).
|
||||
*/
|
||||
public void addTableElementCollection(MTable table) {
|
||||
final MTable reusedElementCollection = tables.get(table.getName());
|
||||
if (reusedElementCollection != null) {
|
||||
final MIndex index = reusedElementCollection.setReusedElementCollection();
|
||||
if (index != null) {
|
||||
indexes.put(index.getIndexName(), index);
|
||||
}
|
||||
} else {
|
||||
if (table.isPartitioned()) {
|
||||
partitionedTables.add(table);
|
||||
}
|
||||
tables.put(table.getName(), table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single column index.
|
||||
*/
|
||||
public void addIndex(String indexName, String tableName, String columnName) {
|
||||
|
||||
indexes.put(indexName, new MIndex(indexName, tableName, columnName));
|
||||
}
|
||||
|
||||
@@ -324,7 +342,6 @@ public class ModelContainer {
|
||||
* Add a multi column index.
|
||||
*/
|
||||
public void addIndex(String indexName, String tableName, String[] columnNames) {
|
||||
|
||||
indexes.put(indexName, new MIndex(indexName, tableName, columnNames));
|
||||
}
|
||||
|
||||
|
||||
@@ -33,10 +33,13 @@ public class PlatformDdlWriter {
|
||||
|
||||
private final PlatformDdl platformDdl;
|
||||
|
||||
public PlatformDdlWriter(DatabasePlatform platform, ServerConfig serverConfig, DbMigrationConfig config) {
|
||||
private final int lockTimeoutSeconds;
|
||||
|
||||
public PlatformDdlWriter(DatabasePlatform platform, ServerConfig serverConfig, DbMigrationConfig config, int lockTimeoutSeconds) {
|
||||
this.platformDdl = PlatformDdlBuilder.create(platform);
|
||||
this.serverConfig = serverConfig;
|
||||
this.config = config;
|
||||
this.lockTimeoutSeconds = lockTimeoutSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,6 +49,13 @@ public class PlatformDdlWriter {
|
||||
|
||||
DdlHandler handler = handler();
|
||||
handler.generateProlog(write);
|
||||
if (lockTimeoutSeconds > 0) {
|
||||
String lockSql = platformDdl.setLockTimeout(lockTimeoutSeconds);
|
||||
if (lockSql != null) {
|
||||
write.apply().append(lockSql).endOfStatement().newLine();
|
||||
}
|
||||
}
|
||||
|
||||
List<ChangeSet> changeSets = dbMigration.getChangeSet();
|
||||
for (ChangeSet changeSet : changeSets) {
|
||||
if (isApply(changeSet)) {
|
||||
|
||||
@@ -95,6 +95,10 @@ public class ModelBuildContext {
|
||||
return model.addTable(table);
|
||||
}
|
||||
|
||||
public void addTableElementCollection(MTable table) {
|
||||
model.addTableElementCollection(table);
|
||||
}
|
||||
|
||||
public void addIndex(String indexName, String tableName, String columnName) {
|
||||
model.addIndex(indexName, tableName, columnName);
|
||||
}
|
||||
|
||||
@@ -17,15 +17,11 @@ public class ModelBuildElementTable {
|
||||
public static void build(ModelBuildContext ctx, BeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
BeanTable beanTable = manyProp.getBeanTable();
|
||||
|
||||
BeanDescriptor<?> targetDescriptor = manyProp.getTargetDescriptor();
|
||||
|
||||
MTable table = new MTable(beanTable.getBaseTable());
|
||||
|
||||
VisitAllUsing.visitOne(targetDescriptor, new ModelBuildPropertyVisitor(ctx, table, targetDescriptor));
|
||||
|
||||
ctx.addTable(table);
|
||||
ctx.addTableElementCollection(table);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class CacheChangeSet {
|
||||
|
||||
final ManyKey key;
|
||||
|
||||
final List<Object> removes = new ArrayList<>();
|
||||
final Set<Object> removes = new HashSet<>();
|
||||
|
||||
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.meta.MetaOrmQueryNode;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
/**
|
||||
* Helper to collect the query execution statistics for a given node.
|
||||
*/
|
||||
public class CObjectGraphNodeStatistics {
|
||||
|
||||
private final ObjectGraphNode node;
|
||||
|
||||
private final LongAdder count = new LongAdder();
|
||||
|
||||
private final LongAdder totalTime = new LongAdder();
|
||||
|
||||
private final LongAdder totalBeans = new LongAdder();
|
||||
|
||||
private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
|
||||
|
||||
CObjectGraphNodeStatistics(ObjectGraphNode node) {
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return count.sum() == 0;
|
||||
}
|
||||
|
||||
public void add(long beanCount, long exeMicros) {
|
||||
count.increment();
|
||||
totalTime.add(exeMicros);
|
||||
totalBeans.add(beanCount);
|
||||
}
|
||||
|
||||
public MetaOrmQueryNode get(boolean reset) {
|
||||
if (reset) {
|
||||
return new Snapshot(node, startTime.getAndSet(System.currentTimeMillis()), count.sumThenReset(),
|
||||
totalTime.sumThenReset(), totalBeans.sumThenReset());
|
||||
} else {
|
||||
return new Snapshot(node, startTime.get(), count.sum(), totalTime.sum(), totalBeans.sum());
|
||||
}
|
||||
}
|
||||
|
||||
private static class Snapshot implements MetaOrmQueryNode {
|
||||
|
||||
private final ObjectGraphNode node;
|
||||
private final long startTime;
|
||||
private final long count;
|
||||
private final long totalTime;
|
||||
private final long totalBeans;
|
||||
|
||||
public Snapshot(ObjectGraphNode node, long startTime, long count, long totalTime, long totalBeans) {
|
||||
this.node = node;
|
||||
this.startTime = startTime;
|
||||
this.count = count;
|
||||
this.totalTime = totalTime;
|
||||
this.totalBeans = totalBeans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return node + " count[" + count + "] time[" + totalTime + "] beans[" + totalBeans + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalTime() {
|
||||
return totalTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalBeans() {
|
||||
return totalBeans;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.avaje.classpath.scanner.ClassPathScanner;
|
||||
import io.avaje.classpath.scanner.ClassPathScannerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.avaje.classpath.scanner.ClassPathScanner;
|
||||
import org.avaje.classpath.scanner.ClassPathScannerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user