mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7035eb228 | ||
|
|
1bf09ddd38 | ||
|
|
a8bf27da55 | ||
|
|
ee8bb5ef75 | ||
|
|
bcfd9cab1d | ||
|
|
2a5fd7f3a9 | ||
|
|
f8c37772d4 | ||
|
|
d988dbe69d | ||
|
|
5cb9b9b237 | ||
|
|
819d391495 | ||
|
|
1f0ed629a7 | ||
|
|
91044d0a75 | ||
|
|
57736185d0 | ||
|
|
8992980689 | ||
|
|
f341ff0167 | ||
|
|
abfa841ed7 | ||
|
|
e68adf53bc | ||
|
|
562d175de1 | ||
|
|
b5cef354ad | ||
|
|
09a887aeb7 | ||
|
|
53c903fa48 | ||
|
|
548454c90d | ||
|
|
94bab5f83b | ||
|
|
78965c1ac4 | ||
|
|
00b0fcaeb3 | ||
|
|
f7905c8e94 |
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
|
||||
@@ -78,7 +78,7 @@ public class DatabaseFactory {
|
||||
Database server = createInternal(config);
|
||||
if (config.isRegister()) {
|
||||
if (config.isDefaultServer()) {
|
||||
if (defaultServerName != null) {
|
||||
if (defaultServerName != null && !defaultServerName.equals(config.getName())) {
|
||||
throw new IllegalStateException("Registering [" + config.getName() + "] as the default server but [" + defaultServerName + "] is already registered as the default");
|
||||
}
|
||||
defaultServerName = config.getName();
|
||||
|
||||
@@ -46,7 +46,7 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to one of the static factory methods like {@link FetchConfig#ofQuery()}
|
||||
*
|
||||
* <p>
|
||||
* Construct using default JOIN mode.
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -89,7 +89,7 @@ public class FetchConfig implements Serializable {
|
||||
* Return FetchConfig to lazily load the relationship.
|
||||
*/
|
||||
public static FetchConfig ofLazy() {
|
||||
return new FetchConfig(LAZY_MODE, 10);
|
||||
return new FetchConfig(LAZY_MODE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,8 +110,8 @@ public class FetchConfig implements Serializable {
|
||||
* We want to migrate away from mutating FetchConfig to a fully immutable FetchConfig.
|
||||
*/
|
||||
private FetchConfig mutate(int mode, int batchSize) {
|
||||
if (batchSize < 1) {
|
||||
throw new IllegalArgumentException("batch size "+batchSize+" must be > 0");
|
||||
if (batchSize < 0) {
|
||||
throw new IllegalArgumentException("batch size " + batchSize + " must be > 0");
|
||||
}
|
||||
this.mode = mode;
|
||||
this.batchSize = batchSize;
|
||||
@@ -124,7 +124,7 @@ public class FetchConfig implements Serializable {
|
||||
*/
|
||||
@Deprecated
|
||||
public FetchConfig lazy() {
|
||||
return mutate(LAZY_MODE, 10);
|
||||
return mutate(LAZY_MODE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +137,7 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery().
|
||||
*
|
||||
* <p>
|
||||
* Eagerly fetch the beans in this path as a separate query (rather than as
|
||||
* part of the main query).
|
||||
* <p>
|
||||
@@ -150,17 +150,15 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
|
||||
*
|
||||
* <p>
|
||||
* Eagerly fetch the beans in this path as a separate query (rather than as
|
||||
* part of the main query).
|
||||
* <p>
|
||||
* The queryBatchSize is the number of parent id's that this separate query
|
||||
* will load per batch.
|
||||
* </p>
|
||||
* <p>
|
||||
* This will load all beans on this path eagerly unless a {@link #lazy(int)}
|
||||
* is also used.
|
||||
* </p>
|
||||
*
|
||||
* @param batchSize the batch size used to load beans on this path
|
||||
*/
|
||||
@@ -171,13 +169,12 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
|
||||
*
|
||||
* <p>
|
||||
* Eagerly fetch the first batch of beans on this path.
|
||||
* This is similar to {@link #query(int)} but only fetches the first batch.
|
||||
* <p>
|
||||
* If there are more parent beans than the batch size then they will not be
|
||||
* loaded eagerly but instead use lazy loading.
|
||||
* </p>
|
||||
*
|
||||
* @param batchSize the number of parent beans this path is populated for
|
||||
*/
|
||||
@@ -188,7 +185,7 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofCache().
|
||||
*
|
||||
* <p>
|
||||
* Eagerly fetch the beans fetching the beans from the L2 bean cache
|
||||
* and using the DB for beans not in the cache.
|
||||
*/
|
||||
|
||||
@@ -498,14 +498,23 @@ public class DatabaseConfig {
|
||||
private boolean notifyL2CacheInForeground;
|
||||
|
||||
/**
|
||||
* Set to true to support query plan capture.
|
||||
* Set to true to enable bind capture required for query plan capture.
|
||||
*/
|
||||
private boolean collectQueryPlans;
|
||||
private boolean queryPlanEnable;
|
||||
|
||||
/**
|
||||
* The default threshold in micros for collecting query plans.
|
||||
*/
|
||||
private long collectQueryPlanThresholdMicros = Long.MAX_VALUE;
|
||||
private long queryPlanThresholdMicros = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Set to true to enable automatic periodic query plan capture.
|
||||
*/
|
||||
private boolean queryPlanCapture;
|
||||
private long queryPlanCapturePeriodSecs = 60 * 10; // 10 minutes
|
||||
private long queryPlanCaptureMaxTimeMillis = 10_000; // 10 seconds
|
||||
private int queryPlanCaptureMaxCount = 10;
|
||||
private QueryPlanListener queryPlanListener;
|
||||
|
||||
/**
|
||||
* The time in millis used to determine when a query is alerted for being slow.
|
||||
@@ -1045,7 +1054,6 @@ public class DatabaseConfig {
|
||||
* This is a performance optimisation to reduce the number times Ebean
|
||||
* requests a sequence to be used as an Id for a bean (aka reduce network
|
||||
* chatter).
|
||||
|
||||
*/
|
||||
public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
|
||||
platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
@@ -2693,7 +2701,10 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings from ebean.properties.
|
||||
* Load settings from application.properties, application.yaml and other sources.
|
||||
* <p>
|
||||
* Uses <code>avaje-config</code> to load configuration properties. Goto https://avaje.io/config
|
||||
* for detail on how and where properties are loaded from.
|
||||
*/
|
||||
public void loadFromProperties() {
|
||||
this.properties = Config.asProperties();
|
||||
@@ -2802,8 +2813,12 @@ public class DatabaseConfig {
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
|
||||
slowQueryMillis = p.getLong("slowQueryMillis", slowQueryMillis);
|
||||
collectQueryPlans = p.getBoolean("collectQueryPlans", collectQueryPlans);
|
||||
collectQueryPlanThresholdMicros = p.getLong("collectQueryPlanThresholdMicros", collectQueryPlanThresholdMicros);
|
||||
queryPlanEnable = p.getBoolean("queryPlan.enable", queryPlanEnable);
|
||||
queryPlanThresholdMicros = p.getLong("queryPlan.thresholdMicros", queryPlanThresholdMicros);
|
||||
queryPlanCapture = p.getBoolean("queryPlan.capture", queryPlanCapture);
|
||||
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
|
||||
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
|
||||
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
|
||||
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
|
||||
@@ -3093,14 +3108,17 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plan time to live.
|
||||
* Return the time to live for ebean's internal query plan.
|
||||
*/
|
||||
public int getQueryPlanTTLSeconds() {
|
||||
return queryPlanTTLSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query plan time to live.
|
||||
* Set the time to live for ebean's internal query plan.
|
||||
* <p>
|
||||
* This is the plan that knows how to execute the query, read the result
|
||||
* and collects execution metrics. By default this is set to 5 mins.
|
||||
*/
|
||||
public void setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
|
||||
this.queryPlanTTLSeconds = queryPlanTTLSeconds;
|
||||
@@ -3173,29 +3191,110 @@ public class DatabaseConfig {
|
||||
/**
|
||||
* Return true if query plan capture is enabled.
|
||||
*/
|
||||
public boolean isCollectQueryPlans() {
|
||||
return collectQueryPlans;
|
||||
public boolean isQueryPlanEnable() {
|
||||
return queryPlanEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to enable query plan capture.
|
||||
*/
|
||||
public void setCollectQueryPlans(boolean collectQueryPlans) {
|
||||
this.collectQueryPlans = collectQueryPlans;
|
||||
public void setQueryPlanEnable(boolean queryPlanEnable) {
|
||||
this.queryPlanEnable = queryPlanEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plan collection threshold in microseconds.
|
||||
*/
|
||||
public long getCollectQueryPlanThresholdMicros() {
|
||||
return collectQueryPlanThresholdMicros;
|
||||
public long getQueryPlanThresholdMicros() {
|
||||
return queryPlanThresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query plan collection threshold in microseconds.
|
||||
* <p>
|
||||
* Queries executing slower than this will have bind values captured such that later
|
||||
* the query plan can be captured and reported.
|
||||
*/
|
||||
public void setCollectQueryPlanThresholdMicros(long collectQueryPlanThresholdMicros) {
|
||||
this.collectQueryPlanThresholdMicros = collectQueryPlanThresholdMicros;
|
||||
public void setQueryPlanThresholdMicros(long queryPlanThresholdMicros) {
|
||||
this.queryPlanThresholdMicros = queryPlanThresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if periodic capture of query plans is enabled.
|
||||
*/
|
||||
public boolean isQueryPlanCapture() {
|
||||
return queryPlanCapture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to turn on periodic capture of query plans.
|
||||
*/
|
||||
public void setQueryPlanCapture(boolean queryPlanCapture) {
|
||||
this.queryPlanCapture = queryPlanCapture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the frequency to capture query plans.
|
||||
*/
|
||||
public long getQueryPlanCapturePeriodSecs() {
|
||||
return queryPlanCapturePeriodSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frequency in seconds to capture query plans.
|
||||
*/
|
||||
public void setQueryPlanCapturePeriodSecs(long queryPlanCapturePeriodSecs) {
|
||||
this.queryPlanCapturePeriodSecs = queryPlanCapturePeriodSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time after which a capture query plans request will
|
||||
* stop capturing more query plans.
|
||||
* <p>
|
||||
* Effectively this controls the amount of load/time we want to
|
||||
* allow for query plan capture.
|
||||
*/
|
||||
public long getQueryPlanCaptureMaxTimeMillis() {
|
||||
return queryPlanCaptureMaxTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time after which a capture query plans request will
|
||||
* stop capturing more query plans.
|
||||
* <p>
|
||||
* Effectively this controls the amount of load/time we want to
|
||||
* allow for query plan capture.
|
||||
*/
|
||||
public void setQueryPlanCaptureMaxTimeMillis(long queryPlanCaptureMaxTimeMillis) {
|
||||
this.queryPlanCaptureMaxTimeMillis = queryPlanCaptureMaxTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max number of query plans captured per request.
|
||||
*/
|
||||
public int getQueryPlanCaptureMaxCount() {
|
||||
return queryPlanCaptureMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the max number of query plans captured per request.
|
||||
*/
|
||||
public void setQueryPlanCaptureMaxCount(int queryPlanCaptureMaxCount) {
|
||||
this.queryPlanCaptureMaxCount = queryPlanCaptureMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the listener used to process captured query plans.
|
||||
*/
|
||||
public QueryPlanListener getQueryPlanListener() {
|
||||
return queryPlanListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener used to process captured query plans.
|
||||
*/
|
||||
public void setQueryPlanListener(QueryPlanListener queryPlanListener) {
|
||||
this.queryPlanListener = queryPlanListener;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.meta.MetaQueryPlan;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The captured query plans.
|
||||
*/
|
||||
public class QueryPlanCapture {
|
||||
|
||||
private final Database database;
|
||||
private final List<MetaQueryPlan> plans;
|
||||
|
||||
public QueryPlanCapture(Database database, List<MetaQueryPlan> plans) {
|
||||
this.database = database;
|
||||
this.plans = plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database the plans were captured for.
|
||||
*/
|
||||
public Database getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the captured query plans.
|
||||
*/
|
||||
public List<MetaQueryPlan> getPlans() {
|
||||
return plans;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.ebean.config;
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL: Listener for captured query plans.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface QueryPlanListener {
|
||||
|
||||
/**
|
||||
* Process the captured query plans.
|
||||
*/
|
||||
void process(QueryPlanCapture capture);
|
||||
}
|
||||
@@ -41,6 +41,9 @@ public class QueryPlanRequest {
|
||||
|
||||
/**
|
||||
* Set the maximum number of plans to capture.
|
||||
* <p>
|
||||
* Use this to limit how much query plan capturing is done as query
|
||||
* plan capture is actual database load.
|
||||
*/
|
||||
public void setMaxCount(int maxCount) {
|
||||
this.maxCount = maxCount;
|
||||
@@ -58,7 +61,9 @@ public class QueryPlanRequest {
|
||||
/**
|
||||
* Set the maximum amount of time we want to use to capture plans.
|
||||
* <p>
|
||||
* Query plan collection will stop once this time is exceeded.
|
||||
* Query plan collection will stop once this time is exceeded. We use
|
||||
* this to ensure the query plan capture does not use excessive amount
|
||||
* of time - put too much load on the database.
|
||||
*/
|
||||
public void setMaxTimeMillis(long maxTimeMillis) {
|
||||
this.maxTimeMillis = maxTimeMillis;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.8.0</tag>
|
||||
<tag>ebean-parent-12.8.1</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+17
-17
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -18,8 +18,8 @@
|
||||
<ebean-migration.version>12.4.0</ebean-migration.version>
|
||||
<ebean-test-docker.version>4.1</ebean-test-docker.version>
|
||||
<ebean-datasource.version>7.0</ebean-datasource.version>
|
||||
<ebean-agent.version>12.6.6</ebean-agent.version>
|
||||
<ebean-maven-plugin.version>12.6.6</ebean-maven-plugin.version>
|
||||
<ebean-agent.version>12.8.1</ebean-agent.version>
|
||||
<ebean-maven-plugin.version>12.8.1</ebean-maven-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -81,88 +81,88 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.8.0</tag>
|
||||
<tag>ebean-parent-12.8.1</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -87,19 +87,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -302,7 +302,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.6.6</version>
|
||||
<version>12.8.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -1,52 +1,25 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebeaninternal.server.expression.IdInExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Used for bean cache lookup with where ids in expression.
|
||||
* Process Cache lookup by Id(s).
|
||||
*/
|
||||
public class CacheIdLookup<T> {
|
||||
|
||||
private final IdInExpression idInExpression;
|
||||
|
||||
private int remaining;
|
||||
|
||||
public CacheIdLookup(IdInExpression idInExpression) {
|
||||
this.idInExpression = idInExpression;
|
||||
}
|
||||
public interface CacheIdLookup<T> {
|
||||
|
||||
/**
|
||||
* Return the Id values for the in expression.
|
||||
* Return the Id values to lookup against the L2 cache.
|
||||
*/
|
||||
public Collection<?> idValues() {
|
||||
return idInExpression.idValues();
|
||||
}
|
||||
Collection<?> idValues();
|
||||
|
||||
/**
|
||||
* Process the hits returning the beans fetched from cache and
|
||||
* adjusting the in expression (to not fetch the hits).
|
||||
* Remove the hits returning the beans fetched from L2 cache.
|
||||
*/
|
||||
public List<T> removeHits(BeanCacheResult<T> cacheResult) {
|
||||
List<T> removeHits(BeanCacheResult<T> cacheResult);
|
||||
|
||||
Set<Object> hitIds = new HashSet<>();
|
||||
List<T> beans = new ArrayList<>(hitIds.size());
|
||||
|
||||
for (BeanCacheResult.Entry<T> hit : cacheResult.hits()) {
|
||||
hitIds.add(hit.getKey());
|
||||
beans.add(hit.getBean());
|
||||
}
|
||||
|
||||
this.remaining = idInExpression.removeIds(hitIds);
|
||||
return beans;
|
||||
}
|
||||
|
||||
public boolean allHits() {
|
||||
return remaining == 0;
|
||||
}
|
||||
/**
|
||||
* Return true if all beans where found in L2 cache.
|
||||
*/
|
||||
boolean allHits();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebeaninternal.server.expression.IdInExpression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Used for bean cache lookup with where ids in expression.
|
||||
*/
|
||||
public class CacheIdLookupMany<T> implements CacheIdLookup<T> {
|
||||
|
||||
private final IdInExpression idInExpression;
|
||||
|
||||
private int remaining;
|
||||
|
||||
public CacheIdLookupMany(IdInExpression idInExpression) {
|
||||
this.idInExpression = idInExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id values for the in expression.
|
||||
*/
|
||||
@Override
|
||||
public Collection<?> idValues() {
|
||||
return idInExpression.idValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the hits returning the beans fetched from cache and
|
||||
* adjusting the in expression (to not fetch the hits).
|
||||
*/
|
||||
@Override
|
||||
public List<T> removeHits(BeanCacheResult<T> cacheResult) {
|
||||
|
||||
Set<Object> hitIds = new HashSet<>();
|
||||
List<T> beans = new ArrayList<>(hitIds.size());
|
||||
|
||||
for (BeanCacheResult.Entry<T> hit : cacheResult.hits()) {
|
||||
hitIds.add(hit.getKey());
|
||||
beans.add(hit.getBean());
|
||||
}
|
||||
|
||||
this.remaining = idInExpression.removeIds(hitIds);
|
||||
return beans;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allHits() {
|
||||
return remaining == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for bean cache lookup with a single id value.
|
||||
*/
|
||||
public class CacheIdLookupSingle<T> implements CacheIdLookup<T> {
|
||||
|
||||
private final Object idValue;
|
||||
private boolean found;
|
||||
|
||||
public CacheIdLookupSingle(Object idValue) {
|
||||
this.idValue = idValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> idValues() {
|
||||
return Collections.singleton(idValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> removeHits(BeanCacheResult<T> cacheResult) {
|
||||
final List<BeanCacheResult.Entry<T>> hits = cacheResult.hits();
|
||||
if (hits.size() == 1) {
|
||||
found = true;
|
||||
return Collections.singletonList(hits.get(0).getBean());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allHits() {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ public interface LoadContext {
|
||||
/**
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
int getSecondaryQueriesMinBatchSize(int defaultQueryBatch);
|
||||
int getSecondaryQueriesMinBatchSize();
|
||||
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
|
||||
@@ -8,6 +8,11 @@ import java.util.List;
|
||||
|
||||
class NoopQueryPlanManager implements QueryPlanManager {
|
||||
|
||||
@Override
|
||||
public void setDefaultThreshold(long thresholdMicros) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiQueryBindCapture createBindCapture(SpiQueryPlan queryPlan) {
|
||||
return SpiQueryBindCapture.NOOP;
|
||||
|
||||
@@ -12,6 +12,11 @@ public interface QueryPlanManager {
|
||||
|
||||
QueryPlanManager NOOP = new NoopQueryPlanManager();
|
||||
|
||||
/**
|
||||
* Update the global default threshold used when new query plans are created.
|
||||
*/
|
||||
void setDefaultThreshold(long thresholdMicros);
|
||||
|
||||
/**
|
||||
* Create the bind capture for the given query plan.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@@ -19,4 +20,8 @@ public interface SpiQueryFetch {
|
||||
*/
|
||||
void fetchProperties(String name, Set<String> properties, FetchConfig config);
|
||||
|
||||
/**
|
||||
* Add a nested fetch graph.
|
||||
*/
|
||||
void addNested(String name, OrmQueryDetail nestedDetail, FetchConfig config);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.config.QueryPlanCapture;
|
||||
import io.ebean.config.QueryPlanListener;
|
||||
import io.ebean.meta.MetaQueryPlan;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class DefaultQueryPlanListener implements QueryPlanListener {
|
||||
|
||||
static final QueryPlanListener INSTANT = new DefaultQueryPlanListener();
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean.QUERYPLAN");
|
||||
|
||||
@Override
|
||||
public void process(QueryPlanCapture capture) {
|
||||
// better to log this in JSON form?
|
||||
String dbName = capture.getDatabase().getName();
|
||||
for (MetaQueryPlan plan : capture.getPlans()) {
|
||||
log.info("queryPlan db:{} label:{} queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}",
|
||||
dbName, plan.getLabel(), plan.getQueryTimeMicros(), plan.getProfileLocation(),
|
||||
plan.getSql(), plan.getBind(), plan.getPlan());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,12 +45,7 @@ import io.ebean.bean.PersistenceContext.WithOption;
|
||||
import io.ebean.bean.SingleBeanLoader;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.EncryptKeyManager;
|
||||
import io.ebean.config.SlowQueryEvent;
|
||||
import io.ebean.config.SlowQueryListener;
|
||||
import io.ebean.config.TenantMode;
|
||||
import io.ebean.config.*;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.event.BeanPersistController;
|
||||
import io.ebean.event.ShutdownManager;
|
||||
@@ -125,6 +120,7 @@ import io.ebeanservice.docstore.api.DocStoreIntegration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
@@ -137,7 +133,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -145,6 +140,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@@ -196,7 +192,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
private final SpiLogManager logManager;
|
||||
private final PersistenceContextScope defaultPersistenceContextScope;
|
||||
private final int lazyLoadBatchSize;
|
||||
private final int queryBatchSize;
|
||||
private final boolean updateAllPropertiesInBatch;
|
||||
private final long slowQueryMicros;
|
||||
private final SlowQueryListener slowQueryListener;
|
||||
@@ -217,7 +212,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
this.extraMetrics = config.getExtraMetrics();
|
||||
this.serverName = this.config.getName();
|
||||
this.lazyLoadBatchSize = this.config.getLazyLoadBatchSize();
|
||||
this.queryBatchSize = this.config.getQueryBatchSize();
|
||||
this.cqueryEngine = config.getCQueryEngine();
|
||||
this.expressionFactory = config.getExpressionFactory();
|
||||
this.encryptKeyManager = this.config.getEncryptKeyManager();
|
||||
@@ -305,10 +299,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return lazyLoadBatchSize;
|
||||
}
|
||||
|
||||
public int getQueryBatchSize() {
|
||||
return queryBatchSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object currentTenantId() {
|
||||
return currentTenantProvider == null ? null : currentTenantProvider.currentId();
|
||||
@@ -410,6 +400,31 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
migrationRunner.loadProperties(config.getProperties());
|
||||
migrationRunner.run(config.getDataSource());
|
||||
}
|
||||
startQueryPlanCapture();
|
||||
}
|
||||
|
||||
private void startQueryPlanCapture() {
|
||||
if (config.isQueryPlanCapture()) {
|
||||
long secs = config.getQueryPlanCapturePeriodSecs();
|
||||
if (secs > 10) {
|
||||
logger.info("capture query plan enabled, every {}secs", secs);
|
||||
backgroundExecutor.scheduleWithFixedDelay(this::collectQueryPlans, secs, secs, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void collectQueryPlans() {
|
||||
QueryPlanRequest request = new QueryPlanRequest();
|
||||
request.setMaxCount(config.getQueryPlanCaptureMaxCount());
|
||||
request.setMaxTimeMillis(config.getQueryPlanCaptureMaxTimeMillis());
|
||||
|
||||
// obtains query explain plans ...
|
||||
List<MetaQueryPlan> plans = metaInfoManager.queryPlanCollectNow(request);
|
||||
QueryPlanListener listener = config.getQueryPlanListener();
|
||||
if (listener == null) {
|
||||
listener = DefaultQueryPlanListener.INSTANT;
|
||||
}
|
||||
listener.process(new QueryPlanCapture(this, plans));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1150,6 +1165,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction) {
|
||||
return Optional.ofNullable(findOne(query, transaction));
|
||||
@@ -1180,6 +1196,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T> Set<T> findSet(Query<T> query, Transaction t) {
|
||||
@@ -1196,6 +1213,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <K, T> Map<K, T> findMap(Query<T> query, Transaction t) {
|
||||
@@ -1217,6 +1235,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A, T> List<A> findSingleAttributeList(Query<T> query, Transaction t) {
|
||||
@@ -1227,7 +1246,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return (List<A>) request.findSingleAttributeList();
|
||||
return request.findSingleAttributeList();
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1277,6 +1296,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <A, T> List<A> findIds(Query<T> query, Transaction t) {
|
||||
return findIdsWithCopy(((SpiQuery<T>) query).copy(), t);
|
||||
@@ -1337,26 +1357,29 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> FutureRowCount<T> findFutureCount(Query<T> q, Transaction t) {
|
||||
SpiQuery<T> copy = ((SpiQuery<T>) q).copy();
|
||||
copy.setFutureFetch(true);
|
||||
Transaction newTxn = createTransaction();
|
||||
QueryFutureRowCount<T> queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<T>(this, copy, newTxn));
|
||||
QueryFutureRowCount<T> queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(Query<T> query, Transaction t) {
|
||||
SpiQuery<T> copy = ((SpiQuery<T>) query).copy();
|
||||
copy.setFutureFetch(true);
|
||||
Transaction newTxn = createTransaction();
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<T>(this, copy, newTxn));
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(Query<T> query, Transaction t) {
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
@@ -1369,11 +1392,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
// Create a new transaction solely to execute the findList() at some future time
|
||||
Transaction newTxn = createTransaction();
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<T>(this, spiQuery, newTxn));
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction) {
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
@@ -1387,6 +1411,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return new LimitOffsetPagedList<>(this, spiQuery);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> QueryIterator<T> findIterate(Query<T> query, Transaction t) {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
@@ -1399,11 +1424,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> Stream<T> findLargeStream(Query<T> query, Transaction transaction) {
|
||||
return findStream(query, transaction);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> Stream<T> findStream(Query<T> query, Transaction transaction) {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
|
||||
@@ -1470,6 +1497,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
// no try finally - findEachWhile guarantee's cleanup of the transaction if required
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> List<Version<T>> findVersions(Query<T> query, Transaction transaction) {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, transaction);
|
||||
@@ -1481,6 +1509,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> List<T> findList(Query<T> query, Transaction t) {
|
||||
return findList(query, t, false);
|
||||
@@ -1540,6 +1569,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public List<SqlRow> findList(SqlQuery query, Transaction t) {
|
||||
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, t);
|
||||
@@ -2241,6 +2271,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return checkUniqueness(bean, null);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Set<Property> checkUniqueness(Object bean, Transaction transaction) {
|
||||
EntityBean entityBean = checkEntityBean(bean);
|
||||
@@ -2252,14 +2283,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
Object id = idProperty.getVal(entityBean);
|
||||
if (entityBean._ebean_getIntercept().isNew() && id != null) {
|
||||
// Primary Key is changeable only on new models - so skip check if we are not
|
||||
// new.
|
||||
// Primary Key is changeable only on new models - so skip check if we are not new
|
||||
Query<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
|
||||
query.setId(id);
|
||||
if (findCount(query, transaction) > 0) {
|
||||
Set<Property> ret = new HashSet<>();
|
||||
ret.add(idProperty);
|
||||
return ret;
|
||||
return Collections.singleton(idProperty);
|
||||
}
|
||||
}
|
||||
for (BeanProperty[] props : beanDesc.getUniqueProps()) {
|
||||
@@ -2322,6 +2350,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
List<MetaQueryPlan> queryPlanInit(QueryPlanInit initRequest) {
|
||||
if (initRequest.isAll()) {
|
||||
queryPlanManager.setDefaultThreshold(initRequest.getThresholdMicros());
|
||||
}
|
||||
return beanDescriptorManager.queryPlanInit(initRequest);
|
||||
}
|
||||
|
||||
|
||||
@@ -617,10 +617,10 @@ public class InternalConfiguration {
|
||||
}
|
||||
|
||||
public QueryPlanManager initQueryPlanManager(TransactionManager transactionManager) {
|
||||
if (!config.isCollectQueryPlans()) {
|
||||
if (!config.isQueryPlanEnable()) {
|
||||
return QueryPlanManager.NOOP;
|
||||
}
|
||||
long threshold = config.getCollectQueryPlanThresholdMicros();
|
||||
long threshold = config.getQueryPlanThresholdMicros();
|
||||
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.getPlatform()), extraMetrics);
|
||||
}
|
||||
|
||||
|
||||
@@ -173,8 +173,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
* iteration is fine.
|
||||
* </p>
|
||||
*/
|
||||
public int getSecondaryQueriesMinBatchSize(int defaultQueryBatch) {
|
||||
return loadContext.getSecondaryQueriesMinBatchSize(defaultQueryBatch);
|
||||
public int getSecondaryQueriesMinBatchSize() {
|
||||
return loadContext.getSecondaryQueriesMinBatchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
private static final Logger logger = LoggerFactory.getLogger(BeanDescriptorManager.class);
|
||||
|
||||
private static final BeanDescComparator beanDescComparator = new BeanDescComparator();
|
||||
public static final String JAVA_LANG_RECORD = "java.lang.Record";
|
||||
|
||||
private final ReadAnnotations readAnnotations;
|
||||
private final TransientProperties transientProperties;
|
||||
@@ -1418,14 +1419,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void checkInheritedClasses(Class<?> beanClass) {
|
||||
Class<?> superclass = beanClass.getSuperclass();
|
||||
if (Object.class.equals(superclass)) {
|
||||
if (Object.class.equals(superclass) || Model.class.equals(superclass) || JAVA_LANG_RECORD.equals(superclass.getName())) {
|
||||
// we got to the top of the inheritance
|
||||
return;
|
||||
}
|
||||
if (Model.class.equals(superclass)) {
|
||||
// top of the inheritance. Not enhancing Model at this stage
|
||||
return;
|
||||
}
|
||||
if (!EntityBean.class.isAssignableFrom(superclass)) {
|
||||
if (isMappedSuperWithNoProperties(superclass)) {
|
||||
// ok to stop and treat just the same as Object.class
|
||||
|
||||
@@ -33,7 +33,7 @@ abstract class DLoadBaseContext {
|
||||
|
||||
final boolean queryFetch;
|
||||
|
||||
DLoadBaseContext(DLoadContext parent, BeanDescriptor<?> desc, String path, int defaultBatchSize, OrmQueryProperties queryProps) {
|
||||
DLoadBaseContext(DLoadContext parent, BeanDescriptor<?> desc, String path, OrmQueryProperties queryProps) {
|
||||
this.parent = parent;
|
||||
this.serverName = parent.getEbeanServer().getName();
|
||||
this.desc = desc;
|
||||
@@ -42,11 +42,7 @@ abstract class DLoadBaseContext {
|
||||
this.hitCache = parent.isBeanCacheGet() && desc.isBeanCaching();
|
||||
this.objectGraphNode = parent.getObjectGraphNode(path);
|
||||
this.queryFetch = queryProps != null && queryProps.isQueryFetch();
|
||||
this.batchSize = initBatchSize(defaultBatchSize, queryProps);
|
||||
}
|
||||
|
||||
private int initBatchSize(int batchSize, OrmQueryProperties queryProps) {
|
||||
return queryProps == null ? batchSize : queryProps.getBatchSize();
|
||||
this.batchSize = parent.batchSize(queryProps);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,8 +31,8 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
|
||||
private LoadBuffer currentBuffer;
|
||||
|
||||
DLoadBeanContext(DLoadContext parent, BeanDescriptor<?> desc, String path, int defaultBatchSize, OrmQueryProperties queryProps) {
|
||||
super(parent, desc, path, defaultBatchSize, queryProps);
|
||||
DLoadBeanContext(DLoadContext parent, BeanDescriptor<?> desc, String path, OrmQueryProperties queryProps) {
|
||||
super(parent, desc, path, queryProps);
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<>();
|
||||
this.currentBuffer = createBuffer(batchSize);
|
||||
|
||||
@@ -90,7 +90,7 @@ public class DLoadContext implements LoadContext {
|
||||
this.planLabel = null;
|
||||
this.profileLocation = null;
|
||||
this.profilingListener = null;
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, defaultBatchSize, null);
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, null);
|
||||
}
|
||||
|
||||
private ObjectGraphOrigin initOrigin() {
|
||||
@@ -128,7 +128,7 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
// initialise rootBeanContext after origin and relativePath have been set
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, defaultBatchSize, null);
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, null);
|
||||
registerSecondaryQueries(secondaryQueries);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class DLoadContext implements LoadContext {
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
@Override
|
||||
public int getSecondaryQueriesMinBatchSize(int defaultQueryBatch) {
|
||||
public int getSecondaryQueriesMinBatchSize() {
|
||||
if (secQuery == null) {
|
||||
return -1;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ public class DLoadContext implements LoadContext {
|
||||
for (OrmQueryProperties aSecQuery : secQuery) {
|
||||
int batchSize = aSecQuery.getBatchSize();
|
||||
if (batchSize == 0) {
|
||||
batchSize = defaultQueryBatch;
|
||||
batchSize = 100;
|
||||
}
|
||||
maxBatch = Math.max(maxBatch, batchSize);
|
||||
}
|
||||
@@ -287,51 +287,55 @@ public class DLoadContext implements LoadContext {
|
||||
getManyContext(path, many).register(bc);
|
||||
}
|
||||
|
||||
int batchSize(OrmQueryProperties props) {
|
||||
if (props == null) {
|
||||
return defaultBatchSize;
|
||||
}
|
||||
int batchSize = props.getBatchSize();
|
||||
return batchSize == 0 ? defaultBatchSize : batchSize;
|
||||
}
|
||||
|
||||
DLoadBeanContext getBeanContext(String path) {
|
||||
if (path == null) {
|
||||
return rootBeanContext;
|
||||
}
|
||||
return beanMap.computeIfAbsent(path, p -> createBeanContext(p, defaultBatchSize, null));
|
||||
return beanMap.computeIfAbsent(path, p -> createBeanContext(p, null));
|
||||
}
|
||||
|
||||
DLoadBeanContext getBeanContextWithInherit(String path, BeanPropertyAssocOne<?> property) {
|
||||
String key = path + ":" + property.getTargetDescriptor().getName();
|
||||
return beanMap.computeIfAbsent(key, p -> createBeanContext(property, path, defaultBatchSize, null));
|
||||
return beanMap.computeIfAbsent(key, p -> createBeanContext(property, path, null));
|
||||
}
|
||||
|
||||
private void registerSecondaryNode(boolean many, OrmQueryProperties props) {
|
||||
int batchSize = props.getBatchSize();
|
||||
if (batchSize == 0) {
|
||||
batchSize = defaultBatchSize;
|
||||
}
|
||||
String path = props.getPath();
|
||||
if (many) {
|
||||
manyMap.put(path, createManyContext(path, batchSize, props));
|
||||
manyMap.put(path, createManyContext(path, props));
|
||||
} else {
|
||||
beanMap.put(path, createBeanContext(path, batchSize, props));
|
||||
beanMap.put(path, createBeanContext(path, props));
|
||||
}
|
||||
}
|
||||
|
||||
DLoadManyContext getManyContext(String path, BeanPropertyAssocMany<?> many) {
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, many, defaultBatchSize));
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, many));
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, BeanPropertyAssocMany<?> many, int batchSize) {
|
||||
return new DLoadManyContext(this, many, path, batchSize, null);
|
||||
private DLoadManyContext createManyContext(String path, BeanPropertyAssocMany<?> many) {
|
||||
return new DLoadManyContext(this, many, path, null);
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
private DLoadManyContext createManyContext(String path, OrmQueryProperties queryProps) {
|
||||
BeanPropertyAssocMany<?> p = (BeanPropertyAssocMany<?>) getBeanProperty(rootDescriptor, path);
|
||||
return new DLoadManyContext(this, p, path, batchSize, queryProps);
|
||||
return new DLoadManyContext(this, p, path, queryProps);
|
||||
}
|
||||
|
||||
private DLoadBeanContext createBeanContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
private DLoadBeanContext createBeanContext(String path, OrmQueryProperties queryProps) {
|
||||
BeanPropertyAssoc<?> p = (BeanPropertyAssoc<?>) getBeanProperty(rootDescriptor, path);
|
||||
return new DLoadBeanContext(this, p.getTargetDescriptor(), path, batchSize, queryProps);
|
||||
return new DLoadBeanContext(this, p.getTargetDescriptor(), path, queryProps);
|
||||
}
|
||||
|
||||
private DLoadBeanContext createBeanContext(BeanPropertyAssoc<?> property, String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
return new DLoadBeanContext(this, property.getTargetDescriptor(), path, batchSize, queryProps);
|
||||
private DLoadBeanContext createBeanContext(BeanPropertyAssoc<?> property, String path, OrmQueryProperties queryProps) {
|
||||
return new DLoadBeanContext(this, property.getTargetDescriptor(), path, queryProps);
|
||||
}
|
||||
|
||||
private BeanProperty getBeanProperty(BeanDescriptor<?> desc, String path) {
|
||||
|
||||
@@ -31,11 +31,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
|
||||
private LoadBuffer currentBuffer;
|
||||
|
||||
DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property,
|
||||
String path, int defaultBatchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
|
||||
DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property, String path, OrmQueryProperties queryProps) {
|
||||
super(parent, property.getBeanDescriptor(), path, queryProps);
|
||||
this.property = property;
|
||||
this.docStoreMapped = property.isTargetDocStoreMapped();
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
class CQueryBindCapture implements SpiQueryBindCapture {
|
||||
|
||||
private static final double multiplier = 1.3d;
|
||||
private static final double multiplier = 1.5d;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final CQueryPlanManager manager;
|
||||
|
||||
@@ -37,8 +37,6 @@ public class CQueryEngine {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CQueryEngine.class);
|
||||
|
||||
private static final int defaultSecondaryQueryBatchSize = 100;
|
||||
|
||||
private static final String T0 = "t0";
|
||||
|
||||
private final int defaultFetchSizeFindList;
|
||||
@@ -214,7 +212,7 @@ public class CQueryEngine {
|
||||
logSql(cquery);
|
||||
}
|
||||
// first check batch sizes set on query joins
|
||||
int iterateBufferSize = request.getSecondaryQueriesMinBatchSize(defaultSecondaryQueryBatchSize);
|
||||
int iterateBufferSize = request.getSecondaryQueriesMinBatchSize();
|
||||
if (iterateBufferSize < 1) {
|
||||
// not set on query joins so check if batch size set on query itself
|
||||
int queryBatch = request.getQuery().getLazyLoadBatchSize();
|
||||
|
||||
@@ -30,14 +30,14 @@ public class CQueryPlanManager implements QueryPlanManager {
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final long defaultThreshold;
|
||||
|
||||
private final QueryPlanLogger planLogger;
|
||||
|
||||
private final TimedMetric timeCollection;
|
||||
|
||||
private final TimedMetric timeBindCapture;
|
||||
|
||||
private long defaultThreshold;
|
||||
|
||||
public CQueryPlanManager(TransactionManager transactionManager, long defaultThreshold, QueryPlanLogger planLogger, ExtraMetrics extraMetrics) {
|
||||
this.transactionManager = transactionManager;
|
||||
this.defaultThreshold = defaultThreshold;
|
||||
@@ -46,6 +46,11 @@ public class CQueryPlanManager implements QueryPlanManager {
|
||||
this.timeBindCapture = extraMetrics.getBindCapture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultThreshold(long thresholdMicros) {
|
||||
this.defaultThreshold = thresholdMicros;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiQueryBindCapture createBindCapture(SpiQueryPlan queryPlan) {
|
||||
return new CQueryBindCapture(this, queryPlan, defaultThreshold);
|
||||
|
||||
@@ -644,4 +644,9 @@ class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQueryFetch
|
||||
public void fetchProperties(String property, Set<String> columns, FetchConfig config) {
|
||||
detail.fetchProperties(property, columns, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNested(String name, OrmQueryDetail nestedDetail, FetchConfig config) {
|
||||
detail.addNested(name, nestedDetail, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,8 @@ import io.ebean.plugin.BeanType;
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.CQueryPlanKey;
|
||||
import io.ebeaninternal.api.CacheIdLookup;
|
||||
import io.ebeaninternal.api.CacheIdLookupMany;
|
||||
import io.ebeaninternal.api.CacheIdLookupSingle;
|
||||
import io.ebeaninternal.api.HashQuery;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
@@ -740,10 +742,14 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return null;
|
||||
}
|
||||
List<SpiExpression> underlyingList = whereExpressions.getUnderlyingList();
|
||||
if (underlyingList.size() == 1) {
|
||||
if (underlyingList.isEmpty()) {
|
||||
if (id != null) {
|
||||
return new CacheIdLookupSingle<>(id);
|
||||
}
|
||||
} else if (underlyingList.size() == 1) {
|
||||
SpiExpression singleExpression = underlyingList.get(0);
|
||||
if (singleExpression instanceof IdInExpression) {
|
||||
return new CacheIdLookup<>((IdInExpression) singleExpression);
|
||||
return new CacheIdLookupMany<>((IdInExpression) singleExpression);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1412,6 +1418,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
detail.fetchProperties(path, other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNested(String name, OrmQueryDetail nestedDetail, FetchConfig config) {
|
||||
detail.addNested(name, nestedDetail, config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> select(String columns) {
|
||||
detail.select(columns);
|
||||
|
||||
@@ -120,8 +120,8 @@ public class OrmQueryProperties implements Serializable {
|
||||
this.parentPath = SplitName.parent(path);
|
||||
this.allProperties = other.allProperties;
|
||||
this.included = other.included;
|
||||
this.cache = other.cache;
|
||||
this.fetchConfig = fetchConfig;
|
||||
this.cache = fetchConfig.isCache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.FetchConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -10,7 +9,7 @@ public class FetchConfigTest {
|
||||
@Test
|
||||
public void testLazy() {
|
||||
FetchConfig config = new FetchConfig().lazy();
|
||||
assertThat(config.getBatchSize()).isEqualTo(10);
|
||||
assertThat(config.getBatchSize()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -72,10 +72,16 @@ public class ServerConfigTest {
|
||||
props.setProperty("enabledL2Regions", "r0,users,orgs");
|
||||
props.setProperty("caseSensitiveCollation", "false");
|
||||
props.setProperty("loadModuleInfo", "true");
|
||||
props.setProperty("collectQueryPlanThresholdMicros", "10000");
|
||||
props.setProperty("forUpdateNoKey", "true");
|
||||
props.setProperty("defaultServer", "false");
|
||||
|
||||
props.setProperty("queryPlan.enable", "true");
|
||||
props.setProperty("queryPlan.thresholdMicros", "10000");
|
||||
props.setProperty("queryPlan.capture", "true");
|
||||
props.setProperty("queryPlan.capturePeriodSecs", "42");
|
||||
props.setProperty("queryPlan.captureMaxTimeMillis", "560");
|
||||
props.setProperty("queryPlan.captureMaxCount", "7");
|
||||
|
||||
serverConfig.loadFromProperties(props);
|
||||
|
||||
assertFalse(serverConfig.isDefaultServer());
|
||||
@@ -97,7 +103,6 @@ public class ServerConfigTest {
|
||||
assertEquals(PlatformConfig.DbUuid.BINARY, serverConfig.getPlatformConfig().getDbUuid());
|
||||
assertEquals(JsonConfig.DateTime.MILLIS, serverConfig.getJsonDateTime());
|
||||
assertEquals(JsonConfig.Date.MILLIS, serverConfig.getJsonDate());
|
||||
assertEquals(10000, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
|
||||
assertEquals("r0,users,orgs", serverConfig.getEnabledL2Regions());
|
||||
|
||||
@@ -106,6 +111,13 @@ public class ServerConfigTest {
|
||||
assertEquals(4, serverConfig.getBackgroundExecutorSchedulePoolSize());
|
||||
assertEquals(98, serverConfig.getBackgroundExecutorShutdownSecs());
|
||||
|
||||
assertTrue(serverConfig.isQueryPlanEnable());
|
||||
assertEquals(10000, serverConfig.getQueryPlanThresholdMicros());
|
||||
assertTrue(serverConfig.isQueryPlanCapture());
|
||||
assertEquals(42, serverConfig.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(560, serverConfig.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(7, serverConfig.getQueryPlanCaptureMaxCount());
|
||||
|
||||
assertThat(serverConfig.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
serverConfig.setPersistBatch(PersistBatch.NONE);
|
||||
@@ -144,7 +156,13 @@ public class ServerConfigTest {
|
||||
assertEquals(JsonConfig.Date.ISO8601, serverConfig.getJsonDate());
|
||||
assertTrue(serverConfig.getPlatformConfig().isCaseSensitiveCollation());
|
||||
assertTrue(serverConfig.isAutoLoadModuleInfo());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
|
||||
assertFalse(serverConfig.isQueryPlanEnable());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getQueryPlanThresholdMicros());
|
||||
assertFalse(serverConfig.isQueryPlanCapture());
|
||||
assertEquals(600, serverConfig.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, serverConfig.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, serverConfig.getQueryPlanCaptureMaxCount());
|
||||
|
||||
serverConfig.setLoadModuleInfo(false);
|
||||
assertFalse(serverConfig.isAutoLoadModuleInfo());
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ParseFetchConfigTest {
|
||||
@Test
|
||||
public void parseLazy() {
|
||||
FetchConfig lazy = ParseFetchConfig.parse("lazy");
|
||||
assertThat(lazy.getBatchSize()).isEqualTo(10);
|
||||
assertThat(lazy.getBatchSize()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -46,7 +46,12 @@ public class MainMemoryLeak {
|
||||
config.addClass(ECachedBean.class);
|
||||
config.loadFromProperties();
|
||||
|
||||
Database server1 = DatabaseFactory.create(config);
|
||||
assert server1 != null;
|
||||
|
||||
// create again for #2193
|
||||
Database server = DatabaseFactory.create(config);
|
||||
assert server != null;
|
||||
|
||||
// create a string with 10k chars
|
||||
char[] c = new char[10_000];
|
||||
|
||||
@@ -169,22 +169,40 @@ public class TestQueryFindEach extends BaseTestCase {
|
||||
DB.find(OmBasicParent.class).delete();
|
||||
insertData();
|
||||
|
||||
test_setLazyLoadBatchSize_withFetchLazy();
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
try (final Transaction transaction = DB.beginTransaction()) {
|
||||
// DB.find(OmBasicParent.class).findList();
|
||||
DB.find(OmBasicChild.class)
|
||||
.setLazyLoadBatchSize(100)
|
||||
//.fetchQuery("parent","name")
|
||||
//.fetch("parent","name")
|
||||
.findEach(child -> {
|
||||
assertNotNull(child.getParent().getName());
|
||||
});
|
||||
}
|
||||
|
||||
DB.find(OmBasicChild.class)
|
||||
.setLazyLoadBatchSize(100)
|
||||
.findEach(child -> {
|
||||
assertNotNull(child.getParent().getName());
|
||||
});
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql.size()).isLessThan(50);
|
||||
}
|
||||
|
||||
private void test_setLazyLoadBatchSize_withFetchLazy() {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
DB.find(OmBasicParent.class)
|
||||
.setLazyLoadBatchSize(5)
|
||||
.fetchLazy("children")
|
||||
.setMaxRows(50)
|
||||
.findEach(it -> {
|
||||
it.getChildren().size();
|
||||
});
|
||||
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(11);
|
||||
assertThat(sql.get(0)).contains(" from om_basic_parent ");
|
||||
for (int i = 1; i < 11; i++) {
|
||||
assertThat(sql.get(i)).contains(" --bind(Array[5]");
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(batchSize = 40)
|
||||
private void insertData() {
|
||||
for (int i = 0; i < 150; i++) {
|
||||
|
||||
@@ -175,17 +175,24 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
// change default collect query plan threshold to 200 micros
|
||||
QueryPlanInit init0 = new QueryPlanInit();
|
||||
init0.setAll(true);
|
||||
init0.setThresholdMicros(200);
|
||||
final List<MetaQueryPlan> plans = server().getMetaInfoManager().queryPlanInit(init0);
|
||||
assertThat(plans.size()).isGreaterThan(1);
|
||||
|
||||
// the server has some plans
|
||||
runQueries();
|
||||
|
||||
// enable query plan bind capture on all plans threshold 100 micros
|
||||
// change query plan threshold to 100 micros
|
||||
QueryPlanInit init = new QueryPlanInit();
|
||||
init.setAll(true);
|
||||
init.setThresholdMicros(100);
|
||||
final List<MetaQueryPlan> appliedToPlans = server().getMetaInfoManager().queryPlanInit(init);
|
||||
assertThat(appliedToPlans.size()).isGreaterThan(4);
|
||||
|
||||
// will collect bind captures
|
||||
// run queries again
|
||||
runQueries();
|
||||
|
||||
ServerMetrics metrics = server().getMetaInfoManager().collectMetrics();
|
||||
@@ -203,12 +210,21 @@ public class TestCustomerFinder extends BaseTestCase {
|
||||
|
||||
// obtains db query plans ...
|
||||
QueryPlanRequest request = new QueryPlanRequest();
|
||||
List<MetaQueryPlan> plans = server().getMetaInfoManager().queryPlanCollectNow(request);
|
||||
assertThat(plans).isNotEmpty();
|
||||
// collect max 1000 plans (use something more like 10)
|
||||
request.setMaxCount(1_000);
|
||||
// don't collect any more plans if used 10 secs
|
||||
request.setMaxTimeMillis(10_000);
|
||||
List<MetaQueryPlan> plans0 = server().getMetaInfoManager().queryPlanCollectNow(request);
|
||||
assertThat(plans0).isNotEmpty();
|
||||
|
||||
for (MetaQueryPlan plan : plans) {
|
||||
logger.info("queryplan label:{}, queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}",
|
||||
plan.getLabel(), plan.getQueryTimeMicros(), plan.getProfileLocation(),
|
||||
plan.getSql(), plan.getBind(), plan.getPlan());
|
||||
System.out.println(plan);
|
||||
}
|
||||
|
||||
//DB.getBackgroundExecutor().scheduleWithFixedDelay(...)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,8 +27,8 @@ datasource.default=h2
|
||||
|
||||
ebean.dumpMetricsOnShutdown=true
|
||||
ebean.dumpMetricsOptions=sql,hash
|
||||
#ebean.collectQueryPlanThresholdMicros=1000
|
||||
ebean.collectQueryPlans=true
|
||||
#ebean.queryPlan.thresholdMicros=1000
|
||||
ebean.queryPlan.enable=true
|
||||
|
||||
ebean.autoReadOnlyDataSource=true
|
||||
#datasource.h2-ro.url=jdbc:h2:mem:tests
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
<description>DDL and DB Migration generation</description>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<!-- <version>12.6.1.PreRelease.0</version>-->
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -29,14 +28,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -77,7 +76,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.6.6</version>
|
||||
<version>12.8.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ public class OracleDdl extends PlatformDdl {
|
||||
this.dropConstraintIfExists = "drop constraint";
|
||||
this.dropIndexIfExists = "drop index ";
|
||||
this.dropTableCascade = " cascade constraints purge";
|
||||
this.addColumn = "add";
|
||||
this.alterColumn = "modify";
|
||||
this.columnSetNotnull = "not null";
|
||||
this.columnSetNull = "null";
|
||||
|
||||
+4
-1
@@ -3,7 +3,6 @@ package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.DbConstraintNaming;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbIdentity;
|
||||
@@ -113,6 +112,7 @@ public class PlatformDdl {
|
||||
|
||||
protected String uniqueIndex = "unique";
|
||||
protected String indexConcurrent = "";
|
||||
protected String createIndexIfNotExists = "";
|
||||
|
||||
/**
|
||||
* Set false for MsSqlServer to allow multiple nulls for OneToOne mapping.
|
||||
@@ -414,6 +414,9 @@ public class PlatformDdl {
|
||||
if (create.isConcurrent()) {
|
||||
buffer.append(indexConcurrent);
|
||||
}
|
||||
if (create.isNotExistsCheck()) {
|
||||
buffer.append(createIndexIfNotExists);
|
||||
}
|
||||
buffer.append(maxConstraintName(create.getIndexName())).append(" on ").append(create.getTableName());
|
||||
appendColumns(create.getColumns(), buffer);
|
||||
return buffer.toString();
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ public class PostgresDdl extends PlatformDdl {
|
||||
this.dropTableCascade = " cascade";
|
||||
this.columnSetType = "type ";
|
||||
this.alterTableIfExists = "if exists ";
|
||||
this.createIndexIfNotExists = "if not exists ";
|
||||
this.columnSetNull = "drop not null";
|
||||
this.addForeignKeySkipCheck = " not valid";
|
||||
this.indexConcurrent = "concurrently ";
|
||||
|
||||
+13
@@ -12,7 +12,11 @@ class WriteCreateIndex {
|
||||
private final boolean unique;
|
||||
private final boolean concurrent;
|
||||
private final String definition;
|
||||
private final boolean notExistsCheck;
|
||||
|
||||
/**
|
||||
* Create index for foreign key.
|
||||
*/
|
||||
WriteCreateIndex(String indexName, String tableName, String[] columns, boolean unique) {
|
||||
this.indexName = indexName;
|
||||
this.tableName = tableName;
|
||||
@@ -20,8 +24,12 @@ class WriteCreateIndex {
|
||||
this.unique = unique;
|
||||
this.concurrent = false;
|
||||
this.definition = null;
|
||||
this.notExistsCheck = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create non-foreign key index.
|
||||
*/
|
||||
public WriteCreateIndex(CreateIndex index) {
|
||||
this.indexName = index.getIndexName();
|
||||
this.tableName = index.getTableName();
|
||||
@@ -29,6 +37,7 @@ class WriteCreateIndex {
|
||||
this.unique = Boolean.TRUE.equals(index.isUnique());
|
||||
this.concurrent = Boolean.TRUE.equals(index.isConcurrent());
|
||||
this.definition = index.getDefinition();
|
||||
this.notExistsCheck = true;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
@@ -58,4 +67,8 @@ class WriteCreateIndex {
|
||||
public boolean useDefinition() {
|
||||
return definition != null && !definition.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isNotExistsCheck() {
|
||||
return notExistsCheck;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class BaseTableDdlTest {
|
||||
ddlGen.alterTableAddColumn(write.apply(), "mytable", column, false, false);
|
||||
|
||||
String ddl = write.apply().getBuffer();
|
||||
assertThat(ddl).contains("alter table mytable add column col_name varchar2(20)");
|
||||
assertThat(ddl).contains("alter table mytable add col_name varchar2(20)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+20
@@ -9,11 +9,15 @@ import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.PlatformDdlBuilder;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterColumn;
|
||||
import io.ebeaninternal.dbmigration.migration.AlterForeignKey;
|
||||
import io.ebeaninternal.dbmigration.migration.Column;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -238,6 +242,22 @@ public class PlatformDdl_AlterColumnTest {
|
||||
assertTrue(exceptionCaught);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void oracle_alterTableAddColumn() throws IOException {
|
||||
DdlWrite write = new DdlWrite();
|
||||
oraDdl.alterTableAddColumn(write.apply(), "my_table", simpleColumn(), false, "1");
|
||||
assertThat(write.apply().getBuffer()).isEqualTo("alter table my_table add my_column int default 1 not null;\n");
|
||||
}
|
||||
|
||||
private Column simpleColumn() {
|
||||
Column column = new Column();
|
||||
column.setName("my_column");
|
||||
column.setType("int");
|
||||
column.setNotnull(true);
|
||||
column.setDefaultValue("1");
|
||||
return column;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useIdentityType_h2() {
|
||||
assertEquals(h2Ddl.useIdentityType(null), IdType.IDENTITY);
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.PlatformDdlBuilder;
|
||||
import io.ebeaninternal.dbmigration.migration.CreateIndex;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class PlatformDdl_CreateIndexTest {
|
||||
|
||||
private final PlatformDdl h2Ddl = PlatformDdlBuilder.create(new H2Platform());
|
||||
private final PlatformDdl pgDdl = PlatformDdlBuilder.create(new PostgresPlatform());
|
||||
private final PlatformDdl mysqlDdl = PlatformDdlBuilder.create(new MySqlPlatform());
|
||||
private final PlatformDdl oraDdl = PlatformDdlBuilder.create(new OraclePlatform());
|
||||
private final PlatformDdl sqlServerDdl = PlatformDdlBuilder.create(new SqlServer17Platform());
|
||||
private final PlatformDdl hanaDdl = PlatformDdlBuilder.create(new HanaPlatform());
|
||||
|
||||
{
|
||||
DatabaseConfig config = DB.getDefault().getPluginApi().getServerConfig();
|
||||
h2Ddl.configure(config);
|
||||
pgDdl.configure(config);
|
||||
mysqlDdl.configure(config);
|
||||
oraDdl.configure(config);
|
||||
sqlServerDdl.configure(config);
|
||||
hanaDdl.configure(config);
|
||||
}
|
||||
|
||||
WriteCreateIndex writeCreateIndex() {
|
||||
|
||||
return writeCreateIndex(true, true);
|
||||
}
|
||||
|
||||
WriteCreateIndex writeCreateIndex(boolean unique, boolean concurrent) {
|
||||
CreateIndex createIndex = new CreateIndex();
|
||||
createIndex.setIndexName("ix_mytab_acol");
|
||||
createIndex.setTableName("mytab");
|
||||
createIndex.setColumns("acol");
|
||||
createIndex.setUnique(unique);
|
||||
createIndex.setConcurrent(concurrent);
|
||||
return new WriteCreateIndex(createIndex);
|
||||
}
|
||||
|
||||
WriteCreateIndex fkeyCreateIndex(boolean unique) {
|
||||
return new WriteCreateIndex("ix_mytab_acol", "mytab", new String[]{"acol"}, unique);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void createUniqueIndex() {
|
||||
|
||||
WriteCreateIndex createIndex = writeCreateIndex();
|
||||
|
||||
String sql = h2Ddl.createIndex(createIndex);
|
||||
assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = pgDdl.createIndex(createIndex);
|
||||
assertEquals("create unique index concurrently if not exists ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = mysqlDdl.createIndex(createIndex);
|
||||
assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = sqlServerDdl.createIndex(createIndex);
|
||||
assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = oraDdl.createIndex(createIndex);
|
||||
assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = hanaDdl.createIndex(createIndex);
|
||||
assertThat(sql).isEqualTo("-- explicit index \"ix_mytab_acol\" for single column \"acol\" of table \"mytab\" is not necessary");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postgres_createIndex() {
|
||||
|
||||
String sql = pgDdl.createIndex(writeCreateIndex(true, true));
|
||||
assertEquals("create unique index concurrently if not exists ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = pgDdl.createIndex(writeCreateIndex(false, false));
|
||||
assertEquals("create index if not exists ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = pgDdl.createIndex(writeCreateIndex(true, false));
|
||||
assertEquals("create unique index if not exists ix_mytab_acol on mytab (acol)", sql);
|
||||
sql = pgDdl.createIndex(writeCreateIndex(false, true));
|
||||
assertEquals("create index concurrently if not exists ix_mytab_acol on mytab (acol)", sql);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postgres_fkeyCreateIndex() {
|
||||
String sql = pgDdl.createIndex(fkeyCreateIndex(true));
|
||||
assertEquals("create unique index ix_mytab_acol on mytab (acol)", sql);
|
||||
|
||||
sql = pgDdl.createIndex(fkeyCreateIndex(false));
|
||||
assertEquals("create index ix_mytab_acol on mytab (acol)", sql);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,11 +17,11 @@ create table migtest_mtm_m_migtest_mtm_c (
|
||||
constraint pk_migtest_mtm_m_migtest_mtm_c primary key (migtest_mtm_m_id,migtest_mtm_c_id)
|
||||
);
|
||||
|
||||
alter table migtest_ckey_detail add column one_key number(10);
|
||||
alter table migtest_ckey_detail add column two_key varchar2(127);
|
||||
alter table migtest_ckey_detail add one_key number(10);
|
||||
alter table migtest_ckey_detail add two_key varchar2(127);
|
||||
|
||||
alter table migtest_ckey_detail add constraint fk_migtest_ckey_detail_parent foreign key (one_key,two_key) references migtest_ckey_parent (one_key,two_key);
|
||||
alter table migtest_ckey_parent add column assoc_id number(10);
|
||||
alter table migtest_ckey_parent add assoc_id number(10);
|
||||
|
||||
alter table migtest_fk_cascade drop constraint fk_migtest_fk_cascade_one_id;
|
||||
alter table migtest_fk_cascade add constraint fk_migtest_fk_cascade_one_id foreign key (one_id) references migtest_fk_cascade_one (id);
|
||||
@@ -46,14 +46,14 @@ alter table migtest_e_basic modify status2 null;
|
||||
insert into migtest_e_user (id) select distinct user_id from migtest_e_basic;
|
||||
alter table migtest_e_basic add constraint fk_migtest_e_basic_user_id foreign key (user_id) references migtest_e_user (id);
|
||||
alter table migtest_e_basic modify user_id null;
|
||||
alter table migtest_e_basic add column new_string_field varchar2(255) default 'foo''bar' not null;
|
||||
alter table migtest_e_basic add column new_boolean_field number(1) default 1 not null;
|
||||
alter table migtest_e_basic add new_string_field varchar2(255) default 'foo''bar' not null;
|
||||
alter table migtest_e_basic add new_boolean_field number(1) default 1 not null;
|
||||
update migtest_e_basic set new_boolean_field = old_boolean;
|
||||
|
||||
alter table migtest_e_basic add column new_boolean_field2 number(1) default 1 not null;
|
||||
alter table migtest_e_basic add column progress number(10) default 0 not null;
|
||||
alter table migtest_e_basic add new_boolean_field2 number(1) default 1 not null;
|
||||
alter table migtest_e_basic add progress number(10) default 0 not null;
|
||||
alter table migtest_e_basic add constraint ck_migtest_e_basic_progress check ( progress in (0,1,2));
|
||||
alter table migtest_e_basic add column new_integer number(10) default 42 not null;
|
||||
alter table migtest_e_basic add new_integer number(10) default 42 not null;
|
||||
|
||||
alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest2;
|
||||
alter table migtest_e_basic drop constraint uq_migtest_e_basic_indextest6;
|
||||
@@ -70,12 +70,12 @@ comment on table migtest_e_history is 'We have history now';
|
||||
update migtest_e_history2 set test_string = 'unknown' where test_string is null;
|
||||
alter table migtest_e_history2 modify test_string default 'unknown';
|
||||
alter table migtest_e_history2 modify test_string not null;
|
||||
alter table migtest_e_history2 add column test_string2 varchar2(255);
|
||||
alter table migtest_e_history2 add column test_string3 varchar2(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add column new_column varchar2(20);
|
||||
alter table migtest_e_history2 add test_string2 varchar2(255);
|
||||
alter table migtest_e_history2 add test_string3 varchar2(255) default 'unknown' not null;
|
||||
alter table migtest_e_history2 add new_column varchar2(20);
|
||||
|
||||
alter table migtest_e_history4 modify test_number number(19);
|
||||
alter table migtest_e_history5 add column test_boolean number(1) default 0 not null;
|
||||
alter table migtest_e_history5 add test_boolean number(1) default 0 not null;
|
||||
|
||||
|
||||
-- NOTE: table has @History - special migration may be necessary
|
||||
@@ -83,9 +83,9 @@ update migtest_e_history6 set test_number1 = 42 where test_number1 is null;
|
||||
alter table migtest_e_history6 modify test_number1 default 42;
|
||||
alter table migtest_e_history6 modify test_number1 not null;
|
||||
alter table migtest_e_history6 modify test_number2 null;
|
||||
alter table migtest_e_softdelete add column deleted number(1) default 0 not null;
|
||||
alter table migtest_e_softdelete add deleted number(1) default 0 not null;
|
||||
|
||||
alter table migtest_oto_child add column master_id number(19);
|
||||
alter table migtest_oto_child add master_id number(19);
|
||||
|
||||
create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3);
|
||||
create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6);
|
||||
|
||||
@@ -31,9 +31,9 @@ update migtest_e_basic set user_id = 23 where user_id is null;
|
||||
alter table migtest_e_basic drop constraint fk_migtest_e_basic_user_id;
|
||||
alter table migtest_e_basic modify user_id default 23;
|
||||
alter table migtest_e_basic modify user_id not null;
|
||||
alter table migtest_e_basic add column old_boolean number(1) default 0 not null;
|
||||
alter table migtest_e_basic add column old_boolean2 number(1);
|
||||
alter table migtest_e_basic add column eref_id number(10);
|
||||
alter table migtest_e_basic add old_boolean number(1) default 0 not null;
|
||||
alter table migtest_e_basic add old_boolean2 number(1);
|
||||
alter table migtest_e_basic add eref_id number(10);
|
||||
|
||||
alter table migtest_e_basic drop constraint uq_mgtst__bsc_stts_ndxtst1;
|
||||
alter table migtest_e_basic drop constraint uq_migtest_e_basic_name;
|
||||
@@ -47,8 +47,8 @@ comment on column migtest_e_history.test_string is '';
|
||||
comment on table migtest_e_history is '';
|
||||
alter table migtest_e_history2 modify test_string drop default;
|
||||
alter table migtest_e_history2 modify test_string null;
|
||||
alter table migtest_e_history2 add column obsolete_string1 varchar2(255);
|
||||
alter table migtest_e_history2 add column obsolete_string2 varchar2(255);
|
||||
alter table migtest_e_history2 add obsolete_string1 varchar2(255);
|
||||
alter table migtest_e_history2 add obsolete_string2 varchar2(255);
|
||||
|
||||
alter table migtest_e_history4 modify test_number number(10);
|
||||
alter table migtest_e_history6 modify test_number1 drop default;
|
||||
|
||||
+4
-4
@@ -161,11 +161,11 @@ create table migtest_oto_master (
|
||||
constraint pk_migtest_oto_master primary key (id)
|
||||
);
|
||||
|
||||
create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1);
|
||||
create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5);
|
||||
create index if not exists ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1);
|
||||
create index if not exists ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5);
|
||||
create index idxd_migtest_0 on migtest_oto_child using hash (upper(name)) where upper(name) = 'JIM';
|
||||
create index concurrently ix_migtest_oto_child_lowername_id on migtest_oto_child (lower(name),id);
|
||||
create index ix_migtest_oto_child_lowername on migtest_oto_child (lower(name));
|
||||
create index concurrently if not exists ix_migtest_oto_child_lowername_id on migtest_oto_child (lower(name),id);
|
||||
create index if not exists ix_migtest_oto_child_lowername on migtest_oto_child (lower(name));
|
||||
create index ix_migtest_fk_cascade_one_id on migtest_fk_cascade (one_id);
|
||||
alter table migtest_fk_cascade add constraint fk_migtest_fk_cascade_one_id foreign key (one_id) references migtest_fk_cascade_one (id) on delete cascade on update restrict;
|
||||
|
||||
|
||||
@@ -100,9 +100,9 @@ alter table migtest_e_softdelete add column deleted boolean default false not nu
|
||||
|
||||
alter table migtest_oto_child add column master_id bigint;
|
||||
|
||||
create index ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3);
|
||||
create index ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6);
|
||||
create index ix_migtest_oto_child_name on migtest_oto_child (name);
|
||||
create index if not exists ix_migtest_e_basic_indextest3 on migtest_e_basic (indextest3);
|
||||
create index if not exists ix_migtest_e_basic_indextest6 on migtest_e_basic (indextest6);
|
||||
create index if not exists ix_migtest_oto_child_name on migtest_oto_child (name);
|
||||
drop index if exists ix_migtest_e_basic_indextest1;
|
||||
drop index if exists ix_migtest_e_basic_indextest5;
|
||||
drop index if exists idxd_migtest_0;
|
||||
|
||||
@@ -66,11 +66,11 @@ alter table migtest_e_history6 alter column test_number1 drop not null;
|
||||
update migtest_e_history6 set test_number2 = 7 where test_number2 is null;
|
||||
alter table migtest_e_history6 alter column test_number2 set default 7;
|
||||
alter table migtest_e_history6 alter column test_number2 set not null;
|
||||
create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1);
|
||||
create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5);
|
||||
create index ix_m12_otoc71 on migtest_oto_child (name);
|
||||
create unique index uq_m12_otoc71 on migtest_oto_child (lower(name));
|
||||
create unique index ix_migtest_oto_master_lowername on migtest_oto_master (lower(name));
|
||||
create index if not exists ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1);
|
||||
create index if not exists ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5);
|
||||
create index if not exists ix_m12_otoc71 on migtest_oto_child (name);
|
||||
create unique index if not exists uq_m12_otoc71 on migtest_oto_child (lower(name));
|
||||
create unique index if not exists ix_migtest_oto_master_lowername on migtest_oto_master (lower(name));
|
||||
drop index if exists ix_migtest_e_basic_indextest3;
|
||||
drop index if exists ix_migtest_e_basic_indextest6;
|
||||
create index ix_migtest_e_basic_eref_id on migtest_e_basic (eref_id);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean external mapping api</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.8.0</tag>
|
||||
<tag>ebean-parent-12.8.1</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean external mapping xml</name>
|
||||
@@ -33,7 +33,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -59,14 +59,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean postgis</name>
|
||||
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean querybean</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -57,21 +57,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@ package io.ebean.typequery;
|
||||
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebeaninternal.api.SpiQueryFetch;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import io.ebeaninternal.server.querydefn.SpiFetchGroup;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -142,7 +145,34 @@ public abstract class TQAssocBean<T, R> extends TQProperty<R> {
|
||||
return _root;
|
||||
}
|
||||
|
||||
private final SpiQueryFetch spiQuery() {
|
||||
/**
|
||||
* Fetch using the nested FetchGroup.
|
||||
*/
|
||||
public R fetch(FetchGroup<T> nestedGroup) {
|
||||
return fetchNested(nestedGroup, FETCH_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch query using the nested FetchGroup.
|
||||
*/
|
||||
public R fetchQuery(FetchGroup<T> nestedGroup) {
|
||||
return fetchNested(nestedGroup, FETCH_QUERY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch cache using the nested FetchGroup.
|
||||
*/
|
||||
public R fetchCache(FetchGroup<T> nestedGroup) {
|
||||
return fetchNested(nestedGroup, FETCH_CACHE);
|
||||
}
|
||||
|
||||
private R fetchNested(FetchGroup<T> nestedGroup, FetchConfig fetchConfig) {
|
||||
OrmQueryDetail nestedDetail = ((SpiFetchGroup) nestedGroup).underlying();
|
||||
spiQuery().addNested(_name, nestedDetail, fetchConfig);
|
||||
return _root;
|
||||
}
|
||||
|
||||
private SpiQueryFetch spiQuery() {
|
||||
return (SpiQueryFetch)((TQRootBean) _root).query();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,13 @@ package org.querytest;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import org.example.domain.Customer;
|
||||
import org.example.domain.Order;
|
||||
import org.example.domain.otherpackage.PhoneNumber;
|
||||
import org.example.domain.query.QCustomer;
|
||||
import org.example.domain.query.QOrder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
@@ -18,6 +22,26 @@ public class QOrderTest {
|
||||
|
||||
private static final QOrder or = QOrder.alias();
|
||||
|
||||
private static final FetchGroup<Customer> fgC = QCustomer.forFetchGroup()
|
||||
.select(cu.name, cu.phoneNumber)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static final FetchGroup<Order> fgNested1 = QOrder.forFetchGroup()
|
||||
.select(or.status, or.shipDate)
|
||||
.customer.fetch(fgC)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static final FetchGroup<Order> fgNested_fetchQuery = QOrder.forFetchGroup()
|
||||
.select(or.status)
|
||||
.customer.fetchQuery(fgC)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static final FetchGroup<Order> fgNested_fetchCache = QOrder.forFetchGroup()
|
||||
.select(or.status)
|
||||
.customer.fetchCache(fgC)
|
||||
.buildFetchGroup();
|
||||
|
||||
|
||||
private static final FetchGroup<Order> fg = QOrder.forFetchGroup()
|
||||
.select(or.status, or.shipDate)
|
||||
.customer.fetchCache(cu.name, cu.status, cu.registered, cu.comments)
|
||||
@@ -28,6 +52,20 @@ public class QOrderTest {
|
||||
.customer.fetch(cu.name)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static Order order;
|
||||
private static Customer customer;
|
||||
|
||||
@BeforeClass
|
||||
public static void before() {
|
||||
setupData();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
DB.delete(order);
|
||||
DB.delete(customer);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetchCache() {
|
||||
|
||||
@@ -76,6 +114,69 @@ public class QOrderTest {
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t1.id, t1.name from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
|
||||
new QOrder()
|
||||
.status.eq(Order.Status.NEW)
|
||||
.select(fgNested1)
|
||||
.findList();
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.ship_date, t1.id, t1.name, t1.phone_number from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested_fetchQuery() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
|
||||
final Order found = new QOrder()
|
||||
.id.eq(order.getId())
|
||||
.select(fgNested_fetchQuery)
|
||||
.findOne();
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
|
||||
// assert fetching customer via fetchQuery
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.name, t0.phone_number from be_customer t0 where t0.id = ?");
|
||||
|
||||
assertThat(found.getCustomer().getPhoneNumber().getMsisdn()).isEqualTo("Ph1");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested_fetchCache() {
|
||||
|
||||
DB.getDefault();
|
||||
|
||||
// ensure the customer is loaded in the L2 cache
|
||||
new QCustomer().id.eq(customer.getId()).findOne();
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
final Order found = new QOrder()
|
||||
.id.eq(order.getId())
|
||||
.select(fgNested_fetchCache) // cache hit for customer
|
||||
.findOne();
|
||||
|
||||
final String msisdn = found.getCustomer().getPhoneNumber().getMsisdn();
|
||||
assertThat(msisdn).isEqualTo("Ph1");
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
|
||||
// assert we only hit DB for order
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_partial() {
|
||||
|
||||
@@ -113,4 +214,15 @@ public class QOrderTest {
|
||||
|
||||
}
|
||||
|
||||
private static void setupData() {
|
||||
|
||||
customer = new Customer();
|
||||
customer.setName("Fred");
|
||||
customer.setPhoneNumber(new PhoneNumber("Ph1"));
|
||||
customer.save();
|
||||
|
||||
order = new Order();
|
||||
order.setCustomer(customer);
|
||||
order.save();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
@@ -22,35 +22,35 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean test</name>
|
||||
@@ -29,14 +29,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean composite</name>
|
||||
@@ -22,20 +22,20 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>kotlin querybean generator</name>
|
||||
@@ -12,7 +12,7 @@
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
|
||||
<properties>
|
||||
<kotlin.version>1.4.21</kotlin.version>
|
||||
<kotlin.version>1.4.31</kotlin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -81,46 +81,47 @@
|
||||
<build>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-kapt</id>
|
||||
<goals>
|
||||
<goal>test-kapt</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sourceDirs>
|
||||
<sourceDir>src/test/kotlin</sourceDir>
|
||||
</sourceDirs>
|
||||
<!-- <annotationProcessorPaths>-->
|
||||
<!-- <annotationProcessorPath>-->
|
||||
<!-- <groupId>io.ebean</groupId>-->
|
||||
<!-- <artifactId>kotlin-querybean-generator</artifactId>-->
|
||||
<!--<!– <version>12.7.1</version>–>-->
|
||||
<!-- <version>12.8.0-SNAPSHOT</version>-->
|
||||
<!-- </annotationProcessorPath>-->
|
||||
<!-- </annotationProcessorPaths>-->
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<jvmTarget>1.8</jvmTarget>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.jetbrains.kotlin</groupId>-->
|
||||
<!-- <artifactId>kotlin-maven-plugin</artifactId>-->
|
||||
<!-- <version>${kotlin.version}</version>-->
|
||||
<!-- <executions>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>test-compile</id>-->
|
||||
<!-- <phase>test-compile</phase>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>test-compile</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- </execution>-->
|
||||
<!-- <execution>-->
|
||||
<!-- <id>test-kapt</id>-->
|
||||
<!-- <goals>-->
|
||||
<!-- <goal>test-kapt</goal>-->
|
||||
<!-- </goals>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <sourceDirs>-->
|
||||
<!-- <sourceDir>src/test/kotlin</sourceDir>-->
|
||||
<!-- </sourceDirs>-->
|
||||
<!--<!– <annotationProcessorPaths>–>-->
|
||||
<!--<!– <annotationProcessorPath>–>-->
|
||||
<!--<!– <groupId>io.ebean</groupId>–>-->
|
||||
<!--<!– <artifactId>kotlin-querybean-generator</artifactId>–>-->
|
||||
<!--<!–<!– <version>12.7.1</version>–>–>-->
|
||||
<!--<!– <version>12.8.0-SNAPSHOT</version>–>-->
|
||||
<!--<!– </annotationProcessorPath>–>-->
|
||||
<!--<!– </annotationProcessorPaths>–>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </execution>-->
|
||||
<!-- </executions>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <jvmTarget>1.8</jvmTarget>-->
|
||||
<!--<!– <args></args>–>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<version>3.8.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-testCompile</id>
|
||||
@@ -145,7 +146,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.6.6</version>
|
||||
<version>12.8.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<parent>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>java8-oss</artifactId>
|
||||
<version>2.3</version>
|
||||
<version>3.1</version>
|
||||
</parent>
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>ebean parent</name>
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.8.0</tag>
|
||||
<tag>ebean-parent-12.8.1</tag>
|
||||
</scm>
|
||||
|
||||
<licenses>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.8.0</version>
|
||||
<version>12.8.1</version>
|
||||
</parent>
|
||||
|
||||
<name>querybean generator</name>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>java8-oss</artifactId>
|
||||
<version>2.3</version>
|
||||
</parent>
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>tests</artifactId>
|
||||
<version>1.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>tests</name>
|
||||
<description>test modules</description>
|
||||
|
||||
<modules>
|
||||
<module>test-java16</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
<!-- <artifactId>java11-oss</artifactId>-->
|
||||
<!-- <version>2.3</version>-->
|
||||
<!-- </parent>-->
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>test-java16</artifactId>
|
||||
<version>1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.8.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.8.1-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>5.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<release>16</release>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.8.1-SNAPSHOT</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.example.records;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public record Address (String line1, String line2, String city) {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.Model;
|
||||
import io.ebean.annotation.Identity;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Identity(start = 1000, cache = 100)
|
||||
@MappedSuperclass
|
||||
public class BaseModel extends Model {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class Contact extends Model {
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@Version
|
||||
private long version;
|
||||
|
||||
private final String name;
|
||||
|
||||
@Embedded(prefix = "home_")
|
||||
private Address homeAddress;
|
||||
|
||||
@Embedded(prefix = "work_")
|
||||
private Address workAddress;
|
||||
|
||||
public Contact(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Address getHomeAddress() {
|
||||
return homeAddress;
|
||||
}
|
||||
|
||||
public void setHomeAddress(Address homeAddress) {
|
||||
this.homeAddress = homeAddress;
|
||||
}
|
||||
|
||||
public Address getWorkAddress() {
|
||||
return workAddress;
|
||||
}
|
||||
|
||||
public void setWorkAddress(Address workAddress) {
|
||||
this.workAddress = workAddress;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.annotation.Length;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "course")
|
||||
public class Course extends BaseModel {
|
||||
|
||||
@Length(200)
|
||||
final String name;
|
||||
|
||||
@Length(400)
|
||||
String summary;
|
||||
|
||||
public Course(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSummary() {
|
||||
return summary;
|
||||
}
|
||||
|
||||
public void setSummary(String summary) {
|
||||
this.summary = summary;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.annotation.Identity;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Identity(start = 1000)
|
||||
@Entity
|
||||
@Table(name="course_rec")
|
||||
public record CourseRecordEntity(@Id long id, String name, String notes) {
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class UserRole extends Model {
|
||||
|
||||
@EmbeddedId
|
||||
final UserRoleId id;
|
||||
|
||||
String note;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public UserRole(UserRoleId id, String note) {
|
||||
this.id = id;
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public UserRoleId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.example.records;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
@Embeddable
|
||||
public record UserRoleId(Integer userId, String roleId) {
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.UUID;
|
||||
|
||||
@IdClass(UserSiteId.class)
|
||||
@Entity
|
||||
public class UserSite extends Model {
|
||||
|
||||
@Id
|
||||
final UUID userId;
|
||||
|
||||
@Id
|
||||
final UUID siteId;
|
||||
|
||||
String note;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public UserSite(UUID userId, UUID siteId) {
|
||||
this.userId = userId;
|
||||
this.siteId = siteId;
|
||||
}
|
||||
|
||||
public UUID getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public UUID getSiteId() {
|
||||
return siteId;
|
||||
}
|
||||
|
||||
public void setNote(String note) {
|
||||
this.note = note;
|
||||
}
|
||||
|
||||
public void setVersion(long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
public long getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.example.records;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import java.util.UUID;
|
||||
|
||||
@Embeddable
|
||||
public record UserSiteId(UUID userId, UUID siteId) {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.DB;
|
||||
import org.example.records.query.QCourseRecordEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CourseRecordEntityTest {
|
||||
|
||||
@Test
|
||||
void record_insert_withGivenIdValue() {
|
||||
var course = new CourseRecordEntity(42, "SuppliedId", "Record");
|
||||
DB.save(course);
|
||||
assertThat(course.id()).isEqualTo(42);
|
||||
|
||||
var found = new QCourseRecordEntity()
|
||||
.name.startsWith("SuppliedId")
|
||||
.findOneOrEmpty();
|
||||
|
||||
assertThat(found).isPresent();
|
||||
assertThat(found.get().id()).isEqualTo(42L);
|
||||
assertThat(found.get().notes()).isEqualTo("Record");
|
||||
}
|
||||
|
||||
@Test
|
||||
void record_insert_usingGeneratedId() {
|
||||
var course2 = new CourseRecordEntity(0, "Second", "Record with generated id");
|
||||
DB.save(course2);
|
||||
// as using @Identity(start = 1000)
|
||||
assertThat(course2.id()).isEqualTo(1000);
|
||||
|
||||
var second = new QCourseRecordEntity()
|
||||
.name.startsWith("Second")
|
||||
.findOneOrEmpty();
|
||||
|
||||
assertThat(second).isPresent();
|
||||
assertThat(second.get().notes()).isEqualTo("Record with generated id");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.example.records;
|
||||
|
||||
import io.ebean.DB;
|
||||
import org.example.records.query.QCourse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.example.records.query.QCourse.Alias.id;
|
||||
import static org.example.records.query.QCourse.Alias.name;
|
||||
|
||||
class DtoQueryUsingRecordsTest {
|
||||
|
||||
@Test
|
||||
void dtoQuery_projectRecords() {
|
||||
|
||||
var course = new Course("Calculus");
|
||||
course.setSummary("Something here");
|
||||
course.save();
|
||||
|
||||
performOrmQuery();
|
||||
|
||||
records_via_SqlDtoQuery(course);
|
||||
records_via_OrmQueryToDtoQuery(course);
|
||||
|
||||
course.delete();
|
||||
}
|
||||
|
||||
private void performOrmQuery() {
|
||||
List<Course> courses = new QCourse()
|
||||
.name.startsWith("Calc")
|
||||
.findList();
|
||||
|
||||
assertThat(courses).hasSize(1);
|
||||
}
|
||||
|
||||
private void records_via_SqlDtoQuery(Course course) {
|
||||
List<Foo> records = DB.findDto(Foo.class, "select id, name from course where name like ?")
|
||||
.setParameter("Calc%")
|
||||
.findList();
|
||||
|
||||
assertThat(records).hasSize(1);
|
||||
assertThat(records.get(0).name()).isEqualTo(course.getName());
|
||||
}
|
||||
|
||||
private void records_via_OrmQueryToDtoQuery(Course course) {
|
||||
List<Foo> records2 = new QCourse()
|
||||
.select(id, name )
|
||||
.name.startsWith("Calc")
|
||||
.asDto(Foo.class)
|
||||
.findList();
|
||||
|
||||
assertThat(records2).hasSize(1);
|
||||
assertThat(records2.get(0).name()).isEqualTo(course.getName());
|
||||
}
|
||||
|
||||
public record Foo(long id, String name){}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.example.records;
|
||||
|
||||
import org.example.records.query.QContact;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.example.records.query.QContact.Alias.homeAddress;
|
||||
import static org.example.records.query.QContact.Alias.name;
|
||||
|
||||
public class RecordAsEmbeddedTest {
|
||||
|
||||
@Test
|
||||
void insert_query() {
|
||||
|
||||
var contact = new Contact("Rob");
|
||||
contact.setWorkAddress(new Address("45 work", "workling", "wo"));
|
||||
contact.setHomeAddress(new Address("94 home st", "homeline", "wo"));
|
||||
|
||||
contact.save();
|
||||
|
||||
Contact found = new QContact()
|
||||
.id.eq(contact.getId())
|
||||
.findOne();
|
||||
|
||||
assertThat(found.getWorkAddress().toString()).isEqualTo("Address[line1=45 work, line2=workling, city=wo]");
|
||||
assertThat(found.getHomeAddress().toString()).isEqualTo("Address[line1=94 home st, line2=homeline, city=wo]");
|
||||
|
||||
Contact foundPartial = new QContact()
|
||||
.select(name, homeAddress)
|
||||
.id.eq(contact.getId())
|
||||
.findOne();
|
||||
|
||||
// invoke lazy loading on getWorkAddress
|
||||
assertThat(foundPartial.getWorkAddress().toString()).isEqualTo("Address[line1=45 work, line2=workling, city=wo]");
|
||||
assertThat(foundPartial.getHomeAddress().toString()).isEqualTo("Address[line1=94 home st, line2=homeline, city=wo]");
|
||||
|
||||
Contact foundNoLazyLoading = new QContact()
|
||||
.select(name, homeAddress)
|
||||
.setDisableLazyLoading(true)
|
||||
.id.eq(contact.getId())
|
||||
.findOne();
|
||||
|
||||
// no lazy loading on getWorkAddress this time
|
||||
assertThat(foundNoLazyLoading.getWorkAddress()).isNull();
|
||||
assertThat(foundNoLazyLoading.getHomeAddress().toString()).isEqualTo("Address[line1=94 home st, line2=homeline, city=wo]");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.example.records;
|
||||
|
||||
import org.example.records.query.QUserSite;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class RecordIdClassTest {
|
||||
|
||||
@Test
|
||||
void insert_query() {
|
||||
|
||||
UUID userId = UUID.randomUUID();
|
||||
UUID siteId = UUID.randomUUID();
|
||||
|
||||
var userSite = new UserSite(userId, siteId);
|
||||
userSite.setNote("HelloIdClass");
|
||||
userSite.save();
|
||||
|
||||
var id = new UserSiteId(userId, siteId);
|
||||
|
||||
UserSite found = new QUserSite()
|
||||
.setId(id)
|
||||
.findOne();
|
||||
|
||||
assertThat(found.getUserId()).isEqualTo(userId);
|
||||
assertThat(found.getSiteId()).isEqualTo(siteId);
|
||||
assertThat(found.getNote()).isEqualTo("HelloIdClass");
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.example.records;
|
||||
|
||||
import org.example.records.query.QUserRole;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class UserRoleTest {
|
||||
|
||||
final UserRoleId id = new UserRoleId(42, "R7");
|
||||
|
||||
@Test
|
||||
void id_equals() {
|
||||
assertThat(id).isEqualTo(new UserRoleId(42, "R7"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void id_notEquals() {
|
||||
assertThat(id).isNotEqualTo(new UserRoleId(43, "R7"));
|
||||
assertThat(id).isNotEqualTo(new UserRoleId(42, "R8"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void insert_query() {
|
||||
|
||||
var userRole = new UserRole(id, "hello");
|
||||
userRole.save();
|
||||
|
||||
UserRole found = new QUserRole()
|
||||
.id.eq(new UserRoleId(42, "R7"))
|
||||
.findOne();
|
||||
|
||||
UserRoleId id1 = found.getId();
|
||||
assertThat(id1).isEqualTo(id);
|
||||
assertThat(id1.userId()).isEqualTo(42);
|
||||
assertThat(id1.roleId()).isEqualTo("R7");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
ebean:
|
||||
test:
|
||||
platform: h2
|
||||
ddlMode: dropCreate
|
||||
dbName: foo
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<configuration scan="true" scanPeriod="10 seconds">
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT"/>
|
||||
</root>
|
||||
|
||||
<logger name="org.avaje" level="TRACE"/>
|
||||
<logger name="io.ebean" level="INFO"/>
|
||||
|
||||
<logger name="io.ebean.docker" level="TRACE"/>
|
||||
<logger name="io.ebean.DDL" level="DEBUG"/>
|
||||
|
||||
<logger name="io.ebean.SQL" level="TRACE"/>
|
||||
<logger name="io.ebean.TXN" level="TRACE"/>
|
||||
<logger name="io.ebean.SUM" level="TRACE"/>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user