mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
130
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae68d41519 | ||
|
|
722692d934 | ||
|
|
21a3f322e1 | ||
|
|
0d175557b0 | ||
|
|
57ccd19fe6 | ||
|
|
9674711516 | ||
|
|
9155716752 | ||
|
|
d7d8c3e651 | ||
|
|
16f6f2ee7f | ||
|
|
fea6dfd62b | ||
|
|
464ed4322e | ||
|
|
c3f556f0dc | ||
|
|
ba6810891e | ||
|
|
c530883e5e | ||
|
|
06542b031e | ||
|
|
4b5365e708 | ||
|
|
1d471fee92 | ||
|
|
3825dea00a | ||
|
|
3fd130ac4c | ||
|
|
196645e7a2 | ||
|
|
f5459920e9 | ||
|
|
ee6452cfb0 | ||
|
|
ad7e18561b | ||
|
|
c640524bfc | ||
|
|
fea840c859 | ||
|
|
bb7df71391 | ||
|
|
cb6f0335b1 | ||
|
|
762899ef10 | ||
|
|
848d4f031e | ||
|
|
481f828507 | ||
|
|
b3d0c21a80 | ||
|
|
a115cdf095 | ||
|
|
410e9d475b | ||
|
|
462385c7d0 | ||
|
|
3655e2c6f8 | ||
|
|
318f6ae3f5 | ||
|
|
c63acad7e0 | ||
|
|
6dba4a3d28 | ||
|
|
ecf1e53616 | ||
|
|
0ff9a00427 | ||
|
|
725ff8dc58 | ||
|
|
a780dc133e | ||
|
|
b111fcfecc | ||
|
|
114693b7cd | ||
|
|
5a39dcb39c | ||
|
|
b04f887bc3 | ||
|
|
5c38561049 | ||
|
|
f40eb011c3 | ||
|
|
a08cf548e7 | ||
|
|
f12f0d7f7a | ||
|
|
0c53efcbbc | ||
|
|
1aeed8ad12 | ||
|
|
bcb136b692 | ||
|
|
8b670fd615 | ||
|
|
970bc8e973 | ||
|
|
007b06e9db | ||
|
|
4513dbf29d | ||
|
|
53bcc62a0c | ||
|
|
858c55c978 | ||
|
|
cedba089e1 | ||
|
|
cbf7811f7c | ||
|
|
ea13b322ca | ||
|
|
486a8cf1c0 | ||
|
|
bfe46432da | ||
|
|
272eae5f22 | ||
|
|
502104eba8 | ||
|
|
fa45c79bd2 | ||
|
|
ee4d1bf866 | ||
|
|
dcf7b60d37 | ||
|
|
0663a97941 | ||
|
|
f31ab4d6a8 | ||
|
|
f77388738b | ||
|
|
945175c533 | ||
|
|
7d37c6cfd8 | ||
|
|
496672b394 | ||
|
|
1ffe359573 | ||
|
|
23cd9b6a93 | ||
|
|
333ac8edd9 | ||
|
|
081cb20260 | ||
|
|
53f1da32be | ||
|
|
5544a2cc3e | ||
|
|
84c3008db1 | ||
|
|
d949d4d6a2 | ||
|
|
03669dc307 | ||
|
|
2a8fad7364 | ||
|
|
e62db11f01 | ||
|
|
8c8f2b95da | ||
|
|
576eb01187 | ||
|
|
8b18b2a20e | ||
|
|
f5c12a916d | ||
|
|
2f8a99c304 | ||
|
|
cd9a43c3ab | ||
|
|
f251ca5431 | ||
|
|
2c44c80f65 | ||
|
|
d9efeac0a1 | ||
|
|
f4a7d0b6ad | ||
|
|
bc5db1e46a | ||
|
|
8743148238 | ||
|
|
68db6723d0 | ||
|
|
9b1fa43792 | ||
|
|
5f2454831e | ||
|
|
140178bb47 | ||
|
|
f95b4b5c4b | ||
|
|
d3b3a79342 | ||
|
|
52398317bc | ||
|
|
7f2e4f54ff | ||
|
|
9f19ed5376 | ||
|
|
d49a7c415f | ||
|
|
8ffc9ede85 | ||
|
|
eba521563a | ||
|
|
ed71e106df | ||
|
|
050ae49f6b | ||
|
|
d5d9a897ae | ||
|
|
ddf200ffdd | ||
|
|
7fa5e2aa8c | ||
|
|
8bfae9deef | ||
|
|
e6c9f151c1 | ||
|
|
30a0935300 | ||
|
|
b4182d4519 | ||
|
|
93cc0399f1 | ||
|
|
5404dab5a3 | ||
|
|
d70da1d805 | ||
|
|
2225d5b7e8 | ||
|
|
270369bd65 | ||
|
|
a932d61a94 | ||
|
|
24b08663af | ||
|
|
bb6c9c84ba | ||
|
|
a1e185b0f6 | ||
|
|
e2a467ca5a | ||
|
|
4b28933298 |
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
custom: https://ebean.io/sponsors
|
||||
@@ -21,7 +21,7 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://timerbe.de" target="_blank">
|
||||
<a href="https://timerbee.de" target="_blank">
|
||||
<img width="222px" src="https://ebean.io/images/logo-timerbee.png">
|
||||
</a>
|
||||
</td>
|
||||
|
||||
@@ -9,20 +9,21 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.39.3</version>
|
||||
<version>11.43.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
<url>http://ebean-orm.github.io/</url>
|
||||
|
||||
<properties>
|
||||
<jackson-core.version>2.9.8</jackson-core.version>
|
||||
<jackson-core.version>2.9.9</jackson-core.version>
|
||||
<jackson-databind.version>2.9.9.2</jackson-databind.version>
|
||||
<snakeyaml.version>1.21</snakeyaml.version>
|
||||
</properties>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.39.3</tag>
|
||||
<tag>ebean-11.43.2</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -117,7 +118,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>4.10</version>
|
||||
<version>4.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -129,7 +130,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>4.5.2</version>
|
||||
<version>4.6.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -141,7 +142,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>11.16.2</version>
|
||||
<version>11.20.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -161,7 +162,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-core.version}</version>
|
||||
<version>${jackson-databind.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -219,6 +220,13 @@
|
||||
|
||||
<!-- Test scope -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.nuodb.jdbc</groupId>
|
||||
<artifactId>nuodb-jdbc</artifactId>
|
||||
<version>20.2.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>oracle</groupId>-->
|
||||
<!--<artifactId>oracle-jdbc</artifactId>-->
|
||||
@@ -229,7 +237,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean.test</groupId>
|
||||
<artifactId>ebean-test-docker</artifactId>
|
||||
<version>2.5.1</version>
|
||||
<version>2.10.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -240,20 +248,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-agentloader</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-agent</artifactId>
|
||||
<version>11.39.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
|
||||
and not require a separate module for it -->
|
||||
<dependency>
|
||||
@@ -287,8 +281,7 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<!-- Do not upgrade to 6.0.6: https://bugs.mysql.com/bug.php?id=82896 -->
|
||||
<version>5.1.43</version>
|
||||
<version>8.0.17</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -299,6 +292,13 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>avaje-composite-testing</artifactId>
|
||||
@@ -330,7 +330,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>11.39.1</version>
|
||||
<version>11.43.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
@@ -393,7 +393,7 @@
|
||||
<overview>src/main/java/io/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform*</excludePackageNames>
|
||||
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform</excludePackageNames>
|
||||
<docletArtifact>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>pygments-doclet</artifactId>
|
||||
|
||||
@@ -69,8 +69,8 @@ public enum CacheMode {
|
||||
*/
|
||||
GET(true, false);
|
||||
|
||||
private boolean get;
|
||||
private boolean put;
|
||||
private final boolean get;
|
||||
private final boolean put;
|
||||
|
||||
CacheMode(boolean get, boolean put) {
|
||||
this.get = get;
|
||||
|
||||
@@ -1237,4 +1237,18 @@ public class DB {
|
||||
return getDefault().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the base tables for the given bean types.
|
||||
*/
|
||||
public static void truncate(Class<?>... types) {
|
||||
getDefault().truncate(types);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate the given tables.
|
||||
*/
|
||||
public static void truncate(String... tables) {
|
||||
getDefault().truncate(tables);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1580,4 +1580,15 @@ public interface Database {
|
||||
* </p>
|
||||
*/
|
||||
<T> Set<String> validateQuery(Query<T> query);
|
||||
|
||||
/**
|
||||
* Truncate all the given tables.
|
||||
*/
|
||||
void truncate(String... tables);
|
||||
|
||||
/**
|
||||
* Truncate the base tables for the given bean types.
|
||||
*/
|
||||
void truncate(Class<?>... tables);
|
||||
|
||||
}
|
||||
|
||||
@@ -536,4 +536,12 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
<T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent);
|
||||
|
||||
/**
|
||||
* Add the expressions to the given expression list.
|
||||
*
|
||||
* @param where The expression list to add the expressions to
|
||||
* @param expressions The expressions that are parsed
|
||||
* @param params Bind parameters to match ? or ?1 bind positions.
|
||||
*/
|
||||
<T> void where(ExpressionList<T> where, String expressions, Object[] params);
|
||||
}
|
||||
|
||||
@@ -489,7 +489,26 @@ public interface ExpressionList<T> {
|
||||
* Add some filter predicate expressions to the many property.
|
||||
*/
|
||||
@Nonnull
|
||||
ExpressionList<T> filterMany(String prop);
|
||||
ExpressionList<T> filterMany(String manyProperty);
|
||||
|
||||
/**
|
||||
* Add filter expressions to the many property.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* DB.find(Customer.class)
|
||||
* .where()
|
||||
* .eq("name", "Rob")
|
||||
* .filterMany("orders", "status = ?", Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param manyProperty The many property
|
||||
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
|
||||
* @param params Bind parameters used in the expressions
|
||||
*/
|
||||
Query<T> filterMany(String manyProperty, String expressions, Object... params);
|
||||
|
||||
/**
|
||||
* Specify specific properties to fetch on the main/root bean (aka partial
|
||||
@@ -663,6 +682,14 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> where();
|
||||
|
||||
/**
|
||||
* Add the expressions to this expression list.
|
||||
*
|
||||
* @param expressions The expressions that are parsed and added to this expression list
|
||||
* @param params Bind parameters to match ? or ?1 bind positions.
|
||||
*/
|
||||
ExpressionList<T> where(String expressions, Object... params);
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
* <pre>{@code
|
||||
@@ -831,9 +858,9 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
ExpressionList<T> between(String propertyName, Object value1, Object value2);
|
||||
|
||||
/**
|
||||
@@ -1327,7 +1354,7 @@ public interface ExpressionList<T> {
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Note that we need to cast the Postgres array for UUID types like:
|
||||
* Note that we need to cast the Postgres array for UUID types like:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -1335,7 +1362,7 @@ public interface ExpressionList<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param raw The raw expression that is typically a subquery
|
||||
* @param raw The raw expression that is typically a subquery
|
||||
* @param values The values which is typically a list or set of id values.
|
||||
*/
|
||||
ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
|
||||
|
||||
@@ -148,6 +148,8 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
private boolean queryAll;
|
||||
|
||||
private boolean cache;
|
||||
|
||||
/**
|
||||
* Construct the fetch configuration object.
|
||||
*/
|
||||
@@ -188,6 +190,17 @@ public class FetchConfig implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly fetch the beans fetching the beans from the L2 bean cache
|
||||
* and using the DB for beans not in the cache.
|
||||
*/
|
||||
public FetchConfig cache() {
|
||||
this.cache = true;
|
||||
this.queryBatchSize = 0;
|
||||
this.queryAll = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly fetch the beans in this path as a separate query (rather than as
|
||||
* part of the main query).
|
||||
@@ -247,6 +260,13 @@ public class FetchConfig implements Serializable {
|
||||
return queryAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this uses L2 bean cache.
|
||||
*/
|
||||
public boolean isCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
@@ -255,6 +275,7 @@ public class FetchConfig implements Serializable {
|
||||
FetchConfig that = (FetchConfig) o;
|
||||
if (lazyBatchSize != that.lazyBatchSize) return false;
|
||||
if (queryBatchSize != that.queryBatchSize) return false;
|
||||
if (cache != that.cache) return false;
|
||||
return queryAll == that.queryAll;
|
||||
}
|
||||
|
||||
@@ -263,6 +284,7 @@ public class FetchConfig implements Serializable {
|
||||
int result = lazyBatchSize;
|
||||
result = 92821 * result + queryBatchSize;
|
||||
result = 92821 * result + (queryAll ? 1 : 0);
|
||||
result = 92821 * result + (cache ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.service.SpiFetchGroupQuery;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
@@ -111,4 +113,11 @@ public interface FetchGroup<T> {
|
||||
return XServiceProvider.fetchGroupOf(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a query to be used by query beans for constructing FetchGroup.
|
||||
*/
|
||||
static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
|
||||
return XServiceProvider.fetchGroupQueryFor(beanType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,12 +67,26 @@ public interface FetchGroupBuilder<T> {
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path including all its properties using L2 cache.
|
||||
* Cache misses fallback to fetchQuery().
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchCache(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path including specified properties using a query join.
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchQuery(String path, String properties);
|
||||
|
||||
/**
|
||||
* Fetch the path including specified properties using L2 cache.
|
||||
* Cache misses fallback to fetchQuery().
|
||||
*/
|
||||
@Nonnull
|
||||
FetchGroupBuilder<T> fetchCache(String path, String properties);
|
||||
|
||||
/**
|
||||
* Fetch the path including all its properties lazily.
|
||||
*/
|
||||
|
||||
@@ -80,7 +80,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Add a property with ascending order to this OrderBy.
|
||||
*/
|
||||
public Query<T> asc(String propertyName, String collation) {
|
||||
|
||||
list.add(new Property(propertyName, true, collation));
|
||||
return query;
|
||||
}
|
||||
@@ -89,7 +88,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Add a property with descending order to this OrderBy.
|
||||
*/
|
||||
public Query<T> desc(String propertyName) {
|
||||
|
||||
list.add(new Property(propertyName, false));
|
||||
return query;
|
||||
}
|
||||
@@ -98,7 +96,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Add a property with descending order to this OrderBy.
|
||||
*/
|
||||
public Query<T> desc(String propertyName, String collation) {
|
||||
|
||||
list.add(new Property(propertyName, false, collation));
|
||||
return query;
|
||||
}
|
||||
@@ -108,7 +105,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Return true if the property is known to be contained in the order by clause.
|
||||
*/
|
||||
public boolean containsProperty(String propertyName) {
|
||||
|
||||
for (Property aList : list) {
|
||||
if (propertyName.equals(aList.getProperty())) {
|
||||
return true;
|
||||
@@ -161,10 +157,9 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Return a copy of the OrderBy.
|
||||
*/
|
||||
public OrderBy<T> copy() {
|
||||
|
||||
OrderBy<T> copy = new OrderBy<>();
|
||||
for (Property aList : list) {
|
||||
copy.add(aList.copy());
|
||||
for (Property property : list) {
|
||||
copy.add(property.copy());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
@@ -241,6 +236,18 @@ public final class OrderBy<T> implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this order by can be used in select clause.
|
||||
*/
|
||||
public boolean supportsSelect() {
|
||||
for (Property property : list) {
|
||||
if (!property.supportsSelect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
@@ -401,6 +408,12 @@ public final class OrderBy<T> implements Serializable {
|
||||
this.ascending = ascending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support use in select clause if no collation or nulls ordering.
|
||||
*/
|
||||
boolean supportsSelect() {
|
||||
return nulls == null;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String orderByClause) {
|
||||
|
||||
@@ -501,6 +501,14 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> fetchQuery(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using L2 bean cache.
|
||||
*
|
||||
* @param path The path of the beans we are fetching from L2 cache.
|
||||
* @param fetchProperties The properties that should be loaded.
|
||||
*/
|
||||
Query<T> fetchCache(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties lazily (via batch lazy loading).
|
||||
* <p>
|
||||
@@ -587,6 +595,11 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using L2 cache.
|
||||
*/
|
||||
Query<T> fetchCache(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path lazily (via batch lazy loading).
|
||||
* <p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.service.SpiFetchGroupQuery;
|
||||
import io.ebean.service.SpiFetchGroupService;
|
||||
import io.ebean.service.SpiProfileLocationFactory;
|
||||
import io.ebean.service.SpiRawSqlService;
|
||||
@@ -71,4 +72,11 @@ class XServiceProvider {
|
||||
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
|
||||
return fetchGroupService.of(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup Query for building fetch groups via query beans.
|
||||
*/
|
||||
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
|
||||
return fetchGroupService.queryFor(cls);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* A call origin for query execution profiling to collect graph use (for query tuning).
|
||||
*/
|
||||
public interface CallOrigin {
|
||||
|
||||
/**
|
||||
* Return the top element. Typically the top stack element with class and line.
|
||||
*/
|
||||
String getTopElement();
|
||||
|
||||
/**
|
||||
* Return the full description of the call origin.
|
||||
*/
|
||||
String getFullDescription();
|
||||
|
||||
/**
|
||||
* Compute and return an origin key based on the query hash.
|
||||
*/
|
||||
String getOriginKey(int queryHash);
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package io.ebean.bean;
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static io.ebean.util.EncodeB64.enc;
|
||||
|
||||
/**
|
||||
* Represent the call stack (stack trace elements).
|
||||
* <p>
|
||||
@@ -17,15 +19,15 @@ import java.util.Arrays;
|
||||
* Note the call stack is trimmed to remove the common ebean internal elements.
|
||||
* </p>
|
||||
*/
|
||||
public final class CallStack implements Serializable {
|
||||
public final class CallStack implements Serializable, CallOrigin {
|
||||
|
||||
private static final long serialVersionUID = -8590644046907438579L;
|
||||
|
||||
private static final String NEWLINE = "\n";
|
||||
|
||||
private final String zeroHash;
|
||||
private final String pathHash;
|
||||
|
||||
private final StackTraceElement[] callStack;
|
||||
|
||||
private final int hc;
|
||||
|
||||
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
|
||||
@@ -37,12 +39,17 @@ public final class CallStack implements Serializable {
|
||||
|
||||
private int computeHashCode() {
|
||||
int hc = 0;
|
||||
for (StackTraceElement aCallStack : callStack) {
|
||||
hc = 92821 * hc + aCallStack.hashCode();
|
||||
for (StackTraceElement element : callStack) {
|
||||
hc = 92821 * hc + element.hashCode();
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return zeroHash + ":" + pathHash + ":" + callStack[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hc;
|
||||
@@ -63,73 +70,29 @@ public final class CallStack implements Serializable {
|
||||
/**
|
||||
* Return the first element of the call stack.
|
||||
*/
|
||||
public StackTraceElement getFirstStackTraceElement() {
|
||||
return callStack[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the call stack.
|
||||
*/
|
||||
public StackTraceElement[] getCallStack() {
|
||||
return callStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash for the first stack element.
|
||||
*/
|
||||
public String getZeroHash() {
|
||||
return zeroHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash for the stack elements (excluding first stack element).
|
||||
*/
|
||||
public String getPathHash() {
|
||||
return pathHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return zeroHash + ":" + pathHash + ":" + callStack[0];
|
||||
public String getTopElement() {
|
||||
return callStack[0].toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the call stack lines appended with the given newLine string.
|
||||
*/
|
||||
public String description(String newLine) {
|
||||
@Override
|
||||
public String getFullDescription() {
|
||||
StringBuilder sb = new StringBuilder(400);
|
||||
for (StackTraceElement aCallStack : callStack) {
|
||||
sb.append(aCallStack.toString()).append(newLine);
|
||||
for (int i = 0; i < callStack.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(NEWLINE);
|
||||
}
|
||||
sb.append(callStack[i].toString());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginKey(int queryHash) {
|
||||
return enc(queryHash) + "." + zeroHash + "." + pathHash;
|
||||
}
|
||||
|
||||
private static final int radix = 1 << 6;
|
||||
private static final int mask = radix - 1;
|
||||
|
||||
/**
|
||||
* Convert the integer to unsigned base 64.
|
||||
*/
|
||||
public static String enc(int i) {
|
||||
char[] buf = new char[32];
|
||||
int charPos = 32;
|
||||
do {
|
||||
buf[--charPos] = intToBase64[i & mask];
|
||||
i >>>= 6;
|
||||
} while (i != 0);
|
||||
|
||||
return new String(buf, charPos, (32 - charPos));
|
||||
}
|
||||
|
||||
private static final char intToBase64[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -16,12 +16,16 @@ public interface EntityBean extends Serializable {
|
||||
/**
|
||||
* Return all the property names in defined order.
|
||||
*/
|
||||
String[] _ebean_getPropertyNames();
|
||||
default String[] _ebean_getPropertyNames() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property name at the given position.
|
||||
*/
|
||||
String _ebean_getPropertyName(int pos);
|
||||
default String _ebean_getPropertyName(int pos) {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the enhancement marker value.
|
||||
@@ -30,28 +34,38 @@ public interface EntityBean extends Serializable {
|
||||
* entity classes are enhanced (specifically not just a super class).
|
||||
* </p>
|
||||
*/
|
||||
String _ebean_getMarker();
|
||||
default String _ebean_getMarker() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new entity bean instance.
|
||||
*/
|
||||
Object _ebean_newInstance();
|
||||
default Object _ebean_newInstance() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated method that sets the loaded state on all the embedded beans on
|
||||
* this entity bean by using EntityBeanIntercept.setEmbeddedLoaded(Object o);
|
||||
*/
|
||||
void _ebean_setEmbeddedLoaded();
|
||||
default void _ebean_setEmbeddedLoaded() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if any embedded beans are new or dirty.
|
||||
*/
|
||||
boolean _ebean_isEmbeddedNewOrDirty();
|
||||
default boolean _ebean_isEmbeddedNewOrDirty() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the intercept for this object.
|
||||
*/
|
||||
EntityBeanIntercept _ebean_getIntercept();
|
||||
default EntityBeanIntercept _ebean_getIntercept() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to _ebean_getIntercept() except it checks to see if the intercept
|
||||
@@ -66,7 +80,9 @@ public interface EntityBean extends Serializable {
|
||||
* frameworks that can't take into account our ebean fields.
|
||||
* </p>
|
||||
*/
|
||||
EntityBeanIntercept _ebean_intercept();
|
||||
default EntityBeanIntercept _ebean_intercept() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of a field of an entity bean of this type.
|
||||
@@ -75,12 +91,16 @@ public interface EntityBean extends Serializable {
|
||||
* on entity beans. That means lazy loading and oldValues creation.
|
||||
* </p>
|
||||
*/
|
||||
void _ebean_setField(int fieldIndex, Object value);
|
||||
default void _ebean_setField(int fieldIndex, Object value) {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the field value with interception.
|
||||
*/
|
||||
void _ebean_setFieldIntercept(int fieldIndex, Object value);
|
||||
default void _ebean_setFieldIntercept(int fieldIndex, Object value) {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of a field from an entity bean of this type.
|
||||
@@ -89,11 +109,15 @@ public interface EntityBean extends Serializable {
|
||||
* on entity beans. That means lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
Object _ebean_getField(int fieldIndex);
|
||||
default Object _ebean_getField(int fieldIndex) {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the field value with interception.
|
||||
*/
|
||||
Object _ebean_getFieldIntercept(int fieldIndex);
|
||||
default Object _ebean_getFieldIntercept(int fieldIndex) {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -95,13 +95,10 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
private final byte[] flags;
|
||||
|
||||
private boolean fullyLoadedBean;
|
||||
|
||||
private boolean loadedFromCache;
|
||||
private Object[] origValues;
|
||||
|
||||
private Exception[] loadErrors;
|
||||
|
||||
private int lazyLoadProperty = -1;
|
||||
|
||||
private Object ownerId;
|
||||
private int sortOrder;
|
||||
|
||||
@@ -116,6 +113,14 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
this.flags = new byte[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
public EntityBeanIntercept() {
|
||||
this.owner = null;
|
||||
this.flags = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the 'owning' entity bean.
|
||||
*/
|
||||
@@ -303,6 +308,22 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set true when the bean has been loaded from L2 bean cache.
|
||||
* The effect of this is that we should skip the cache if there
|
||||
* is subsequent lazy loading (bean cache partially populated).
|
||||
*/
|
||||
public void setLoadedFromCache(boolean loadedFromCache) {
|
||||
this.loadedFromCache = loadedFromCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this bean was loaded from L2 bean cache.
|
||||
*/
|
||||
public boolean isLoadedFromCache() {
|
||||
return loadedFromCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the bean should be treated as readOnly. If a setter method
|
||||
* is called when it is readOnly an Exception is thrown.
|
||||
@@ -772,7 +793,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
public boolean[] getLoaded() {
|
||||
boolean[] ret= new boolean[flags.length];
|
||||
boolean[] ret = new boolean[flags.length];
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* This exception is thrown, when the default implementation of EntityBean is not or not properly overwritten by enhancer.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
public class NotEnhancedException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Identifies a unique node of an object graph.
|
||||
@@ -85,8 +86,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
}
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
//noinspection StringEquality
|
||||
return ((e.path == path) || (e.path != null && e.path.equals(path)))
|
||||
return (Objects.equals(e.path, path))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 410937765287968708L;
|
||||
|
||||
private final CallStack callStack;
|
||||
private final CallOrigin callOrigin;
|
||||
|
||||
private final String beanType;
|
||||
|
||||
@@ -24,11 +24,11 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
|
||||
private final String key;
|
||||
|
||||
public ObjectGraphOrigin(int queryHash, CallStack callStack, String beanType) {
|
||||
this.callStack = callStack;
|
||||
public ObjectGraphOrigin(int queryHash, CallOrigin callOrigin, String beanType) {
|
||||
this.callOrigin = callOrigin;
|
||||
this.beanType = beanType;
|
||||
this.queryHash = queryHash;
|
||||
this.key = callStack.getOriginKey(queryHash);
|
||||
this.key = callOrigin.getOriginKey(queryHash);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,22 +49,22 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
/**
|
||||
* The call stack involved.
|
||||
*/
|
||||
public CallStack getCallStack() {
|
||||
return callStack;
|
||||
public CallOrigin getCallOrigin() {
|
||||
return callOrigin;
|
||||
}
|
||||
|
||||
public String getFirstStackElement() {
|
||||
return callStack.getFirstStackTraceElement().toString();
|
||||
public String getTopElement() {
|
||||
return callOrigin.getTopElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "key[" + key + "] type[" + beanType + "] " + callStack.getFirstStackTraceElement() + " ";
|
||||
return "key[" + key + "] type[" + beanType + "] " + callOrigin.getTopElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hc = 92821 * callStack.hashCode();
|
||||
int hc = 92821 * callOrigin.hashCode();
|
||||
hc = 92821 * hc + beanType.hashCode();
|
||||
hc = 92821 * hc + queryHash;
|
||||
return hc;
|
||||
@@ -82,6 +82,6 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
ObjectGraphOrigin e = (ObjectGraphOrigin) obj;
|
||||
return e.queryHash == queryHash
|
||||
&& e.beanType.equals(beanType)
|
||||
&& e.callStack.equals(callStack);
|
||||
&& e.callOrigin.equals(callOrigin);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ public enum ServerCacheType {
|
||||
*/
|
||||
QUERY("_Q");
|
||||
|
||||
private String code;
|
||||
private final String code;
|
||||
|
||||
ServerCacheType(String code) {
|
||||
this.code = code;
|
||||
|
||||
@@ -219,7 +219,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
/**
|
||||
* Copies all relevant properties for a clone. See {@link #getShallowCopy()}
|
||||
* @param other
|
||||
*/
|
||||
protected void setFromOriginal(AbstractBeanCollection<E> other) {
|
||||
this.disableLazyLoad = other.disableLazyLoad;
|
||||
|
||||
@@ -237,7 +237,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
|
||||
@@ -77,6 +77,9 @@ public class PlatformConfig {
|
||||
this.geometrySRID = platformConfig.geometrySRID;
|
||||
this.dbUuid = platformConfig.dbUuid;
|
||||
this.caseSensitiveCollation = platformConfig.caseSensitiveCollation;
|
||||
this.allQuotedIdentifiers = platformConfig.allQuotedIdentifiers;
|
||||
this.databaseInetAddressVarchar = platformConfig.databaseInetAddressVarchar;
|
||||
this.customDbTypeMappings = platformConfig.customDbTypeMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -653,6 +653,7 @@ public class ServerConfig {
|
||||
* @param cls The type of the service object to obtain
|
||||
* @return The service object given the class type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <P> P getServiceObject(Class<P> cls) {
|
||||
return (P) serviceObject.get(serviceObjectKey(cls));
|
||||
}
|
||||
@@ -2928,6 +2929,7 @@ public class ServerConfig {
|
||||
}
|
||||
loadDocStoreSettings(p);
|
||||
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
|
||||
|
||||
@@ -35,9 +35,9 @@ public enum TenantMode {
|
||||
* (that holds configuration e.g.)
|
||||
*/
|
||||
DB_WITH_MASTER(true, true);
|
||||
|
||||
boolean dynamicDataSource;
|
||||
boolean ddlEnabled;
|
||||
|
||||
final boolean dynamicDataSource;
|
||||
final boolean ddlEnabled;
|
||||
|
||||
TenantMode(boolean dynamicDataSource, boolean ddlEnabled) {
|
||||
this.dynamicDataSource = dynamicDataSource;
|
||||
@@ -50,12 +50,12 @@ public enum TenantMode {
|
||||
public boolean isDynamicDataSource() {
|
||||
return dynamicDataSource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, if DDL is enabled.
|
||||
*/
|
||||
public boolean isDdlEnabled() {
|
||||
return ddlEnabled;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ public class DatabasePlatform {
|
||||
|
||||
protected boolean supportsDeleteTableAlias;
|
||||
|
||||
protected boolean supportsSavepointId = true;
|
||||
|
||||
/**
|
||||
* The behaviour used when ending a read only transaction at read committed isolation level.
|
||||
*/
|
||||
@@ -137,6 +139,8 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected Platform platform = Platform.GENERIC;
|
||||
|
||||
protected String truncateTable = "truncate table %s";
|
||||
|
||||
protected String columnAliasPrefix = "c";
|
||||
|
||||
protected String tableAliasPlaceHolder = "${ta}";
|
||||
@@ -328,6 +332,13 @@ public class DatabasePlatform {
|
||||
return caseSensitiveCollation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports SavepointId values.
|
||||
*/
|
||||
public boolean isSupportsSavepointId() {
|
||||
return supportsSavepointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum table name length.
|
||||
* <p>
|
||||
@@ -568,7 +579,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Normally not needed - overridden in CockroachPlatform.
|
||||
*/
|
||||
public boolean isDdlCommitOnCreateIndex() {
|
||||
public boolean isDdlAutoCommit() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -699,6 +710,13 @@ public class DatabasePlatform {
|
||||
return persistBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a statement to truncate a table.
|
||||
*/
|
||||
public String truncateStatement(String table) {
|
||||
return String.format(truncateTable, table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the DB schema if it does not exist.
|
||||
*/
|
||||
|
||||
@@ -27,15 +27,13 @@ public class DbDefaultValue {
|
||||
* The key for the NOW / current timestamp.
|
||||
*/
|
||||
public static final String NOW = "now";
|
||||
|
||||
|
||||
/**
|
||||
* The 'null' literal.
|
||||
*/
|
||||
public static final String NULL = "null";
|
||||
|
||||
|
||||
|
||||
protected Map<String, String> map = new LinkedHashMap<>();
|
||||
protected final Map<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Set the DB now function.
|
||||
@@ -82,10 +80,9 @@ public class DbDefaultValue {
|
||||
return val != null ? val : dbDefaultLiteral;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method checks & convert the {@link DbDefault#value()} to a valid SQL literal.
|
||||
*
|
||||
*
|
||||
* This is mainly to quote string literals and verify integer/dates for correctness.
|
||||
* <p>
|
||||
* Note: There are some special cases:
|
||||
@@ -98,24 +95,24 @@ public class DbDefaultValue {
|
||||
* If you need really the String "null", you have to specify <code>@DbDefault("'null'")</code>
|
||||
* which gives you the <code>default 'null'</code> statement.</li>
|
||||
* <li>Any statement, that begins and ends with single quote will not be checked or get quoted again.</li>
|
||||
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
|
||||
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
|
||||
* a <code>default N'SANDNES'</code> in DDL. Note that this is platform specific!</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static String toSqlLiteral(String defaultValue, Class<?> propertyType, int sqlType) {
|
||||
if (propertyType == null
|
||||
|| defaultValue == null
|
||||
|| defaultValue == null
|
||||
|| NULL.equals(defaultValue)
|
||||
|| (defaultValue.startsWith("'") && defaultValue.endsWith("'"))
|
||||
|| (defaultValue.startsWith("$RAW:"))) {
|
||||
|| (defaultValue.startsWith("$RAW:"))) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (Boolean.class.isAssignableFrom(propertyType) || Boolean.TYPE.isAssignableFrom(propertyType)) {
|
||||
return toBooleanLiteral(defaultValue);
|
||||
}
|
||||
|
||||
if (Number.class.isAssignableFrom(propertyType)
|
||||
|
||||
if (Number.class.isAssignableFrom(propertyType)
|
||||
|| Byte.TYPE.equals(propertyType)
|
||||
|| Short.TYPE.equals(propertyType)
|
||||
|| Integer.TYPE.equals(propertyType)
|
||||
@@ -126,7 +123,7 @@ public class DbDefaultValue {
|
||||
Double.valueOf(defaultValue); // verify if it is a number
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
// check if it is a date/time - in all other cases return quoted defaultValue
|
||||
switch (sqlType) {
|
||||
// date
|
||||
@@ -155,7 +152,7 @@ public class DbDefaultValue {
|
||||
}
|
||||
throw new IllegalArgumentException("'" + value + "' is not a valid value for boolean");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This adds single qoutes around the <code>value</code> and doubles single quotes.
|
||||
* "User's home" will return "'User''s home'"
|
||||
@@ -175,7 +172,7 @@ public class DbDefaultValue {
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String toDateLiteral(String value) {
|
||||
if (NOW.equals(value)) {
|
||||
return value; // this will get translated later
|
||||
@@ -191,7 +188,7 @@ public class DbDefaultValue {
|
||||
DatatypeConverter.parseTime(value); // verify
|
||||
return toTextLiteral(value);
|
||||
}
|
||||
|
||||
|
||||
private static String toDateTimeLiteral(String value) {
|
||||
if (NOW.equals(value)) {
|
||||
return value; // this will get translated later
|
||||
|
||||
@@ -11,12 +11,12 @@ class DbPlatformTypeLookup {
|
||||
/**
|
||||
* A map to lookup the type by name.
|
||||
*/
|
||||
private Map<String, DbType> nameLookup = new HashMap<>();
|
||||
private final Map<String, DbType> nameLookup = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A map to lookup the type by JDBC int value.
|
||||
*/
|
||||
private Map<Integer, DbType> idLookup = new HashMap<>();
|
||||
private final Map<Integer, DbType> idLookup = new HashMap<>();
|
||||
|
||||
DbPlatformTypeLookup() {
|
||||
addAll();
|
||||
|
||||
@@ -23,7 +23,7 @@ public class DbPlatformTypeMapping {
|
||||
}
|
||||
}
|
||||
|
||||
private static DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
|
||||
private static final DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
|
||||
|
||||
private static final DbPlatformType BOOLEAN_LOGICAL = new BooleanLogicalType();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class SqlErrorCodes {
|
||||
|
||||
private Map<String,DataErrorType> map = new HashMap<>();
|
||||
private final Map<String,DataErrorType> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map the codes to AcquireLockException.
|
||||
|
||||
@@ -21,7 +21,7 @@ public class CockroachPlatform extends PostgresPlatform {
|
||||
* Needs a commit after create index such that alter table add foreign key ... succeeds.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDdlCommitOnCreateIndex() {
|
||||
public boolean isDdlAutoCommit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ public class DB2Platform extends DatabasePlatform {
|
||||
this.platform = Platform.DB2;
|
||||
this.maxTableNameLength = 18;
|
||||
this.maxConstraintNameLength = 18;
|
||||
this.truncateTable = "truncate table %s reuse storage ignore delete triggers immediate";
|
||||
this.sqlLimiter = new Db2SqlLimiter();
|
||||
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
|
||||
@@ -26,7 +26,6 @@ public class H2Platform extends DatabasePlatform {
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
this.columnAliasPrefix = null;
|
||||
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("50200","HYT00")
|
||||
|
||||
@@ -18,7 +18,6 @@ public class HanaPlatform extends DatabasePlatform {
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.supportsResultSetConcurrencyModeUpdatable = false;
|
||||
this.columnAliasPrefix = null;
|
||||
|
||||
this.historySupport = new HanaHistorySupport();
|
||||
this.basicSqlLimiter = new HanaBasicSqlLimiter();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ public class HsqldbPlatform extends DatabasePlatform {
|
||||
super();
|
||||
this.platform = Platform.HSQLDB;
|
||||
this.dbEncrypt = new H2DbEncrypt();
|
||||
|
||||
this.truncateTable = "delete from %s";
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
|
||||
@@ -27,10 +27,10 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
this.platform = Platform.MYSQL;
|
||||
this.useExtraTransactionOnIterateSecondaryQueries = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.supportsSavepointId = false;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
this.historySupport = new MySqlHistorySupport();
|
||||
this.columnAliasPrefix = null;
|
||||
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package io.ebean.config.dbplatform.nuodb;
|
||||
|
||||
import io.ebean.config.dbplatform.DbViewHistorySupport;
|
||||
|
||||
/**
|
||||
* Runtime support for @History with NuoDB.
|
||||
*/
|
||||
public class NuoDbHistorySupport extends DbViewHistorySupport {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.ebean.config.dbplatform.nuodb;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* NuoDb specific platform.
|
||||
*/
|
||||
public class NuoDbPlatform extends DatabasePlatform {
|
||||
|
||||
public NuoDbPlatform() {
|
||||
super();
|
||||
this.platform = Platform.NUODB;
|
||||
this.idInExpandedForm = true;
|
||||
this.supportsResultSetConcurrencyModeUpdatable = false;
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.columnAliasPrefix = null;
|
||||
this.likeClauseRaw = "like ?";
|
||||
this.historySupport = new NuoDbHistorySupport();
|
||||
//this.dbEncrypt = ...
|
||||
dbIdentity.setIdType(IdType.IDENTITY);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
dbIdentity.setSupportsSequence(true);
|
||||
dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
|
||||
// No referential integrity exception to map
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
//.addAcquireLock("")
|
||||
.addDuplicateKey("23000")
|
||||
.build();
|
||||
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new NuoDbSequence(be, ds, seqName, stepSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
|
||||
switch (forUpdateMode) {
|
||||
case NOWAIT:
|
||||
return sql + " for update nowait";
|
||||
case SKIPLOCKED:
|
||||
default:
|
||||
return sql + " for update";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.ebean.config.dbplatform.nuodb;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public class NuoDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*/
|
||||
public NuoDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = "select next value for " + seqName + " from dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return nextSql;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
this.sqlLimiter = new RownumSqlLimiter();
|
||||
this.basicSqlLimiter = new BasicSqlAnsiLimiter();
|
||||
this.historySupport = new OracleDbHistorySupport();
|
||||
|
||||
this.truncateTable = "truncate table %s cascade";
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
dbIdentity.setSupportsSequence(true);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
@@ -36,7 +36,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
this.clobDbType = Types.VARCHAR;
|
||||
this.nativeUuidType = true;
|
||||
this.columnAliasPrefix = null;
|
||||
|
||||
this.truncateTable = "truncate table %s cascade";
|
||||
this.dbEncrypt = new PostgresDbEncrypt();
|
||||
this.historySupport = new PostgresHistorySupport();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public class SQLitePlatform extends DatabasePlatform {
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
this.dbIdentity.setSupportsSequence(false);
|
||||
this.dbIdentity.setSelectLastInsertedIdTemplate("select last_insert_rowid()");
|
||||
|
||||
this.truncateTable = "delete from %s";
|
||||
this.booleanDbType = Types.INTEGER;
|
||||
this.likeClauseRaw = "like ?";
|
||||
this.likeClauseEscaped = "like ?";
|
||||
|
||||
@@ -24,6 +24,11 @@ public interface BeanQueryRequest<T> {
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
/**
|
||||
* Return true if an Id IN expression should have the bind parameters padded.
|
||||
*/
|
||||
boolean isPadInExpression();
|
||||
|
||||
/**
|
||||
* Return true if multi-value binding using Array or Table Values is supported.
|
||||
*/
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class QueryPlanRequest {
|
||||
|
||||
private List<MetaQueryPlan> plans = new ArrayList<>();
|
||||
private final List<MetaQueryPlan> plans = new ArrayList<>();
|
||||
|
||||
private Connection connection;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
class MetricServiceProvider {
|
||||
|
||||
private static MetricFactory metricFactory = init();
|
||||
private static final MetricFactory metricFactory = init();
|
||||
|
||||
private static MetricFactory init() {
|
||||
|
||||
|
||||
@@ -223,7 +223,6 @@ public interface BeanType<T> {
|
||||
|
||||
/**
|
||||
* Visit all children recursively
|
||||
* @param visitor
|
||||
*/
|
||||
void visitAllInheritanceChildren(Consumer<BeanType<?>> visitor);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public interface ExpressionPath {
|
||||
/**
|
||||
* Return the underlying bean property.
|
||||
*/
|
||||
public Property getProperty();
|
||||
Property getProperty();
|
||||
|
||||
/**
|
||||
* The ElPrefix plus name.
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Property of a entity bean that is a ToMany property.
|
||||
*/
|
||||
public interface PropertyAssocMany extends Property {
|
||||
|
||||
/**
|
||||
* Add the loaded current bean to its associated parent.
|
||||
* <p>
|
||||
* Helper method used by Ebean Elastic integration when loading with a persistence context.
|
||||
*/
|
||||
void lazyLoadMany(EntityBean current);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.ebean.service;
|
||||
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.Query;
|
||||
|
||||
/**
|
||||
* Extension of Query to build FetchGroup via query beans.
|
||||
*/
|
||||
public interface SpiFetchGroupQuery<T> extends Query<T> {
|
||||
|
||||
/**
|
||||
* Build the fetch group with select and fetch clauses.
|
||||
*/
|
||||
FetchGroup<T> buildFetchGroup();
|
||||
}
|
||||
@@ -23,4 +23,10 @@ public interface SpiFetchGroupService {
|
||||
* @return The FetchGroupBuilder to add additional select and fetch clauses
|
||||
*/
|
||||
<T> FetchGroupBuilder<T> of(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Return a new FetchGroupQuery for building FetchGroup via query beans.
|
||||
*/
|
||||
<T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType);
|
||||
|
||||
}
|
||||
|
||||
@@ -49,13 +49,12 @@ class PathPropertiesParser {
|
||||
private String getPath() {
|
||||
do {
|
||||
char c1 = chars[pos++];
|
||||
switch (c1) {
|
||||
case '(':
|
||||
return currentWord();
|
||||
default:
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
if (c1 == '(') {
|
||||
return currentWord();
|
||||
} else {
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} while (pos < eof);
|
||||
throw new RuntimeException("Hit EOF while reading sectionTitle from " + startPos);
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
@@ -107,9 +108,7 @@ public class AnnotationUtil {
|
||||
* Finds all annotations recusively for a class and its superclasses or interfaces.
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> findAnnotationsRecursive(Class<?> clazz, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
Objects.requireNonNull(annotationType);
|
||||
Set<A> ret = new LinkedHashSet<>();
|
||||
Set<Annotation> visited = new HashSet<>();
|
||||
Set<Class<?>> visitedInterfaces = new HashSet<>();
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package io.ebean.util;
|
||||
|
||||
/**
|
||||
* Integer to base64 encoder.
|
||||
*/
|
||||
public final class EncodeB64 {
|
||||
|
||||
private static final int radix = 1 << 6;
|
||||
private static final int mask = radix - 1;
|
||||
|
||||
/**
|
||||
* Convert the integer to unsigned base 64.
|
||||
*/
|
||||
public static String enc(int i) {
|
||||
char[] buf = new char[32];
|
||||
int charPos = 32;
|
||||
do {
|
||||
buf[--charPos] = intToBase64[i & mask];
|
||||
i >>>= 6;
|
||||
} while (i != 0);
|
||||
|
||||
return new String(buf, charPos, (32 - charPos));
|
||||
}
|
||||
|
||||
private static final char intToBase64[] = {
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||
};
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import java.util.List;
|
||||
*/
|
||||
public class BeanCacheResult<T> {
|
||||
|
||||
private List<Entry<T>> list = new ArrayList<>();
|
||||
private final List<Entry<T>> list = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Add an entry.
|
||||
|
||||
@@ -115,10 +115,10 @@ public class BindParams implements Serializable {
|
||||
* Return a Natural Key bind param if supported.
|
||||
*/
|
||||
public NaturalKeyBindParam getNaturalKeyBindParam() {
|
||||
if (positionedParameters != null) {
|
||||
if (!positionedParameters.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (namedParameters != null && namedParameters.size() == 1) {
|
||||
if (namedParameters.size() == 1) {
|
||||
Entry<String, Param> e = namedParameters.entrySet().iterator().next();
|
||||
return new NaturalKeyBindParam(e.getKey(), e.getValue().getInValue());
|
||||
}
|
||||
|
||||
@@ -7,22 +7,37 @@ import io.ebean.TxScope;
|
||||
* Helper object to make AOP generated code simpler.
|
||||
*/
|
||||
public class HelpScopeTrans {
|
||||
private static boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Entering an enhanced transactional method.
|
||||
*/
|
||||
public static void enter(TxScope txScope) {
|
||||
server().scopedTransactionEnter(txScope);
|
||||
if (enabled) {
|
||||
server().scopedTransactionEnter(txScope);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exiting an enhanced transactional method.
|
||||
*/
|
||||
public static void exit(Object returnOrThrowable, int opCode) {
|
||||
server().scopedTransactionExit(returnOrThrowable, opCode);
|
||||
if (enabled) {
|
||||
server().scopedTransactionExit(returnOrThrowable, opCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static SpiEbeanServer server() {
|
||||
return (SpiEbeanServer) Ebean.getDefaultServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the @Transactional does what is supposed to do or is disabled
|
||||
* (useful only unit testing)
|
||||
*
|
||||
* @param enabled if set to false, @Transactional will not create a transaction
|
||||
*/
|
||||
public static void setEnabled(boolean enabled) {
|
||||
HelpScopeTrans.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,6 @@ import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -17,8 +15,6 @@ import java.util.Set;
|
||||
*/
|
||||
public class LoadBeanRequest extends LoadRequest {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(LoadBeanRequest.class);
|
||||
|
||||
private final List<EntityBeanIntercept> batch;
|
||||
|
||||
private final LoadBeanBuffer loadBuffer;
|
||||
@@ -27,11 +23,14 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
|
||||
private final boolean loadCache;
|
||||
|
||||
private boolean loadedFromCache;
|
||||
|
||||
/**
|
||||
* Construct for lazy load request.
|
||||
*/
|
||||
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, String lazyLoadProperty, boolean loadCache) {
|
||||
this(LoadBuffer, null, true, lazyLoadProperty, loadCache);
|
||||
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, EntityBeanIntercept ebi, boolean loadCache) {
|
||||
this(LoadBuffer, null, true, ebi.getLazyLoadProperty(), loadCache);
|
||||
this.loadedFromCache = ebi.isLoadedFromCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,10 +55,16 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
return loadBuffer.getBeanDescriptor().getBeanType();
|
||||
}
|
||||
|
||||
public boolean isLoadCache() {
|
||||
return loadCache;
|
||||
/**
|
||||
* Return true if the beans invoking lazy loading were previously loaded from cache.
|
||||
*/
|
||||
public boolean isLoadedFromCache() {
|
||||
return loadedFromCache;
|
||||
}
|
||||
|
||||
private boolean isLoadCache() {
|
||||
return loadCache;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "path:" + loadBuffer.getFullPath() + " batch:" + batch.size();
|
||||
@@ -75,17 +80,10 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Return the load context.
|
||||
*/
|
||||
public LoadBeanBuffer getLoadContext() {
|
||||
private LoadBeanBuffer getLoadContext() {
|
||||
return loadBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property that invoked the lazy loading.
|
||||
*/
|
||||
public String getLazyLoadProperty() {
|
||||
return lazyLoadProperty;
|
||||
}
|
||||
|
||||
public int getBatchSize() {
|
||||
return getLoadContext().getBatchSize();
|
||||
}
|
||||
@@ -93,30 +91,14 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Return the list of Id values for the beans in the lazy load buffer.
|
||||
*/
|
||||
public List<Object> getIdList(int batchSize) {
|
||||
public List<Object> getIdList() {
|
||||
|
||||
List<Object> idList = new ArrayList<>(batchSize);
|
||||
List<Object> idList = new ArrayList<>();
|
||||
|
||||
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
|
||||
for (EntityBeanIntercept ebi : batch) {
|
||||
EntityBean bean = ebi.getOwner();
|
||||
idList.add(desc.getId(bean));
|
||||
idList.add(desc.getId(ebi.getOwner()));
|
||||
}
|
||||
|
||||
|
||||
if (!desc.isMultiValueIdSupported() && !idList.isEmpty()) {
|
||||
int extraIds = batchSize - batch.size();
|
||||
if (extraIds > 0) {
|
||||
// for performance make up the Id's to the batch size
|
||||
// so we get the same query (for Ebean and the db)
|
||||
Object firstId = idList.get(0);
|
||||
for (int i = 0; i < extraIds; i++) {
|
||||
// just add the first Id again
|
||||
idList.add(firstId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idList;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.api;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.server.core.BindPadding;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -65,13 +66,6 @@ public class LoadManyRequest extends LoadRequest {
|
||||
return batch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the load context.
|
||||
*/
|
||||
public LoadManyBuffer getLoadContext() {
|
||||
return loadContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if lazy loading should only load the id values.
|
||||
* <p>
|
||||
@@ -80,14 +74,14 @@ public class LoadManyRequest extends LoadRequest {
|
||||
* used.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isOnlyIds() {
|
||||
private boolean isOnlyIds() {
|
||||
return onlyIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we should load the Collection ids into the cache.
|
||||
*/
|
||||
public boolean isLoadCache() {
|
||||
private boolean isLoadCache() {
|
||||
return loadCache;
|
||||
}
|
||||
|
||||
@@ -98,22 +92,16 @@ public class LoadManyRequest extends LoadRequest {
|
||||
return loadContext.getBatchSize();
|
||||
}
|
||||
|
||||
private List<Object> getParentIdList(int batchSize) {
|
||||
private List<Object> getParentIdList() {
|
||||
|
||||
ArrayList<Object> idList = new ArrayList<>(batchSize);
|
||||
List<Object> idList = new ArrayList<>();
|
||||
|
||||
BeanPropertyAssocMany<?> many = getMany();
|
||||
for (BeanCollection<?> bc : batch) {
|
||||
idList.add(many.getParentId(bc.getOwnerBean()));
|
||||
}
|
||||
if (!many.getTargetDescriptor().isMultiValueIdSupported()) {
|
||||
int extraIds = batchSize - batch.size();
|
||||
if (extraIds > 0) {
|
||||
Object firstId = idList.get(0);
|
||||
for (int i = 0; i < extraIds; i++) {
|
||||
idList.add(firstId);
|
||||
}
|
||||
}
|
||||
if (many.getTargetDescriptor().isPadInExpression()) {
|
||||
BindPadding.padIds(idList);
|
||||
}
|
||||
|
||||
return idList;
|
||||
@@ -123,7 +111,7 @@ public class LoadManyRequest extends LoadRequest {
|
||||
return loadContext.getBeanProperty();
|
||||
}
|
||||
|
||||
public SpiQuery<?> createQuery(SpiEbeanServer server, int batchSize) {
|
||||
public SpiQuery<?> createQuery(SpiEbeanServer server) {
|
||||
|
||||
BeanPropertyAssocMany<?> many = getMany();
|
||||
|
||||
@@ -142,10 +130,7 @@ public class LoadManyRequest extends LoadRequest {
|
||||
}
|
||||
|
||||
query.setLazyLoadForParents(many);
|
||||
|
||||
List<Object> idList = getParentIdList(batchSize);
|
||||
many.addWhereParentIdIn(query, idList, loadContext.isUseDocStore());
|
||||
|
||||
many.addWhereParentIdIn(query, getParentIdList(), loadContext.isUseDocStore());
|
||||
query.setPersistenceContext(loadContext.getPersistenceContext());
|
||||
|
||||
String mode = isLazy() ? "+lazy" : "+query";
|
||||
|
||||
@@ -7,7 +7,9 @@ import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@@ -21,9 +23,7 @@ public class ManyWhereJoins implements Serializable {
|
||||
|
||||
private final TreeMap<String, PropertyJoin> joins = new TreeMap<>();
|
||||
|
||||
private StringBuilder formulaProperties = new StringBuilder();
|
||||
|
||||
private boolean formulaWithJoin;
|
||||
private List<String> formulaJoinProperties;
|
||||
|
||||
private boolean aggregation;
|
||||
|
||||
@@ -125,27 +125,24 @@ public class ManyWhereJoins implements Serializable {
|
||||
* specifically for the findCount query.
|
||||
*/
|
||||
public void addFormulaWithJoin(String propertyName) {
|
||||
if (formulaWithJoin) {
|
||||
formulaProperties.append(",");
|
||||
} else {
|
||||
formulaProperties = new StringBuilder();
|
||||
formulaWithJoin = true;
|
||||
if (formulaJoinProperties == null) {
|
||||
formulaJoinProperties = new ArrayList<>();
|
||||
}
|
||||
formulaProperties.append(propertyName);
|
||||
formulaJoinProperties.add(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the query select includes a formula with join.
|
||||
*/
|
||||
public boolean isFormulaWithJoin() {
|
||||
return formulaWithJoin;
|
||||
return formulaJoinProperties != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the formula properties to build the select clause for a findCount query.
|
||||
*/
|
||||
public String getFormulaProperties() {
|
||||
return formulaProperties.toString();
|
||||
public List<String> getFormulaJoinProperties() {
|
||||
return formulaJoinProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,8 +12,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class NaturalKeyEntry {
|
||||
|
||||
private Map<String,Object> map = new HashMap<>();
|
||||
private Object key;
|
||||
private final Map<String,Object> map = new HashMap<>();
|
||||
private final Object key;
|
||||
private Object inValue;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ScopedTransaction extends SpiTransactionProxy {
|
||||
/**
|
||||
* Stack of 'nested' transactions.
|
||||
*/
|
||||
private ArrayStack<ScopeTrans> stack = new ArrayStack<>();
|
||||
private final ArrayStack<ScopeTrans> stack = new ArrayStack<>();
|
||||
|
||||
private ScopeTrans current;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import io.ebean.Transaction;
|
||||
import io.ebean.TxScope;
|
||||
import io.ebean.bean.BeanCollectionLoader;
|
||||
import io.ebean.bean.BeanLoader;
|
||||
import io.ebean.bean.CallStack;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -81,7 +81,7 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanLoader,
|
||||
* graph costing.
|
||||
* </p>
|
||||
*/
|
||||
CallStack createCallStack();
|
||||
CallOrigin createCallOrigin();
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope to use defined at query or server level.
|
||||
|
||||
@@ -7,7 +7,7 @@ import io.ebean.OrderBy;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.bean.CallStack;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.event.readaudit.ReadEvent;
|
||||
@@ -106,9 +106,9 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
*/
|
||||
UPDATE(FIND_UPDATE, "update", true);
|
||||
|
||||
private boolean update;
|
||||
private String profileEventId;
|
||||
private String label;
|
||||
private final boolean update;
|
||||
private final String profileEventId;
|
||||
private final String label;
|
||||
|
||||
Type(String profileEventId, String label) {
|
||||
this(profileEventId, label, false);
|
||||
@@ -289,6 +289,11 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
*/
|
||||
boolean selectAllForLazyLoadProperty();
|
||||
|
||||
/**
|
||||
* Set the on a secondary query given the label, relativePath and profile location of the parent query.
|
||||
*/
|
||||
void setProfilePath(String label, String relativePath, ProfileLocation profileLocation);
|
||||
|
||||
/**
|
||||
* Set the query mode.
|
||||
*/
|
||||
@@ -558,7 +563,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
* because the queryPlanHash is used to identify the query point.
|
||||
* </p>
|
||||
*/
|
||||
ObjectGraphNode setOrigin(CallStack callStack);
|
||||
ObjectGraphNode setOrigin(CallOrigin callOrigin);
|
||||
|
||||
/**
|
||||
* Set the profile point of the bean or collection that is lazy loading.
|
||||
|
||||
@@ -40,4 +40,19 @@ public interface SpiTransactionManager {
|
||||
*/
|
||||
void externalRemoveTransaction();
|
||||
|
||||
/**
|
||||
* Notify of a transaction commit.
|
||||
*/
|
||||
void notifyOfCommit(SpiTransaction transaction);
|
||||
|
||||
/**
|
||||
* Notify of a transaction rollback.
|
||||
*/
|
||||
void notifyOfRollback(SpiTransaction transaction, Throwable cause);
|
||||
|
||||
/**
|
||||
* Notify of a query only transaction commit.
|
||||
*/
|
||||
void notifyOfQueryOnly(SpiTransaction transaction);
|
||||
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class TransactionEvent implements Serializable {
|
||||
* Return the list of PersistRequestBean's for this transaction.
|
||||
*/
|
||||
public List<PersistRequestBean<?>> getListenerNotify() {
|
||||
return (listenerNotify == null) ? null : listenerNotify;
|
||||
return listenerNotify;
|
||||
}
|
||||
|
||||
public TransactionEventTable getEventTables() {
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.sql.SQLException;
|
||||
public class DdlGenerator {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DdlGenerator.class);
|
||||
private static final String[] BUILD_DIRS = {"target", "build"};
|
||||
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
@@ -43,13 +44,14 @@ public class DdlGenerator {
|
||||
private final boolean extraDdl;
|
||||
private final boolean createOnly;
|
||||
private final boolean jaxbPresent;
|
||||
private final boolean ddlCommitOnCreateIndex;
|
||||
private final boolean ddlAutoCommit;
|
||||
private final String dbSchema;
|
||||
private final ScriptTransform scriptTransform;
|
||||
|
||||
private CurrentModel currentModel;
|
||||
private String dropAllContent;
|
||||
private String createAllContent;
|
||||
private File baseDir;
|
||||
|
||||
public DdlGenerator(SpiEbeanServer server, ServerConfig serverConfig) {
|
||||
this.server = server;
|
||||
@@ -61,12 +63,23 @@ public class DdlGenerator {
|
||||
if (!serverConfig.getTenantMode().isDdlEnabled() && serverConfig.isDdlRun()) {
|
||||
log.warn("DDL can't be run on startup with TenantMode " + serverConfig.getTenantMode());
|
||||
this.runDdl = false;
|
||||
this.ddlCommitOnCreateIndex = false;
|
||||
this.ddlAutoCommit = false;
|
||||
} else {
|
||||
this.runDdl = serverConfig.isDdlRun();
|
||||
this.ddlCommitOnCreateIndex = server.getDatabasePlatform().isDdlCommitOnCreateIndex();
|
||||
this.ddlAutoCommit = server.getDatabasePlatform().isDdlAutoCommit();
|
||||
}
|
||||
this.scriptTransform = createScriptTransform(serverConfig.getMigrationConfig());
|
||||
this.baseDir = initBaseDir();
|
||||
}
|
||||
|
||||
private File initBaseDir() {
|
||||
for (String buildDir : BUILD_DIRS) {
|
||||
File dir = new File(buildDir);
|
||||
if (dir.exists() && dir.isDirectory()) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
return new File(".");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,13 +160,11 @@ public class DdlGenerator {
|
||||
|
||||
DdlRunner runner = new DdlRunner(expectErrors, scriptName);
|
||||
try {
|
||||
if (expectErrors) {
|
||||
if (expectErrors || ddlAutoCommit) {
|
||||
connection.setAutoCommit(true);
|
||||
} else if (ddlCommitOnCreateIndex) {
|
||||
runner.setCommitOnCreateIndex();
|
||||
}
|
||||
int count = runner.runAll(scriptTransform.transform(content), connection);
|
||||
if (expectErrors) {
|
||||
if (expectErrors || ddlAutoCommit) {
|
||||
connection.setAutoCommit(false);
|
||||
}
|
||||
connection.commit();
|
||||
@@ -212,7 +223,6 @@ public class DdlGenerator {
|
||||
* extra-ddl.xml should have some partition initialisation but this helps people get going.
|
||||
*/
|
||||
private void checkInitialTablePartitions(Connection connection) {
|
||||
|
||||
DatabasePlatform databasePlatform = server.getDatabasePlatform();
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -245,12 +255,11 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected void runResourceScript(Connection connection, String sqlScript) throws IOException {
|
||||
|
||||
if (sqlScript != null) {
|
||||
try (InputStream is = getClassLoader().getResourceAsStream(sqlScript)) {
|
||||
if (is != null) {
|
||||
String content = readContent(new InputStreamReader(is));
|
||||
runScript(connection, false, content, sqlScript);
|
||||
runScript(connection, false, content, sqlScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,7 +277,6 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected void writeDrop(String dropFile) {
|
||||
|
||||
try {
|
||||
writeFile(dropFile, generateDropAllDdl());
|
||||
} catch (IOException e) {
|
||||
@@ -277,7 +285,6 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected void writeCreate(String createFile) {
|
||||
|
||||
try {
|
||||
writeFile(createFile, generateCreateAllDdl());
|
||||
} catch (IOException e) {
|
||||
@@ -286,7 +293,6 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected String generateDropAllDdl() {
|
||||
|
||||
try {
|
||||
dropAllContent = currentModel().getDropAllDdl();
|
||||
return dropAllContent;
|
||||
@@ -296,7 +302,6 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected String generateCreateAllDdl() {
|
||||
|
||||
try {
|
||||
createAllContent = currentModel().getCreateDdl();
|
||||
return createAllContent;
|
||||
@@ -321,8 +326,7 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected void writeFile(String fileName, String fileContent) throws IOException {
|
||||
|
||||
File f = new File(fileName);
|
||||
File f = new File(baseDir, fileName);
|
||||
try (FileWriter fw = new FileWriter(f)) {
|
||||
fw.write(fileContent);
|
||||
fw.flush();
|
||||
@@ -330,17 +334,14 @@ public class DdlGenerator {
|
||||
}
|
||||
|
||||
protected String readFile(String fileName) throws IOException {
|
||||
|
||||
File f = new File(fileName);
|
||||
File f = new File(baseDir, fileName);
|
||||
if (!f.exists()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return readContent(new FileReader(f));
|
||||
}
|
||||
|
||||
protected String readContent(Reader reader) throws IOException {
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
try (LineNumberReader lineReader = new LineNumberReader(reader)) {
|
||||
String s;
|
||||
@@ -355,7 +356,6 @@ public class DdlGenerator {
|
||||
* Create the ScriptTransform for placeholder key/value replacement.
|
||||
*/
|
||||
private ScriptTransform createScriptTransform(DbMigrationConfig config) {
|
||||
|
||||
return ScriptTransform.build(config.getRunPlaceholders(), config.getRunPlaceholderMap());
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
import io.ebean.config.dbplatform.sqlanywhere.SqlAnywherePlatform;
|
||||
@@ -804,6 +805,8 @@ public class DefaultDbMigration implements DbMigration {
|
||||
return new SQLitePlatform();
|
||||
case HANA:
|
||||
return new HanaPlatform();
|
||||
case NUODB:
|
||||
return new NuoDbPlatform();
|
||||
case COCKROACH:
|
||||
return new CockroachPlatform();
|
||||
case CLICKHOUSE:
|
||||
|
||||
@@ -60,10 +60,7 @@ class LastMigration {
|
||||
}
|
||||
|
||||
private static boolean includeSqlFile(String lowerFileName) {
|
||||
if (lowerFileName.startsWith("r") || lowerFileName.startsWith("i") || !lowerFileName.endsWith(SQL)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !lowerFileName.startsWith("r") && !lowerFileName.startsWith("i") && lowerFileName.endsWith(SQL);
|
||||
}
|
||||
|
||||
private static boolean includeModelFile(String lowerFileName) {
|
||||
|
||||
@@ -62,14 +62,14 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Used to check that indexes on foreign keys should be skipped as a unique index on the columns
|
||||
* already exists.
|
||||
*/
|
||||
protected IndexSet indexSet = new IndexSet();
|
||||
protected final IndexSet indexSet = new IndexSet();
|
||||
|
||||
/**
|
||||
* Used when unique constraints specifically for OneToOne can't be created normally (MsSqlServer).
|
||||
*/
|
||||
protected List<Column> externalUnique = new ArrayList<>();
|
||||
protected final List<Column> externalUnique = new ArrayList<>();
|
||||
|
||||
protected List<UniqueConstraint> externalCompoundUnique = new ArrayList<>();
|
||||
protected final List<UniqueConstraint> externalCompoundUnique = new ArrayList<>();
|
||||
|
||||
// counters used when constraint names are truncated due to maximum length
|
||||
// and these counters are used to keep the constraint name unique
|
||||
@@ -82,9 +82,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Base tables that have associated history tables that need their triggers/functions regenerated as
|
||||
* columns have been added, removed, included or excluded.
|
||||
*/
|
||||
protected Map<String, HistoryTableUpdate> regenerateHistoryTriggers = new LinkedHashMap<>();
|
||||
protected final Map<String, HistoryTableUpdate> regenerateHistoryTriggers = new LinkedHashMap<>();
|
||||
|
||||
private boolean strictMode;
|
||||
private final boolean strictMode;
|
||||
|
||||
private final HistorySupport historySupport;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (defaultValue == null) {
|
||||
handleStrictError(tableName, columnName);
|
||||
}
|
||||
before = Arrays.asList(platformDdl.getUpdateNullWithDefault());
|
||||
before = Collections.singletonList(platformDdl.getUpdateNullWithDefault());
|
||||
} else {
|
||||
before = getScriptsForPlatform(alter.getBefore(), platformDdl.getPlatform().getName());
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ public class CockroachDdl extends PlatformDdl {
|
||||
|
||||
public CockroachDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.historyDdl = new PostgresHistoryDdl();
|
||||
this.dropTableCascade = " cascade";
|
||||
this.columnSetType = "type ";
|
||||
this.alterTableIfExists = "if exists ";
|
||||
|
||||
+8
-11
@@ -29,11 +29,11 @@ public abstract class DbTriggerBasedHistoryDdl implements PlatformHistoryDdl {
|
||||
protected String viewSuffix;
|
||||
protected String historySuffix;
|
||||
|
||||
|
||||
protected String currentTimestamp = "now(6)";
|
||||
protected String sysPeriodType = "datetime(6)";
|
||||
protected String now = "now(6)";
|
||||
protected String sysPeriodEndValue = "now(6)";
|
||||
|
||||
public DbTriggerBasedHistoryDdl() {
|
||||
DbTriggerBasedHistoryDdl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -164,7 +164,7 @@ public abstract class DbTriggerBasedHistoryDdl implements PlatformHistoryDdl {
|
||||
protected void addSysPeriodColumns(DdlBuffer apply, String baseTableName, String whenCreatedColumn) throws IOException {
|
||||
|
||||
apply.append("alter table ").append(baseTableName).append(" add column ")
|
||||
.append(sysPeriodStart).append(" ").append(sysPeriodType).append(" default ").append(currentTimestamp).endOfStatement();
|
||||
.append(sysPeriodStart).append(" ").append(sysPeriodType).append(" default ").append(now).endOfStatement();
|
||||
apply.append("alter table ").append(baseTableName).append(" add column ")
|
||||
.append(sysPeriodEnd).append(" ").append(sysPeriodType).endOfStatement();
|
||||
|
||||
@@ -246,13 +246,12 @@ public abstract class DbTriggerBasedHistoryDdl implements PlatformHistoryDdl {
|
||||
|
||||
buffer.append(" insert into ").append(historyTable).append(" (").append(sysPeriodStart).append(",").append(sysPeriodEnd).append(",");
|
||||
appendColumnNames(buffer, columns, "");
|
||||
buffer.append(") values (OLD.").append(sysPeriodStart).append(", ").append(currentTimestamp).append(",");
|
||||
buffer.append(") values (OLD.").append(sysPeriodStart).append(", ").append(sysPeriodEndValue).append(",");
|
||||
appendColumnNames(buffer, columns, "OLD.");
|
||||
buffer.append(");").newLine();
|
||||
}
|
||||
|
||||
protected void appendColumnNames(DdlBuffer buffer, List<String> columns, String columnPrefix) throws IOException {
|
||||
|
||||
void appendColumnNames(DdlBuffer buffer, List<String> columns, String columnPrefix) throws IOException {
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (i > 0) {
|
||||
buffer.append(", ");
|
||||
@@ -265,8 +264,7 @@ public abstract class DbTriggerBasedHistoryDdl implements PlatformHistoryDdl {
|
||||
/**
|
||||
* Append a single column to the buffer if it is not null.
|
||||
*/
|
||||
protected void appendColumnName(DdlBuffer buffer, String prefix, String columnName) throws IOException {
|
||||
|
||||
void appendColumnName(DdlBuffer buffer, String prefix, String columnName) throws IOException {
|
||||
if (columnName != null) {
|
||||
buffer.append(prefix).append(columnName);
|
||||
}
|
||||
@@ -280,8 +278,7 @@ public abstract class DbTriggerBasedHistoryDdl implements PlatformHistoryDdl {
|
||||
* the column.
|
||||
* </p>
|
||||
*/
|
||||
protected List<String> columnNamesForApply(MTable table) {
|
||||
|
||||
List<String> columnNamesForApply(MTable table) {
|
||||
return table.allHistoryColumns(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,10 @@ public class H2HistoryDdl extends DbTriggerBasedHistoryDdl {
|
||||
|
||||
private static final String TRIGGER_CLASS = H2HistoryTrigger.class.getName();
|
||||
|
||||
public H2HistoryDdl() {
|
||||
H2HistoryDdl() {
|
||||
this.sysPeriodType = "timestamp";
|
||||
this.currentTimestamp = "now()";
|
||||
this.now = "now()";
|
||||
this.sysPeriodEndValue = "now()";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-3
@@ -11,13 +11,11 @@ import java.io.IOException;
|
||||
*/
|
||||
public class MySqlHistoryDdl extends DbTriggerBasedHistoryDdl {
|
||||
|
||||
|
||||
public MySqlHistoryDdl() {
|
||||
MySqlHistoryDdl() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropTriggers(DdlBuffer buffer, String baseTable) throws IOException {
|
||||
|
||||
buffer.append("drop trigger ").append(updateTriggerName(baseTable)).endOfStatement();
|
||||
buffer.append("drop trigger ").append(deleteTriggerName(baseTable)).endOfStatement();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebean.annotation.ConstraintMode;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
|
||||
public class NuoDbDdl extends PlatformDdl {
|
||||
|
||||
public NuoDbDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.historyDdl = new NuoDbHistoryDdl();
|
||||
this.identitySuffix = " generated by default as identity";
|
||||
this.dropConstraintIfExists = "drop constraint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendForeignKeyOnUpdate(StringBuilder buffer, ConstraintMode mode) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void appendForeignKeyOnDelete(StringBuilder buffer, ConstraintMode mode) {
|
||||
if (mode == ConstraintMode.RESTRICT) {
|
||||
// do nothing
|
||||
} else if (mode == ConstraintMode.SET_NULL) {
|
||||
// do nothing
|
||||
} else {
|
||||
super.appendForeignKeyOnDelete(buffer, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
|
||||
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* NuoDB history support using DB triggers to maintain a history table.
|
||||
*/
|
||||
public class NuoDbHistoryDdl extends DbTriggerBasedHistoryDdl {
|
||||
|
||||
NuoDbHistoryDdl() {
|
||||
this.now = "now()";
|
||||
this.sysPeriodEndValue = "NEW.sys_period_start";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropTriggers(DdlBuffer buffer, String baseTable) throws IOException {
|
||||
|
||||
buffer.append("drop trigger ").append(updateTriggerName(baseTable)).endOfStatement();
|
||||
buffer.append("drop trigger ").append(deleteTriggerName(baseTable)).endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createTriggers(DdlWrite writer, MTable table) throws IOException {
|
||||
|
||||
DbTriggerUpdate update = createDbTriggerUpdate(writer, table);
|
||||
|
||||
addBeforeUpdate(updateTriggerName(update.getBaseTable()), update);
|
||||
addBeforeDelete(deleteTriggerName(update.getBaseTable()), update);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateHistoryTriggers(DbTriggerUpdate update) throws IOException {
|
||||
|
||||
recreateHistoryView(update);
|
||||
|
||||
DdlBuffer buffer = update.historyTriggerBuffer();
|
||||
String baseTable = update.getBaseTable();
|
||||
|
||||
dropTriggers(buffer, baseTable);
|
||||
addBeforeUpdate(updateTriggerName(baseTable), update);
|
||||
addBeforeDelete(deleteTriggerName(baseTable), update);
|
||||
}
|
||||
|
||||
private void addBeforeUpdate(String triggerName, DbTriggerUpdate update) throws IOException {
|
||||
|
||||
DdlBuffer apply = update.historyTriggerBuffer();
|
||||
addTriggerStart(triggerName, update, apply, " before update for each row as ");
|
||||
apply.append(" NEW.sys_period_start = greatest(current_timestamp, date_add(OLD.sys_period_start, interval 1 microsecond))").endOfStatement();
|
||||
appendInsertIntoHistory(apply, update.getHistoryTable(), update.getColumns());
|
||||
addEndTrigger(apply);
|
||||
}
|
||||
|
||||
private void addBeforeDelete(String triggerName, DbTriggerUpdate update) throws IOException {
|
||||
|
||||
DdlBuffer apply = update.historyTriggerBuffer();
|
||||
addTriggerStart(triggerName, update, apply, " before delete for each row as");
|
||||
appendInsertIntoHistory(apply, update.getHistoryTable(), update.getColumns());
|
||||
addEndTrigger(apply);
|
||||
}
|
||||
|
||||
private void addTriggerStart(String triggerName, DbTriggerUpdate update, DdlBuffer apply, String s) throws IOException {
|
||||
apply
|
||||
.append("delimiter $$").newLine()
|
||||
.append("create or replace trigger ").append(triggerName).append(" for ").append(update.getBaseTable())
|
||||
.append(s).newLine();
|
||||
}
|
||||
|
||||
private void addEndTrigger(DdlBuffer apply) throws IOException {
|
||||
apply.append("end_trigger")
|
||||
.endOfStatement()
|
||||
.append("$$").newLine()
|
||||
.newLine();
|
||||
}
|
||||
|
||||
}
|
||||
+4
-4
@@ -12,9 +12,9 @@ import java.util.List;
|
||||
*/
|
||||
public class PostgresHistoryDdl extends DbTriggerBasedHistoryDdl {
|
||||
|
||||
|
||||
public PostgresHistoryDdl() {
|
||||
this.currentTimestamp = "current_timestamp";
|
||||
PostgresHistoryDdl() {
|
||||
this.now = "current_timestamp";
|
||||
this.sysPeriodEndValue = "current_timestamp";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ public class PostgresHistoryDdl extends DbTriggerBasedHistoryDdl {
|
||||
protected void addSysPeriodColumns(DdlBuffer apply, String baseTableName, String whenCreatedColumn) throws IOException {
|
||||
apply
|
||||
.append("alter table ").append(baseTableName)
|
||||
.append(" add column ").append(sysPeriod).append(" tstzrange not null default tstzrange(").append(currentTimestamp).append(", null)")
|
||||
.append(" add column ").append(sysPeriod).append(" tstzrange not null default tstzrange(").append(now).append(", null)")
|
||||
.endOfStatement();
|
||||
|
||||
if (whenCreatedColumn != null) {
|
||||
|
||||
@@ -150,7 +150,7 @@ public class CurrentModel {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (script.isInit() && ExtraDdlXmlReader.matchPlatform(server.getDatabasePlatform().getName(), script.getPlatforms())) {
|
||||
ddl.append(prefix + script.getName()).append('\n');
|
||||
ddl.append(prefix).append(script.getName()).append('\n');
|
||||
ddl.append(script.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebeaninternal.dbmigration.migration.DdlScript;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A column in the logical model.
|
||||
@@ -309,7 +310,7 @@ public class MColumn {
|
||||
}
|
||||
|
||||
protected static boolean different(String val1, String val2) {
|
||||
return (val1 == null) ? val2 != null : !val1.equals(val2);
|
||||
return !Objects.equals(val1, val2);
|
||||
}
|
||||
|
||||
private boolean hasValue(String val) {
|
||||
|
||||
@@ -769,7 +769,7 @@ public class MTable {
|
||||
nullableColumns.add(columnName);
|
||||
}
|
||||
}
|
||||
uniq.setNullableColumns(nullableColumns.toArray(new String[nullableColumns.size()]));
|
||||
uniq.setNullableColumns(nullableColumns.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -49,8 +49,7 @@ class ModelBuildIntersectionTable {
|
||||
|
||||
private void buildFkConstraints() {
|
||||
|
||||
PropertyForeignKey foreignKey = manyProp.getForeignKey();
|
||||
if (foreignKey == null || !foreignKey.isNoConstraint()) {
|
||||
if (manyProp.hasForeignKeyConstraint()) {
|
||||
ctx.fkeyBuilder(intersectionTable)
|
||||
.addForeignKey(manyProp.getBeanDescriptor(), intersectionTableJoin, true)
|
||||
.addForeignKey(manyProp.getTargetDescriptor(), tableJoin, false);
|
||||
|
||||
+11
-6
@@ -170,8 +170,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
List<MColumn> modelColumns = new ArrayList<>(columns.length);
|
||||
|
||||
PropertyForeignKey foreignKey = p.getForeignKey();
|
||||
|
||||
MCompoundForeignKey compoundKey = null;
|
||||
if (columns.length > 1) {
|
||||
// compound foreign key
|
||||
@@ -196,7 +194,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setDbMigrationInfos(p.getDbMigrationInfos());
|
||||
col.setDefaultValue(p.getDbColumnDefault());
|
||||
if (columns.length == 1) {
|
||||
if (p.hasForeignKey() && !importedProperty.getBeanDescriptor().suppressForeignKey()) {
|
||||
if (p.hasForeignKeyConstraint() && !importedProperty.getBeanDescriptor().suppressForeignKey()) {
|
||||
// single references column (put it on the column)
|
||||
String refTable = importedProperty.getBeanDescriptor().getBaseTable();
|
||||
if (refTable == null) {
|
||||
@@ -208,6 +206,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
if (p.hasForeignKeyIndex()) {
|
||||
col.setForeignKeyIndex(determineForeignKeyIndexName(col.getName()));
|
||||
}
|
||||
PropertyForeignKey foreignKey = p.getForeignKey();
|
||||
if (foreignKey != null) {
|
||||
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
|
||||
}
|
||||
@@ -256,9 +255,15 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
}
|
||||
TableJoin primaryKeyJoin = p.getBeanDescriptor().getPrimaryKeyJoin();
|
||||
if (primaryKeyJoin != null && !table.isPartitioned()) {
|
||||
TableJoinColumn[] columns = primaryKeyJoin.columns();
|
||||
col.setReferences(primaryKeyJoin.getTable() + "." + columns[0].getForeignDbColumn());
|
||||
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
|
||||
final PropertyForeignKey foreignKey = primaryKeyJoin.getForeignKey();
|
||||
if (foreignKey == null || !foreignKey.isNoConstraint()) {
|
||||
TableJoinColumn[] columns = primaryKeyJoin.columns();
|
||||
col.setReferences(primaryKeyJoin.getTable() + "." + columns[0].getForeignDbColumn());
|
||||
col.setForeignKeyName(determineForeignKeyConstraintName(col.getName()));
|
||||
if (foreignKey != null) {
|
||||
col.setForeignKeyModes(foreignKey.getOnDelete(), foreignKey.getOnUpdate());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
col.setDefaultValue(p.getDbColumnDefault());
|
||||
|
||||
@@ -181,7 +181,7 @@ public class DJsonService implements SpiJsonService {
|
||||
if (modifyAware) {
|
||||
return ((ModifyAwareList<T>) list).asSet();
|
||||
} else {
|
||||
return new LinkedHashSet<T>(list);
|
||||
return new LinkedHashSet<>(list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
*/
|
||||
public class AutoTuneCollection {
|
||||
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
final List<Entry> entries = new ArrayList<>();
|
||||
|
||||
public Entry add(ObjectGraphOrigin origin, OrmQueryDetail detail, String sourceQuery) {
|
||||
Entry entry = new Entry(origin, detail, sourceQuery);
|
||||
|
||||
@@ -149,7 +149,7 @@ public class AutoTuneDiffCollection {
|
||||
origin.setKey(point.getKey());
|
||||
origin.setBeanType(point.getBeanType());
|
||||
origin.setDetail(entry.getDetail().toString());
|
||||
origin.setCallStack(point.getCallStack().description("\n"));
|
||||
origin.setCallStack(point.getCallOrigin().getFullDescription());
|
||||
origin.setOriginal(query);
|
||||
|
||||
if (updateTuning) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebeaninternal.server.autotune.service;
|
||||
|
||||
import io.ebean.bean.CallStack;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.config.AutoTuneConfig;
|
||||
import io.ebean.config.AutoTuneMode;
|
||||
@@ -97,7 +97,7 @@ public class BaseQueryTuner {
|
||||
|
||||
if (!useTuning(query)) {
|
||||
if (profiling) {
|
||||
profiling(query, server.createCallStack());
|
||||
profiling(query, server.createCallOrigin());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -110,8 +110,8 @@ public class BaseQueryTuner {
|
||||
}
|
||||
|
||||
// create a query point to identify the query
|
||||
CallStack stack = server.createCallStack();
|
||||
ObjectGraphNode origin = query.setOrigin(stack);
|
||||
CallOrigin callOrigin = server.createCallOrigin();
|
||||
ObjectGraphNode origin = query.setOrigin(callOrigin);
|
||||
|
||||
if (profiling) {
|
||||
if (profilingListener.isProfileRequest(origin, query)) {
|
||||
@@ -154,10 +154,10 @@ public class BaseQueryTuner {
|
||||
}
|
||||
}
|
||||
|
||||
private void profiling(SpiQuery<?> query, CallStack stack) {
|
||||
private void profiling(SpiQuery<?> query, CallOrigin call) {
|
||||
|
||||
// create a query point to identify the query
|
||||
ObjectGraphNode origin = query.setOrigin(stack);
|
||||
ObjectGraphNode origin = query.setOrigin(call);
|
||||
if (profilingListener.isProfileRequest(origin, query)) {
|
||||
// collect more profiling based on profiling rate etc
|
||||
query.setProfilingListener(profilingListener);
|
||||
|
||||
@@ -13,6 +13,8 @@ public class CachedBeanDataToBean {
|
||||
public static void load(BeanDescriptor<?> desc, EntityBean bean, CachedBeanData cacheBeanData, PersistenceContext context) {
|
||||
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
// any future lazy loading skips L2 bean cache
|
||||
ebi.setLoadedFromCache(true);
|
||||
|
||||
BeanProperty idProperty = desc.getIdProperty();
|
||||
if (desc.getInheritInfo() != null) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiSqlBinding;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.lib.util.Str;
|
||||
import io.ebeaninternal.server.lib.Str;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
import io.ebeaninternal.server.util.BindParamsParser;
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Supports padding bind parameters for IN expressions.
|
||||
* <p>
|
||||
* We do this in order to get better hit ratio on DB query plans.
|
||||
* </p>
|
||||
*/
|
||||
public final class BindPadding {
|
||||
|
||||
/**
|
||||
* Pad out the Ids into common bucket sizes.
|
||||
*
|
||||
* @param idCollection The collection of Ids values being bound.
|
||||
*/
|
||||
public static void padIds(List<Object> idCollection) {
|
||||
|
||||
int extraIds = padding(idCollection.size());
|
||||
if (extraIds > 0) {
|
||||
// for performance make up the Id's to the batch size
|
||||
// so we get the same query (for Ebean and the db)
|
||||
Object firstId = idCollection.get(0);
|
||||
for (int i = 0; i < extraIds; i++) {
|
||||
// just add the first Id again
|
||||
idCollection.add(firstId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra padding on binding id's in order to get better hit ratio on DB prepared statements / query plans.
|
||||
*/
|
||||
static int padding(int size) {
|
||||
if (size == 1) {
|
||||
return 0;
|
||||
}
|
||||
if (size <= 5) {
|
||||
return 5 - size;
|
||||
}
|
||||
if (size <= 10) {
|
||||
return 10 - size;
|
||||
}
|
||||
if (size <= 20) {
|
||||
return 20 - size;
|
||||
}
|
||||
if (size <= 40) {
|
||||
return 40 - size;
|
||||
}
|
||||
if (size <= 50) {
|
||||
return 50 - size;
|
||||
}
|
||||
return size <= 100 ? 100 - size : 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallOrigin;
|
||||
|
||||
/**
|
||||
* Creates CallOrigin based on the stack trace.
|
||||
*/
|
||||
public interface CallOriginFactory {
|
||||
|
||||
/**
|
||||
* Create and return the CallStack given the stack trace elements.
|
||||
*/
|
||||
CallOrigin createCallOrigin();
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallStack;
|
||||
|
||||
/**
|
||||
* Creates CallStack based on the stack trace.
|
||||
*/
|
||||
public interface CallStackFactory {
|
||||
|
||||
/**
|
||||
* Create and return the CallStack given the stack trace elements.
|
||||
*/
|
||||
CallStack createCallStack();
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.Postgres8Platform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
@@ -108,6 +109,9 @@ public class DatabasePlatformFactory {
|
||||
if (dbName.equals("clickhouse")) {
|
||||
return new ClickHousePlatform();
|
||||
}
|
||||
if (dbName.equals("nuodb")) {
|
||||
return new NuoDbPlatform();
|
||||
}
|
||||
if (dbName.equals("sqlite")) {
|
||||
return new SQLitePlatform();
|
||||
}
|
||||
@@ -158,6 +162,8 @@ public class DatabasePlatformFactory {
|
||||
return new HsqldbPlatform();
|
||||
} else if (dbProductName.contains("postgres")) {
|
||||
return readPostgres(connection);
|
||||
} else if (dbProductName.contains("nuo")) {
|
||||
return new NuoDbPlatform();
|
||||
} else if (dbProductName.contains("sqlite")) {
|
||||
return new SQLitePlatform();
|
||||
} else if (dbProductName.contains("db2")) {
|
||||
@@ -177,7 +183,7 @@ public class DatabasePlatformFactory {
|
||||
/**
|
||||
* Use a select version() query as it could be Postgres or CockroachDB.
|
||||
*/
|
||||
private static PostgresPlatform readPostgres(Connection connection) {
|
||||
private static DatabasePlatform readPostgres(Connection connection) {
|
||||
// Postgres driver uses a hardcoded product name so use version() query
|
||||
PreparedStatement statement = null;
|
||||
ResultSet resultSet = null;
|
||||
|
||||
@@ -91,17 +91,13 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
if (map == null) {
|
||||
return schedulePool.schedule(c, delay, unit);
|
||||
} else {
|
||||
return schedulePool.schedule(new Callable<V>() {
|
||||
@Override
|
||||
public V call() throws Exception {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return c.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
return schedulePool.schedule(() -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return c.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
|
||||
}, delay, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
@@ -25,7 +26,7 @@ import java.util.List;
|
||||
/**
|
||||
* Helper to handle lazy loading and refreshing of beans.
|
||||
*/
|
||||
public class DefaultBeanLoader {
|
||||
class DefaultBeanLoader {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultBeanLoader.class);
|
||||
|
||||
@@ -33,63 +34,19 @@ public class DefaultBeanLoader {
|
||||
|
||||
private final boolean onIterateUseExtraTxn;
|
||||
|
||||
protected DefaultBeanLoader(DefaultServer server) {
|
||||
DefaultBeanLoader(DefaultServer server) {
|
||||
this.server = server;
|
||||
this.onIterateUseExtraTxn = server.getDatabasePlatform().useExtraTransactionOnIterateSecondaryQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a batch size that might be less than the requestedBatchSize.
|
||||
* <p>
|
||||
* This means we can have large and variable requestedBatchSizes.
|
||||
* </p>
|
||||
* <p>
|
||||
* We want to restrict the number of different batch sizes as we want to
|
||||
* re-use the query plan cache and get DB statement re-use.
|
||||
* </p>
|
||||
*/
|
||||
private int getBatchSize(int batchSize) {
|
||||
void loadMany(LoadManyRequest loadRequest) {
|
||||
|
||||
if (batchSize == 1) {
|
||||
// there is only one bean/collection to load
|
||||
return 1;
|
||||
}
|
||||
if (batchSize <= 5) {
|
||||
// anything less than 5 becomes 5
|
||||
return 5;
|
||||
}
|
||||
if (batchSize <= 10) {
|
||||
return 10;
|
||||
}
|
||||
if (batchSize <= 20) {
|
||||
return 20;
|
||||
}
|
||||
if (batchSize <= 50) {
|
||||
return 50;
|
||||
}
|
||||
if (batchSize <= 100) {
|
||||
return 100;
|
||||
}
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
public void refreshMany(EntityBean parentBean, String propertyName) {
|
||||
refreshMany(parentBean, propertyName, null);
|
||||
}
|
||||
|
||||
public void loadMany(LoadManyRequest loadRequest) {
|
||||
|
||||
List<BeanCollection<?>> batch = loadRequest.getBatch();
|
||||
|
||||
int batchSize = getBatchSize(batch.size());
|
||||
|
||||
SpiQuery<?> query = loadRequest.createQuery(server, batchSize);
|
||||
SpiQuery<?> query = loadRequest.createQuery(server);
|
||||
executeQuery(loadRequest, query);
|
||||
|
||||
loadRequest.postLoad();
|
||||
}
|
||||
|
||||
public void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
|
||||
EntityBean parentBean = bc.getOwnerBean();
|
||||
String propertyName = bc.getPropertyName();
|
||||
@@ -97,8 +54,8 @@ public class DefaultBeanLoader {
|
||||
loadManyInternal(parentBean, propertyName, null, false, onlyIds);
|
||||
}
|
||||
|
||||
public void refreshMany(EntityBean parentBean, String propertyName, Transaction t) {
|
||||
loadManyInternal(parentBean, propertyName, t, true, false);
|
||||
void refreshMany(EntityBean parentBean, String propertyName) {
|
||||
loadManyInternal(parentBean, propertyName, null, true, false);
|
||||
}
|
||||
|
||||
private void loadManyInternal(EntityBean parentBean, String propertyName, Transaction t, boolean refresh, boolean onlyIds) {
|
||||
@@ -147,8 +104,7 @@ public class DefaultBeanLoader {
|
||||
query.setLoadDescription("+lazy", null);
|
||||
}
|
||||
|
||||
String idProperty = parentDesc.getIdBinder().getIdProperty();
|
||||
query.select(idProperty);
|
||||
query.select(parentDesc.getIdBinder().getIdProperty());
|
||||
|
||||
if (onlyIds) {
|
||||
query.fetch(many.getName(), many.getTargetIdProperty());
|
||||
@@ -185,16 +141,14 @@ public class DefaultBeanLoader {
|
||||
/**
|
||||
* Load a batch of beans for +query or +lazy loading.
|
||||
*/
|
||||
public void loadBean(LoadBeanRequest loadRequest) {
|
||||
void loadBean(LoadBeanRequest loadRequest) {
|
||||
|
||||
List<EntityBeanIntercept> batch = loadRequest.getBatch();
|
||||
if (batch.isEmpty()) {
|
||||
throw new RuntimeException("Nothing in batch?");
|
||||
}
|
||||
|
||||
int batchSize = getBatchSize(batch.size());
|
||||
|
||||
List<Object> idList = loadRequest.getIdList(batchSize);
|
||||
List<Object> idList = loadRequest.getIdList();
|
||||
if (idList.isEmpty()) {
|
||||
// everything was loaded from cache
|
||||
return;
|
||||
@@ -202,6 +156,9 @@ public class DefaultBeanLoader {
|
||||
|
||||
SpiQuery<?> query = server.createQuery(loadRequest.getBeanType());
|
||||
loadRequest.configureQuery(query, idList);
|
||||
if (loadRequest.isLoadedFromCache()) {
|
||||
query.setBeanCacheMode(CacheMode.PUT);
|
||||
}
|
||||
|
||||
List<?> list = executeQuery(loadRequest, query);
|
||||
loadRequest.postLoad(list);
|
||||
@@ -228,7 +185,7 @@ public class DefaultBeanLoader {
|
||||
refreshBeanInternal(bean, SpiQuery.Mode.REFRESH_BEAN, -1);
|
||||
}
|
||||
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
void loadBean(EntityBeanIntercept ebi) {
|
||||
refreshBeanInternal(ebi.getOwner(), SpiQuery.Mode.LAZYLOAD_BEAN, -1);
|
||||
}
|
||||
|
||||
@@ -315,6 +272,5 @@ public class DefaultBeanLoader {
|
||||
}
|
||||
|
||||
desc.resetManyProperties(dbBean);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+6
-8
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.CallStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -7,7 +8,7 @@ import java.util.Arrays;
|
||||
/**
|
||||
* Default CallStackFactory where the Hash function for StackTraceElement includes the line number.
|
||||
*/
|
||||
public class DefaultCallStackFactory implements CallStackFactory {
|
||||
public class DefaultCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
|
||||
@@ -15,12 +16,12 @@ public class DefaultCallStackFactory implements CallStackFactory {
|
||||
|
||||
private final int maxCallStack;
|
||||
|
||||
DefaultCallStackFactory(int maxCallStack) {
|
||||
DefaultCallOriginFactory(int maxCallStack) {
|
||||
this.maxCallStack = maxCallStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallStack createCallStack() {
|
||||
public CallOrigin createCallOrigin() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
|
||||
// ignore the first 6 as they are always avaje stack elements
|
||||
@@ -55,13 +56,10 @@ public class DefaultCallStackFactory implements CallStackFactory {
|
||||
if (element.getClassName().startsWith(IO_EBEAN)) {
|
||||
return true;
|
||||
}
|
||||
if (element.getMethodName().startsWith("_ebean_")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return element.getMethodName().startsWith("_ebean_");
|
||||
}
|
||||
|
||||
private CallStack createCallStack(StackTraceElement[] finalTrace) {
|
||||
private CallOrigin createCallStack(StackTraceElement[] finalTrace) {
|
||||
return new CallStack(finalTrace, finalTrace[0].hashCode(), pathHash(finalTrace));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ import io.ebean.ValuePair;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.CallStack;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
@@ -102,7 +102,7 @@ import io.ebeaninternal.server.query.LimitOffsetPagedList;
|
||||
import io.ebeaninternal.server.query.QueryFutureIds;
|
||||
import io.ebeaninternal.server.query.QueryFutureList;
|
||||
import io.ebeaninternal.server.query.QueryFutureRowCount;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.querydefn.DefaultDtoQuery;
|
||||
import io.ebeaninternal.server.querydefn.DefaultOrmQuery;
|
||||
import io.ebeaninternal.server.querydefn.DefaultOrmUpdate;
|
||||
@@ -124,8 +124,10 @@ import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Clock;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
@@ -160,9 +162,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
/**
|
||||
* Clock to use for WhenModified and WhenCreated.
|
||||
*/
|
||||
private ClockService clockService;
|
||||
private final ClockService clockService;
|
||||
|
||||
private final CallStackFactory callStackFactory;
|
||||
private final CallOriginFactory callStackFactory;
|
||||
|
||||
/**
|
||||
* Handles the save, delete, updateSql CallableSql.
|
||||
@@ -310,12 +312,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
/**
|
||||
* Create the CallStackFactory depending if AutoTune is being used.
|
||||
*/
|
||||
private CallStackFactory initCallStackFactory(ServerConfig serverConfig) {
|
||||
private CallOriginFactory initCallStackFactory(ServerConfig serverConfig) {
|
||||
if (!serverConfig.getAutoTuneConfig().isActive()) {
|
||||
// use a common CallStack for performance as we don't care with no AutoTune
|
||||
return new NoopCallStackFactory();
|
||||
return new NoopCallOriginFactory();
|
||||
}
|
||||
return new DefaultCallStackFactory(serverConfig.getMaxCallStack());
|
||||
return new DefaultCallOriginFactory(serverConfig.getMaxCallStack());
|
||||
}
|
||||
|
||||
private void configureServerPlugins() {
|
||||
@@ -568,37 +570,31 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public void refreshMany(Object parentBean, String propertyName) {
|
||||
|
||||
beanLoader.refreshMany(checkEntityBean(parentBean), propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMany(LoadManyRequest loadRequest) {
|
||||
|
||||
beanLoader.loadMany(loadRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
|
||||
beanLoader.loadMany(bc, onlyIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(Object bean) {
|
||||
|
||||
beanLoader.refresh(checkEntityBean(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBean(LoadBeanRequest loadRequest) {
|
||||
|
||||
beanLoader.loadBean(loadRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
|
||||
beanLoader.loadBean(ebi);
|
||||
}
|
||||
|
||||
@@ -639,6 +635,36 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
externalModification(evt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate(Class<?>... types) {
|
||||
List<String> tableNames = new ArrayList<>();
|
||||
for (Class<?> type : types) {
|
||||
tableNames.add(getBeanDescriptor(type).getBaseTable());
|
||||
}
|
||||
truncate(tableNames.toArray(new String[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void truncate(String... tables) {
|
||||
try (Connection connection = getDataSource().getConnection()) {
|
||||
for (String table : tables) {
|
||||
executeSql(connection, databasePlatform.truncateStatement(table));
|
||||
}
|
||||
connection.commit();
|
||||
} catch(SQLException e) {
|
||||
throw new PersistenceException("Error executing truncate", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeSql(Connection connection, String sql) throws SQLException {
|
||||
if (sql != null) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
|
||||
transactionManager.log().sql().debug(sql);
|
||||
stmt.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the query execution statistics.
|
||||
*/
|
||||
@@ -658,7 +684,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createEntityBean(Class<T> type) {
|
||||
return getBeanDescriptor(type).createBean();
|
||||
}
|
||||
@@ -1104,7 +1129,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
// if determine cost and no origin for AutoTune
|
||||
if (query.getParentNode() == null) {
|
||||
query.setOrigin(createCallStack());
|
||||
query.setOrigin(createCallOrigin());
|
||||
}
|
||||
|
||||
return new OrmQueryRequest<>(this, queryEngine, query, (SpiTransaction) t);
|
||||
@@ -2278,8 +2303,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public CallStack createCallStack() {
|
||||
return callStackFactory.createCallStack();
|
||||
public CallOrigin createCallOrigin() {
|
||||
return callStackFactory.createCallOrigin();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@ class DefaultSlowQueryListener implements SlowQueryListener {
|
||||
String firstStack = "";
|
||||
ObjectGraphNode node = event.getOriginNode();
|
||||
if (node != null) {
|
||||
firstStack = node.getOriginQueryPoint().getFirstStackElement();
|
||||
firstStack = node.getOriginQueryPoint().getTopElement();
|
||||
}
|
||||
log.warn("Slow query warning - millis:{} rows:{} caller[{}] sql[{}]", event.getTimeMillis(), event.getRowCount(), firstStack, event.getSql());
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import io.ebeaninternal.server.dto.DtoColumn;
|
||||
import io.ebeaninternal.server.dto.DtoMappingRequest;
|
||||
import io.ebeaninternal.server.dto.DtoQueryPlan;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.RsetDataReader;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ import io.ebeaninternal.server.cluster.ClusterManager;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeaninternal.server.core.timezone.CloneDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.LocalDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.NoDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.SimpleDataTimeZone;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
@@ -65,7 +66,7 @@ import io.ebeaninternal.server.persist.platform.PostgresMultiValueBind;
|
||||
import io.ebeaninternal.server.query.CQueryEngine;
|
||||
import io.ebeaninternal.server.query.DefaultOrmQueryEngine;
|
||||
import io.ebeaninternal.server.query.DefaultRelationalQueryEngine;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditLogger;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditPrepare;
|
||||
import io.ebeaninternal.server.text.json.DJsonContext;
|
||||
@@ -163,7 +164,7 @@ public class InternalConfiguration {
|
||||
|
||||
private final SpiLogManager logManager;
|
||||
|
||||
public InternalConfiguration(boolean online, ClusterManager clusterManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
InternalConfiguration(boolean online, ClusterManager clusterManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses) {
|
||||
|
||||
this.online = online;
|
||||
@@ -237,7 +238,7 @@ public class InternalConfiguration {
|
||||
return docStoreFactory;
|
||||
}
|
||||
|
||||
public ClockService getClockService() {
|
||||
ClockService getClockService() {
|
||||
return clockService;
|
||||
}
|
||||
|
||||
@@ -292,7 +293,7 @@ public class InternalConfiguration {
|
||||
/**
|
||||
* Return the ReadAuditLogger implementation to use.
|
||||
*/
|
||||
public ReadAuditLogger getReadAuditLogger() {
|
||||
ReadAuditLogger getReadAuditLogger() {
|
||||
ReadAuditLogger found = bootupClasses.getReadAuditLogger();
|
||||
return plugin(found != null ? found : new DefaultReadAuditLogger());
|
||||
}
|
||||
@@ -300,7 +301,7 @@ public class InternalConfiguration {
|
||||
/**
|
||||
* Return the ReadAuditPrepare implementation to use.
|
||||
*/
|
||||
public ReadAuditPrepare getReadAuditPrepare() {
|
||||
ReadAuditPrepare getReadAuditPrepare() {
|
||||
ReadAuditPrepare found = bootupClasses.getReadAuditPrepare();
|
||||
return plugin(found != null ? found : new DefaultReadAuditPrepare());
|
||||
}
|
||||
@@ -328,35 +329,33 @@ public class InternalConfiguration {
|
||||
|
||||
private MultiValueBind createMultiValueBind(Platform platform) {
|
||||
// only Postgres at this stage
|
||||
switch (platform) {
|
||||
case POSTGRES:
|
||||
return new PostgresMultiValueBind();
|
||||
default:
|
||||
return new MultiValueBind();
|
||||
if (platform == Platform.POSTGRES) {
|
||||
return new PostgresMultiValueBind();
|
||||
}
|
||||
return new MultiValueBind();
|
||||
}
|
||||
|
||||
public SpiJsonContext createJsonContext(SpiEbeanServer server) {
|
||||
SpiJsonContext createJsonContext(SpiEbeanServer server) {
|
||||
return new DJsonContext(server, jsonFactory, typeManager);
|
||||
}
|
||||
|
||||
public AutoTuneService createAutoTuneService(SpiEbeanServer server) {
|
||||
AutoTuneService createAutoTuneService(SpiEbeanServer server) {
|
||||
return AutoTuneServiceFactory.create(server, serverConfig);
|
||||
}
|
||||
|
||||
public DtoQueryEngine createDtoQueryEngine() {
|
||||
DtoQueryEngine createDtoQueryEngine() {
|
||||
return new DtoQueryEngine(binder);
|
||||
}
|
||||
|
||||
public RelationalQueryEngine createRelationalQueryEngine() {
|
||||
RelationalQueryEngine createRelationalQueryEngine() {
|
||||
return new DefaultRelationalQueryEngine(binder, serverConfig.getDatabaseBooleanTrue(), serverConfig.getPlatformConfig().getDbUuid().useBinaryOptimized());
|
||||
}
|
||||
|
||||
public OrmQueryEngine createOrmQueryEngine() {
|
||||
OrmQueryEngine createOrmQueryEngine() {
|
||||
return new DefaultOrmQueryEngine(cQueryEngine, binder);
|
||||
}
|
||||
|
||||
public Persister createPersister(SpiEbeanServer server) {
|
||||
Persister createPersister(SpiEbeanServer server) {
|
||||
return new DefaultPersister(server, binder, beanDescriptorManager);
|
||||
}
|
||||
|
||||
@@ -368,6 +367,10 @@ public class InternalConfiguration {
|
||||
return bootupClasses;
|
||||
}
|
||||
|
||||
private Platform getPlatform() {
|
||||
return getDatabasePlatform().getPlatform();
|
||||
}
|
||||
|
||||
public DatabasePlatform getDatabasePlatform() {
|
||||
return serverConfig.getDatabasePlatform();
|
||||
}
|
||||
@@ -384,7 +387,7 @@ public class InternalConfiguration {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public BeanDescriptorManager getBeanDescriptorManager() {
|
||||
BeanDescriptorManager getBeanDescriptorManager() {
|
||||
return beanDescriptorManager;
|
||||
}
|
||||
|
||||
@@ -400,7 +403,7 @@ public class InternalConfiguration {
|
||||
return deployUtil;
|
||||
}
|
||||
|
||||
public CQueryEngine getCQueryEngine() {
|
||||
CQueryEngine getCQueryEngine() {
|
||||
return cQueryEngine;
|
||||
}
|
||||
|
||||
@@ -416,14 +419,14 @@ public class InternalConfiguration {
|
||||
/**
|
||||
* Create the DocStoreIntegration components for the given server.
|
||||
*/
|
||||
public DocStoreIntegration createDocStoreIntegration(SpiServer server) {
|
||||
DocStoreIntegration createDocStoreIntegration(SpiServer server) {
|
||||
return plugin(docStoreFactory.create(server));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the TransactionManager taking into account autoCommit mode.
|
||||
*/
|
||||
public TransactionManager createTransactionManager(DocStoreUpdateProcessor indexUpdateProcessor) {
|
||||
TransactionManager createTransactionManager(DocStoreUpdateProcessor indexUpdateProcessor) {
|
||||
|
||||
TransactionScopeManager scopeManager = createTransactionScopeManager();
|
||||
boolean notifyL2CacheInForeground = cacheManager.isLocalL2Caching() || serverConfig.isNotifyL2CacheInForeground();
|
||||
@@ -498,9 +501,9 @@ public class InternalConfiguration {
|
||||
}
|
||||
if (externalTransactionManager != null) {
|
||||
logger.info("Using Transaction Manager [" + externalTransactionManager.getClass() + "]");
|
||||
return new ExternalTransactionScopeManager(serverConfig.getName(), externalTransactionManager);
|
||||
return new ExternalTransactionScopeManager(externalTransactionManager);
|
||||
} else {
|
||||
return new DefaultTransactionScopeManager(serverConfig.getName());
|
||||
return new DefaultTransactionScopeManager();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,9 +514,12 @@ public class InternalConfiguration {
|
||||
|
||||
String tz = serverConfig.getDataTimeZone();
|
||||
if (tz == null) {
|
||||
if (getPlatform() == Platform.MYSQL) {
|
||||
return new LocalDataTimeZone();
|
||||
}
|
||||
return new NoDataTimeZone();
|
||||
}
|
||||
if (getDatabasePlatform().getPlatform() == Platform.ORACLE) {
|
||||
if (getPlatform() == Platform.ORACLE) {
|
||||
return new CloneDataTimeZone(tz);
|
||||
} else {
|
||||
return new SimpleDataTimeZone(tz);
|
||||
@@ -561,11 +567,11 @@ public class InternalConfiguration {
|
||||
return multiValueBind;
|
||||
}
|
||||
|
||||
public DtoBeanManager getDtoBeanManager() {
|
||||
DtoBeanManager getDtoBeanManager() {
|
||||
return dtoBeanManager;
|
||||
}
|
||||
|
||||
public SpiLogManager getLogManager() {
|
||||
SpiLogManager getLogManager() {
|
||||
return logManager;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user