mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
80
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec016cab17 | ||
|
|
7c28f01923 | ||
|
|
54da22eee6 | ||
|
|
6772b6e87e | ||
|
|
9856ebd540 | ||
|
|
f96ac6e6fe | ||
|
|
4c5618b04b | ||
|
|
a77de9e5e6 | ||
|
|
da29330a2a | ||
|
|
d0f9d4a9a6 | ||
|
|
61ee67ee41 | ||
|
|
3117acd2d7 | ||
|
|
4cee41d8d6 | ||
|
|
f4a58938bd | ||
|
|
4ce84f694f | ||
|
|
8eb248b966 | ||
|
|
c294d8e568 | ||
|
|
e923316ce9 | ||
|
|
f611068a03 | ||
|
|
dd880ac09b | ||
|
|
dbe24a4041 | ||
|
|
1f32dc2dc5 | ||
|
|
b2ce9db8a8 | ||
|
|
a626690918 | ||
|
|
0d511d51a6 | ||
|
|
854f467504 | ||
|
|
d3cc393edc | ||
|
|
002014f930 | ||
|
|
c8d352b0a8 | ||
|
|
3796f2b267 | ||
|
|
4ef5abceca | ||
|
|
4eda4201de | ||
|
|
933aa30149 | ||
|
|
0c80b3078a | ||
|
|
7317847aa7 | ||
|
|
444644f759 | ||
|
|
f704da641d | ||
|
|
a1d2f4c1af | ||
|
|
b7469da5b1 | ||
|
|
2897968a54 | ||
|
|
6360fad701 | ||
|
|
dbc97aa28c | ||
|
|
a231c136a9 | ||
|
|
c6487e56cf | ||
|
|
dac0a97a3f | ||
|
|
ff0274f72c | ||
|
|
ddee202bcc | ||
|
|
e1522a4a68 | ||
|
|
7bc6170587 | ||
|
|
0322c19261 | ||
|
|
18ae0a7833 | ||
|
|
e99db44ddf | ||
|
|
361de9ea99 | ||
|
|
99732b30b1 | ||
|
|
dd5e5819b8 | ||
|
|
b4330679b8 | ||
|
|
59447ad261 | ||
|
|
3bd20a424a | ||
|
|
4ac3a8d1ad | ||
|
|
5a8f8b3a83 | ||
|
|
7c01cec466 | ||
|
|
30ad4260f0 | ||
|
|
ab421d6f2b | ||
|
|
0b807addc7 | ||
|
|
bb03ef5693 | ||
|
|
248a7b1062 | ||
|
|
9da28262b4 | ||
|
|
fc8dd18fd1 | ||
|
|
70ba658442 | ||
|
|
70b730657f | ||
|
|
bf3cb7e2e2 | ||
|
|
c2708ecc76 | ||
|
|
896aba3053 | ||
|
|
f78b602a90 | ||
|
|
306c1b5cf6 | ||
|
|
cdf2718ca9 | ||
|
|
967ca0c9f3 | ||
|
|
607acb1b4e | ||
|
|
5f923945e9 | ||
|
|
11fbe8bf5b |
@@ -4,12 +4,12 @@
|
||||
<parent>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>java8-oss</artifactId>
|
||||
<version>2.1</version>
|
||||
<version>2.2</version>
|
||||
</parent>
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.3.4</version>
|
||||
<version>12.3.9</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-12.3.4</tag>
|
||||
<tag>ebean-12.3.9</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -63,8 +63,8 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>config</artifactId>
|
||||
<version>1.2</version>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -87,7 +87,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>6.12</version>
|
||||
<version>6.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -126,14 +126,14 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-databind.version}</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope to read validation annotations Size etc -->
|
||||
@@ -141,21 +141,21 @@
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>1.1.0.Final</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>2.9.7</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope to compile with java 11 -->
|
||||
@@ -170,7 +170,7 @@
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>javax.annotation-api</artifactId>
|
||||
<version>1.3.2</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope for Postgres JSON/JSONB support -->
|
||||
@@ -178,7 +178,7 @@
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.10</version>
|
||||
<scope>provided</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test scope -->
|
||||
@@ -299,7 +299,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.3.4</version>
|
||||
<version>12.3.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Optional;
|
||||
*
|
||||
* public class CustomerFinder extends BeanFinder<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
* @Inject
|
||||
* public CustomerFinder(Database database) {
|
||||
* super(Customer.class, database);
|
||||
* }
|
||||
|
||||
@@ -9,10 +9,10 @@ import java.util.Collection;
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Repository
|
||||
* @Repository
|
||||
* public class CustomerRepository extends BeanRepository<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
* @Inject
|
||||
* public CustomerRepository(Database server) {
|
||||
* super(Customer.class, server);
|
||||
* }
|
||||
|
||||
@@ -60,7 +60,9 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public class DB {
|
||||
public final class DB {
|
||||
|
||||
private static final DbContext context = DbContext.getInstance();
|
||||
|
||||
/**
|
||||
* Hide constructor.
|
||||
@@ -72,7 +74,7 @@ public class DB {
|
||||
* Return the default database.
|
||||
*/
|
||||
public static Database getDefault() {
|
||||
return Ebean.getDefaultServer();
|
||||
return context.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,26 +83,9 @@ public class DB {
|
||||
* @param name The name of the database
|
||||
*/
|
||||
public static Database byName(String name) {
|
||||
return Ebean.getServer(name);
|
||||
return context.get(name);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Register the server with this Ebean singleton. Specify if the registered
|
||||
// * server is the primary/default database.
|
||||
// */
|
||||
// public static void register(EbeanServer server, boolean defaultServer) {
|
||||
// serverMgr.register(server, defaultServer);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Backdoor for registering a mock implementation of EbeanServer as the default database.
|
||||
// */
|
||||
// protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
|
||||
// EbeanServer originalPrimaryServer = serverMgr.defaultServer;
|
||||
// serverMgr.registerWithName(name, server, defaultServer);
|
||||
// return originalPrimaryServer;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the ScriptRunner for the default database.
|
||||
* <p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
@@ -132,6 +133,25 @@ public interface Database {
|
||||
*/
|
||||
MetaInfoManager getMetaInfoManager();
|
||||
|
||||
/**
|
||||
* Return the platform used for this database instance.
|
||||
* <p>
|
||||
* Note many platforms have multiple specific platform types so often we want to
|
||||
* get the base platform via {@link Platform#base()}.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Platform platform = database.getPlatform().base();
|
||||
* if (platform == Platform.MYSQL) {
|
||||
* // do MySql specific function
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return platform for this database instance
|
||||
*/
|
||||
Platform getPlatform();
|
||||
|
||||
/**
|
||||
* Return the extended API intended for use by plugins.
|
||||
*/
|
||||
@@ -861,7 +881,7 @@ public interface Database {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.config.BeanNotEnhancedException;
|
||||
import io.ebean.datasource.DataSourceConfigurationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Holds Database instances.
|
||||
*/
|
||||
final class DbContext {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DbContext.class);
|
||||
|
||||
static {
|
||||
EbeanVersion.getVersion();
|
||||
}
|
||||
|
||||
private static final DbContext INSTANCE = new DbContext();
|
||||
|
||||
/**
|
||||
* Cache for fast concurrent read access.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, Database> concMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache for synchronized read, creation and put. Protected by the monitor object.
|
||||
*/
|
||||
private final HashMap<String, Database> syncMap = new HashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* The 'default' Database.
|
||||
*/
|
||||
private Database defaultDatabase;
|
||||
|
||||
private DbContext() {
|
||||
try {
|
||||
if (!DbPrimary.isSkip()) {
|
||||
// look to see if there is a default server defined
|
||||
String defaultName = DbPrimary.getDefaultServerName();
|
||||
logger.debug("defaultName:{}", defaultName);
|
||||
if (defaultName != null && !defaultName.trim().isEmpty()) {
|
||||
defaultDatabase = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
} catch (BeanNotEnhancedException e) {
|
||||
throw e;
|
||||
|
||||
} catch (DataSourceConfigurationException e) {
|
||||
String msg = "Configuration error creating DataSource for the default Database." +
|
||||
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
|
||||
" See https://ebean.io/docs/trouble-shooting#datasource";
|
||||
throw new DataSourceConfigurationException(msg, e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error trying to create the default Database", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the shared singleton instance.
|
||||
*/
|
||||
static DbContext getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default database.
|
||||
*/
|
||||
Database getDefault() {
|
||||
if (defaultDatabase == null) {
|
||||
String msg = "The default Database has not been defined?";
|
||||
msg += " This is normally set via the ebean.datasource.default property.";
|
||||
msg += " Otherwise it should be registered programmatically via registerServer()";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return defaultDatabase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database by name.
|
||||
*/
|
||||
Database get(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return defaultDatabase;
|
||||
}
|
||||
// non-synchronized read
|
||||
Database server = concMap.get(name);
|
||||
if (server != null) {
|
||||
return server;
|
||||
}
|
||||
// synchronized read, create and put
|
||||
return getWithCreate(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronized read, create and put of Databases.
|
||||
*/
|
||||
private Database getWithCreate(String name) {
|
||||
synchronized (monitor) {
|
||||
Database server = syncMap.get(name);
|
||||
if (server == null) {
|
||||
// register when creating server this way
|
||||
server = EbeanServerFactory.create(name);
|
||||
register(server, false);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a server so we can get it by its name.
|
||||
*/
|
||||
void register(Database server, boolean isDefault) {
|
||||
registerWithName(server.getName(), server, isDefault);
|
||||
}
|
||||
|
||||
private void registerWithName(String name, Database server, boolean isDefault) {
|
||||
synchronized (monitor) {
|
||||
concMap.put(name, server);
|
||||
syncMap.put(name, server);
|
||||
if (isDefault) {
|
||||
defaultDatabase = server;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Database mock(String name, Database server, boolean defaultServer) {
|
||||
Database originalPrimaryServer = this.defaultDatabase;
|
||||
registerWithName(name, server, defaultServer);
|
||||
return originalPrimaryServer;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import java.util.Properties;
|
||||
* <p/>
|
||||
* Intended for internal use as part of bootup, construction, registration of the default database.
|
||||
*/
|
||||
class PrimaryServer {
|
||||
class DbPrimary {
|
||||
|
||||
private static String defaultServerName;
|
||||
|
||||
@@ -19,7 +19,7 @@ class PrimaryServer {
|
||||
* Set whether to skip automatically creating the primary database.
|
||||
*/
|
||||
static synchronized void setSkip(boolean skip) {
|
||||
PrimaryServer.skip = skip;
|
||||
DbPrimary.skip = skip;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -149,7 +149,7 @@ public interface DocumentStore {
|
||||
* .setUseDocStore(true)
|
||||
* .where()... // perhaps add predicates
|
||||
* .findEachWhile(new Predicate<Order>() {
|
||||
* @Override
|
||||
* @Override
|
||||
* public void accept(Order bean) {
|
||||
* // process the bean
|
||||
*
|
||||
|
||||
@@ -2,26 +2,19 @@ package io.ebean;
|
||||
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.config.BeanNotEnhancedException;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.datasource.DataSourceConfigurationException;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.json.JsonContext;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to use <code>io.ebean.DB</code>.
|
||||
@@ -34,123 +27,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ebean {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
|
||||
|
||||
static {
|
||||
EbeanVersion.getVersion(); // initialises the version class and logs the version.
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages creation and cache of Databases.
|
||||
*/
|
||||
private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager();
|
||||
|
||||
/**
|
||||
* Helper class for managing fast and safe access and creation of Databases.
|
||||
*/
|
||||
private static final class ServerManager {
|
||||
|
||||
/**
|
||||
* Cache for fast concurrent read access.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, EbeanServer> concMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache for synchronized read, creation and put. Protected by the monitor object.
|
||||
*/
|
||||
private final HashMap<String, EbeanServer> syncMap = new HashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* The 'default' Database.
|
||||
*/
|
||||
private EbeanServer defaultServer;
|
||||
|
||||
private ServerManager() {
|
||||
|
||||
try {
|
||||
if (!PrimaryServer.isSkip()) {
|
||||
// look to see if there is a default server defined
|
||||
String defaultName = PrimaryServer.getDefaultServerName();
|
||||
logger.debug("defaultName:{}", defaultName);
|
||||
if (defaultName != null && !defaultName.trim().isEmpty()) {
|
||||
defaultServer = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
} catch (BeanNotEnhancedException e) {
|
||||
throw e;
|
||||
|
||||
} catch (DataSourceConfigurationException e) {
|
||||
String msg = "Configuration error creating DataSource for the default Database." +
|
||||
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
|
||||
" See https://ebean.io/docs/trouble-shooting#datasource";
|
||||
throw new DataSourceConfigurationException(msg, e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error trying to create the default Database", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private EbeanServer getDefaultServer() {
|
||||
if (defaultServer == null) {
|
||||
String msg = "The default Database has not been defined?";
|
||||
msg += " This is normally set via the ebean.datasource.default property.";
|
||||
msg += " Otherwise it should be registered programmatically via registerServer()";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return defaultServer;
|
||||
}
|
||||
|
||||
private EbeanServer get(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return defaultServer;
|
||||
}
|
||||
// non-synchronized read
|
||||
EbeanServer server = concMap.get(name);
|
||||
if (server != null) {
|
||||
return server;
|
||||
}
|
||||
// synchronized read, create and put
|
||||
return getWithCreate(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronized read, create and put of Databases.
|
||||
*/
|
||||
private EbeanServer getWithCreate(String name) {
|
||||
|
||||
synchronized (monitor) {
|
||||
|
||||
EbeanServer server = syncMap.get(name);
|
||||
if (server == null) {
|
||||
// register when creating server this way
|
||||
server = EbeanServerFactory.create(name);
|
||||
register(server, false);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a server so we can get it by its name.
|
||||
*/
|
||||
private void register(EbeanServer server, boolean isDefaultServer) {
|
||||
registerWithName(server.getName(), server, isDefaultServer);
|
||||
}
|
||||
|
||||
private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
|
||||
synchronized (monitor) {
|
||||
concMap.put(name, server);
|
||||
syncMap.put(name, server);
|
||||
if (isDefaultServer) {
|
||||
defaultServer = server;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
private static final DbContext context = DbContext.getInstance();
|
||||
|
||||
private Ebean() {
|
||||
}
|
||||
@@ -174,7 +52,7 @@ public final class Ebean {
|
||||
* @param name the name of the server, can use null for the 'default server'
|
||||
*/
|
||||
public static EbeanServer getServer(String name) {
|
||||
return serverMgr.get(name);
|
||||
return (EbeanServer)context.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,7 +62,27 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static EbeanServer getDefaultServer() {
|
||||
return serverMgr.getDefaultServer();
|
||||
return (EbeanServer)context.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the server with this Ebean singleton. Specify if the registered
|
||||
* server is the primary/default database.
|
||||
*/
|
||||
@Deprecated
|
||||
public static void register(EbeanServer server, boolean defaultServer) {
|
||||
context.register(server, defaultServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backdoor for registering a mock implementation of EbeanServer as the default database.
|
||||
*/
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
|
||||
return (EbeanServer)context.mock(name, server, defaultServer);
|
||||
}
|
||||
|
||||
private static Database getDefault() {
|
||||
return context.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,24 +103,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static ExpressionFactory getExpressionFactory() {
|
||||
return serverMgr.getDefaultServer().getExpressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the server with this Ebean singleton. Specify if the registered
|
||||
* server is the primary/default database.
|
||||
*/
|
||||
public static void register(EbeanServer server, boolean defaultServer) {
|
||||
serverMgr.register(server, defaultServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backdoor for registering a mock implementation of EbeanServer as the default database.
|
||||
*/
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
|
||||
EbeanServer originalPrimaryServer = serverMgr.defaultServer;
|
||||
serverMgr.registerWithName(name, server, defaultServer);
|
||||
return originalPrimaryServer;
|
||||
return getDefault().getExpressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +119,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Object nextId(Class<?> beanType) {
|
||||
return serverMgr.getDefaultServer().nextId(beanType);
|
||||
return getDefault().nextId(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,7 +165,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Transaction beginTransaction() {
|
||||
return serverMgr.getDefaultServer().beginTransaction();
|
||||
return getDefault().beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,7 +174,7 @@ public final class Ebean {
|
||||
* @param isolation the Transaction isolation level
|
||||
*/
|
||||
public static Transaction beginTransaction(TxIsolation isolation) {
|
||||
return serverMgr.getDefaultServer().beginTransaction(isolation);
|
||||
return getDefault().beginTransaction(isolation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,7 +227,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Transaction beginTransaction(TxScope scope) {
|
||||
return serverMgr.getDefaultServer().beginTransaction(scope);
|
||||
return getDefault().beginTransaction(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,7 +235,7 @@ public final class Ebean {
|
||||
* in scope.
|
||||
*/
|
||||
public static Transaction currentTransaction() {
|
||||
return serverMgr.getDefaultServer().currentTransaction();
|
||||
return getDefault().currentTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -384,21 +265,21 @@ public final class Ebean {
|
||||
* @throws PersistenceException if there is no currently active transaction
|
||||
*/
|
||||
public static void register(TransactionCallback transactionCallback) throws PersistenceException {
|
||||
serverMgr.getDefaultServer().register(transactionCallback);
|
||||
getDefault().register(transactionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the current transaction.
|
||||
*/
|
||||
public static void commitTransaction() {
|
||||
serverMgr.getDefaultServer().commitTransaction();
|
||||
getDefault().commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the current transaction.
|
||||
*/
|
||||
public static void rollbackTransaction() {
|
||||
serverMgr.getDefaultServer().rollbackTransaction();
|
||||
getDefault().rollbackTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,14 +307,14 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void endTransaction() {
|
||||
serverMgr.getDefaultServer().endTransaction();
|
||||
getDefault().endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current transaction as rollback only.
|
||||
*/
|
||||
public static void setRollbackOnly() {
|
||||
serverMgr.getDefaultServer().currentTransaction().setRollbackOnly();
|
||||
getDefault().currentTransaction().setRollbackOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,7 +325,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Map<String, ValuePair> diff(Object a, Object b) {
|
||||
return serverMgr.getDefaultServer().diff(a, b);
|
||||
return getDefault().diff(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,7 +346,7 @@ public final class Ebean {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -478,7 +359,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void save(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().save(bean);
|
||||
getDefault().save(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,14 +367,14 @@ public final class Ebean {
|
||||
* want to explicitly insert it.
|
||||
*/
|
||||
public static void insert(Object bean) {
|
||||
serverMgr.getDefaultServer().insert(bean);
|
||||
getDefault().insert(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a collection of beans.
|
||||
*/
|
||||
public static void insertAll(Collection<?> beans) {
|
||||
serverMgr.getDefaultServer().insertAll(beans);
|
||||
getDefault().insertAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -516,7 +397,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void markAsDirty(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().markAsDirty(bean);
|
||||
getDefault().markAsDirty(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -531,16 +412,6 @@ public final class Ebean {
|
||||
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
|
||||
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
|
||||
* OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
|
||||
* that are in the database but are not in the collection are deleted.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>{@link ServerConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
|
||||
* controls if only the changed properties are included in the update or if all the loaded
|
||||
* properties are included instead.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // A 'stateless update' example
|
||||
@@ -553,14 +424,14 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void update(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().update(bean);
|
||||
getDefault().update(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the beans in the collection.
|
||||
*/
|
||||
public static void updateAll(Collection<?> beans) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().updateAll(beans);
|
||||
getDefault().updateAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,7 +440,7 @@ public final class Ebean {
|
||||
* @param bean The bean to merge
|
||||
*/
|
||||
public static void merge(Object bean) {
|
||||
serverMgr.getDefaultServer().merge(bean);
|
||||
getDefault().merge(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -579,14 +450,14 @@ public final class Ebean {
|
||||
* @param options The options to control the merge
|
||||
*/
|
||||
public static void merge(Object bean, MergeOptions options) {
|
||||
serverMgr.getDefaultServer().merge(bean, options);
|
||||
getDefault().merge(bean, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from a Collection.
|
||||
*/
|
||||
public static int saveAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().saveAll(beans);
|
||||
return getDefault().saveAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -637,7 +508,7 @@ public final class Ebean {
|
||||
*/
|
||||
@Nonnull
|
||||
public static Set<Property> checkUniqueness(Object bean) {
|
||||
return serverMgr.getDefaultServer().checkUniqueness(bean);
|
||||
return getDefault().checkUniqueness(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -645,7 +516,7 @@ public final class Ebean {
|
||||
*/
|
||||
@Nonnull
|
||||
public static Set<Property> checkUniqueness(Object bean, Transaction transaction) {
|
||||
return serverMgr.getDefaultServer().checkUniqueness(bean, transaction);
|
||||
return getDefault().checkUniqueness(bean, transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -668,56 +539,56 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static boolean delete(Object bean) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().delete(bean);
|
||||
return getDefault().delete(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean in permanent fashion (will not use soft delete).
|
||||
*/
|
||||
public static boolean deletePermanent(Object bean) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deletePermanent(bean);
|
||||
return getDefault().deletePermanent(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
*/
|
||||
public static int delete(Class<?> beanType, Object id) {
|
||||
return serverMgr.getDefaultServer().delete(beanType, id);
|
||||
return getDefault().delete(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete permanent the bean given its type and id.
|
||||
*/
|
||||
public static int deletePermanent(Class<?> beanType, Object id) {
|
||||
return serverMgr.getDefaultServer().deletePermanent(beanType, id);
|
||||
return getDefault().deletePermanent(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values.
|
||||
*/
|
||||
public static int deleteAll(Class<?> beanType, Collection<?> ids) {
|
||||
return serverMgr.getDefaultServer().deleteAll(beanType, ids);
|
||||
return getDefault().deleteAll(beanType, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete permanent several beans given their type and id values.
|
||||
*/
|
||||
public static int deleteAllPermanent(Class<?> beanType, Collection<?> ids) {
|
||||
return serverMgr.getDefaultServer().deleteAllPermanent(beanType, ids);
|
||||
return getDefault().deleteAllPermanent(beanType, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans in the Collection.
|
||||
*/
|
||||
public static int deleteAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAll(beans);
|
||||
return getDefault().deleteAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete permanent all the beans in the Collection (will not use soft delete).
|
||||
*/
|
||||
public static int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAllPermanent(beans);
|
||||
return getDefault().deleteAllPermanent(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -728,7 +599,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void refresh(Object bean) {
|
||||
serverMgr.getDefaultServer().refresh(bean);
|
||||
getDefault().refresh(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -746,7 +617,7 @@ public final class Ebean {
|
||||
* @param manyPropertyName the property name of the List Set or Map to refresh.
|
||||
*/
|
||||
public static void refreshMany(Object bean, String manyPropertyName) {
|
||||
serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
|
||||
getDefault().refreshMany(bean, manyPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -771,7 +642,7 @@ public final class Ebean {
|
||||
* @param id the id value
|
||||
*/
|
||||
public static <T> T getReference(Class<T> beanType, Object id) {
|
||||
return serverMgr.getDefaultServer().getReference(beanType, id);
|
||||
return getDefault().getReference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -814,7 +685,7 @@ public final class Ebean {
|
||||
* @param sortByClause the properties to sort the list by
|
||||
*/
|
||||
public static <T> void sort(List<T> list, String sortByClause) {
|
||||
serverMgr.getDefaultServer().sort(list, sortByClause);
|
||||
getDefault().sort(list, sortByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -864,7 +735,7 @@ public final class Ebean {
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T find(Class<T> beanType, Object id) {
|
||||
return serverMgr.getDefaultServer().find(beanType, id);
|
||||
return getDefault().find(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -879,7 +750,7 @@ public final class Ebean {
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlQuery createSqlQuery(String sql) {
|
||||
return serverMgr.getDefaultServer().sqlQuery(sql);
|
||||
return getDefault().sqlQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -894,7 +765,7 @@ public final class Ebean {
|
||||
*/
|
||||
@Deprecated
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return serverMgr.getDefaultServer().sqlUpdate(sql);
|
||||
return getDefault().sqlUpdate(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -903,7 +774,7 @@ public final class Ebean {
|
||||
* @see CallableSql
|
||||
*/
|
||||
public static CallableSql createCallableSql(String sql) {
|
||||
return serverMgr.getDefaultServer().createCallableSql(sql);
|
||||
return getDefault().createCallableSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -935,16 +806,14 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
|
||||
|
||||
return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate);
|
||||
return getDefault().createUpdate(beanType, ormUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CsvReader for a given beanType.
|
||||
*/
|
||||
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getDefaultServer().createCsvReader(beanType);
|
||||
return getDefault().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,7 +828,7 @@ public final class Ebean {
|
||||
* @return The query
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
return getDefault().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -982,8 +851,7 @@ public final class Ebean {
|
||||
* @return A ORM Query object for this beanType
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getDefaultServer().createQuery(beanType);
|
||||
return getDefault().createQuery(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1020,8 +888,7 @@ public final class Ebean {
|
||||
* @return The query with expressions defined as per the parsed query statement
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType, String eql) {
|
||||
|
||||
return serverMgr.getDefaultServer().createQuery(beanType, eql);
|
||||
return getDefault().createQuery(beanType, eql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1036,8 +903,7 @@ public final class Ebean {
|
||||
* @return A ORM Query object for this beanType
|
||||
*/
|
||||
public static <T> Query<T> find(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getDefaultServer().find(beanType);
|
||||
return getDefault().find(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1060,7 +926,7 @@ public final class Ebean {
|
||||
* @return The query to set parameters and execute
|
||||
*/
|
||||
public static <T> Query<T> findNative(Class<T> beanType, String nativeSql) {
|
||||
return serverMgr.getDefaultServer().findNative(beanType, nativeSql);
|
||||
return getDefault().findNative(beanType, nativeSql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1075,7 +941,7 @@ public final class Ebean {
|
||||
* @param <T> The type of the DTO bean.
|
||||
*/
|
||||
public static <T> DtoQuery<T> findDto(Class<T> dtoType, String sql) {
|
||||
return serverMgr.getDefaultServer().findDto(dtoType, sql);
|
||||
return getDefault().findDto(dtoType, sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1097,7 +963,7 @@ public final class Ebean {
|
||||
* @return The update query to use
|
||||
*/
|
||||
public static <T> UpdateQuery<T> update(Class<T> beanType) {
|
||||
return serverMgr.getDefaultServer().update(beanType);
|
||||
return getDefault().update(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,7 +977,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static <T> Filter<T> filter(Class<T> beanType) {
|
||||
return serverMgr.getDefaultServer().filter(beanType);
|
||||
return getDefault().filter(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1154,7 +1020,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(CallableSql)
|
||||
*/
|
||||
public static int execute(SqlUpdate sqlUpdate) {
|
||||
return serverMgr.getDefaultServer().execute(sqlUpdate);
|
||||
return getDefault().execute(sqlUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1182,7 +1048,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(SqlUpdate)
|
||||
*/
|
||||
public static int execute(CallableSql callableSql) {
|
||||
return serverMgr.getDefaultServer().execute(callableSql);
|
||||
return getDefault().execute(callableSql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1206,7 +1072,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(TxScope scope, Runnable r) {
|
||||
serverMgr.getDefaultServer().execute(scope, r);
|
||||
getDefault().execute(scope, r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1233,7 +1099,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(Runnable r) {
|
||||
serverMgr.getDefaultServer().execute(r);
|
||||
getDefault().execute(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1258,7 +1124,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> T executeCall(TxScope scope, Callable<T> c) {
|
||||
return serverMgr.getDefaultServer().executeCall(scope, c);
|
||||
return getDefault().executeCall(scope, c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1291,7 +1157,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> T executeCall(Callable<T> c) {
|
||||
return serverMgr.getDefaultServer().executeCall(c);
|
||||
return getDefault().executeCall(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1325,8 +1191,7 @@ public final class Ebean {
|
||||
* @param deletes true if rows on the table where deleted
|
||||
*/
|
||||
public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
|
||||
serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes);
|
||||
getDefault().externalModification(tableName, inserts, updates, deletes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1336,14 +1201,14 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static BeanState getBeanState(Object bean) {
|
||||
return serverMgr.getDefaultServer().getBeanState(bean);
|
||||
return getDefault().getBeanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return serverMgr.getDefaultServer().getServerCacheManager();
|
||||
return getDefault().getServerCacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1351,14 +1216,14 @@ public final class Ebean {
|
||||
* queries.
|
||||
*/
|
||||
public static BackgroundExecutor getBackgroundExecutor() {
|
||||
return serverMgr.getDefaultServer().getBackgroundExecutor();
|
||||
return getDefault().getBackgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
*/
|
||||
public static JsonContext json() {
|
||||
return serverMgr.getDefaultServer().json();
|
||||
return getDefault().json();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class EbeanServerFactory {
|
||||
EbeanServer server = createInternal(config);
|
||||
|
||||
if (config.isRegister()) {
|
||||
PrimaryServer.setSkip(true);
|
||||
DbPrimary.setSkip(true);
|
||||
Ebean.register(server, config.isDefaultServer());
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class EbeanServerFactory {
|
||||
|
||||
if (containerConfig == null) {
|
||||
// effectively load configuration from ebean.properties
|
||||
Properties properties = PrimaryServer.getProperties();
|
||||
Properties properties = DbPrimary.getProperties();
|
||||
containerConfig = new ContainerConfig();
|
||||
containerConfig.loadFromProperties(properties);
|
||||
}
|
||||
|
||||
@@ -6,18 +6,18 @@ import org.slf4j.LoggerFactory;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Class to determine the ebean version. (
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
* Class to determine the ebean version.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public class EbeanVersion {
|
||||
private EbeanVersion() {
|
||||
|
||||
}
|
||||
private static final Logger logger = LoggerFactory.getLogger(EbeanVersion.class);
|
||||
|
||||
private static String version = "unknown";
|
||||
|
||||
static {
|
||||
try {
|
||||
Properties prop = new Properties();
|
||||
@@ -34,6 +34,10 @@ public class EbeanVersion {
|
||||
}
|
||||
}
|
||||
|
||||
private EbeanVersion() {
|
||||
// hide
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ebean version (read from /META-INF/maven/io.ebean/ebean/pom.properties)
|
||||
*/
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Expr {
|
||||
}
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* In Range - {@code property >= value1 and property < value2}.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
|
||||
@@ -155,7 +155,7 @@ public interface ExpressionFactory {
|
||||
Expression ineObject(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* In Range - {@code property >= value1 and property < value2}.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
|
||||
@@ -859,7 +859,7 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* In Range - property >= value1 and property < value2.
|
||||
* In Range - {@code property >= value1 and property < value2}.
|
||||
* <p>
|
||||
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
|
||||
* </p>
|
||||
@@ -1254,12 +1254,10 @@ public interface ExpressionList<T> {
|
||||
* The raw expression should contain a single ? or ?1
|
||||
* at the location of the parameter. We use ?1 when binding a
|
||||
* collection for an IN expression.
|
||||
* </p>
|
||||
* <p>>
|
||||
* <p>
|
||||
* When properties in the clause are fully qualified as table-column names
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
* <p>
|
||||
* <h4>Examples:</h4>
|
||||
* <pre>{@code
|
||||
|
||||
@@ -37,12 +37,13 @@ import java.util.List;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
* ...
|
||||
*
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
* When the Finder is registered as a field on Customer it can then be used like:
|
||||
@@ -79,12 +80,13 @@ public class Finder<I, T> {
|
||||
* // ... add extra customer specific finder methods
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
* ...
|
||||
*
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public Finder(Class<T> type) {
|
||||
|
||||
@@ -32,19 +32,19 @@ import io.ebean.bean.EntityBean;
|
||||
* // Typically there is a common base model that has some
|
||||
* // common properties like the ones below
|
||||
*
|
||||
* @MappedSuperclass
|
||||
* public class BaseModel extends Model {
|
||||
* @MappedSuperclass
|
||||
* public class BaseModel extends Model {
|
||||
*
|
||||
* @Id Long id;
|
||||
* @Id Long id;
|
||||
*
|
||||
* @Version Long version;
|
||||
* @Version Long version;
|
||||
*
|
||||
* @WhenCreated Timestamp whenCreated;
|
||||
* @WhenCreated Timestamp whenCreated;
|
||||
*
|
||||
* @WhenUpdated Timestamp whenUpdated;
|
||||
*
|
||||
* ...
|
||||
* @WhenUpdated Timestamp whenUpdated;
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <h3>Extend the Model</h3>
|
||||
@@ -52,7 +52,7 @@ import io.ebean.bean.EntityBean;
|
||||
*
|
||||
* // Extend the mappedSuperclass
|
||||
*
|
||||
* @Entity @Table(name="o_account")
|
||||
* @Entity @Table(name="o_account")
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* String name;
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.util.StringHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -341,7 +339,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
if (collation != null) {
|
||||
if (collation.contains("${}")) {
|
||||
// this is a complex collation, e.g. DB2 - we must replace the property
|
||||
sb.append(StringHelper.replaceString(collation, "${}", property));
|
||||
sb.append(collation.replace("${}", property));
|
||||
} else {
|
||||
sb.append(property);
|
||||
sb.append(" collate ").append(collation);
|
||||
|
||||
@@ -94,8 +94,8 @@ public interface PagedList<T> {
|
||||
* Return the Future row count. You might get this if you wish to cancel the total row count query
|
||||
* or specify a timeout for the row count query.
|
||||
* <p>
|
||||
* The loadRowCount() & getTotalRowCount() methods internally make use of this getFutureRowCount() method.
|
||||
* Generally I expect people to prefer loadRowCount() & getTotalRowCount() over getFutureRowCount().
|
||||
* The loadRowCount() and getTotalRowCount() methods internally make use of this getFutureRowCount() method.
|
||||
* Generally I expect people to prefer loadRowCount() and getTotalRowCount() over getFutureRowCount().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
*
|
||||
* // where a bean is annotated with a complex
|
||||
* // natural key made of several properties
|
||||
* @Cache(naturalKey = {"store","code","sku"})
|
||||
* @Cache(naturalKey = {"store","code","sku"})
|
||||
*
|
||||
*
|
||||
* Pairs pairs = new Pairs("sku", "code");
|
||||
|
||||
@@ -6,17 +6,13 @@ package io.ebean;
|
||||
* <p>
|
||||
* If you don't want to build object graphs you can use {@link SqlQuery} instead
|
||||
* which returns {@link SqlRow} objects rather than entity beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Unparsed RawSql:</b>
|
||||
* </p>
|
||||
* <p>
|
||||
* When RawSql is created via {@link RawSqlBuilder#unparsed(String)} then Ebean can not
|
||||
* modify the SQL at all. It can't add any extra expressions into the SQL.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Parsed RawSql:</b>
|
||||
* </p>
|
||||
* <p>
|
||||
* When RawSql is created via {@link RawSqlBuilder#parse(String)} then Ebean will parse the
|
||||
* SQL and find places in the SQL where it can add extra where expressions, add
|
||||
@@ -24,16 +20,13 @@ package io.ebean;
|
||||
* explicitly tell Ebean where these insertion points are you can place special
|
||||
* strings into your SQL ({@code ${where}} or {@code ${andWhere}} and {@code ${having}} or
|
||||
* {@code ${andHaving})}.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the SQL already includes a WHERE clause put in {@code ${andWhere}} in the location
|
||||
* you want Ebean to add any extra where expressions. If the SQL doesn't have a
|
||||
* WHERE clause put {@code ${where}} in instead. Similarly you can put in {@code ${having}} or
|
||||
* {@code ${andHaving}} where you want Ebean put add extra having expressions.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Aggregates:</b>
|
||||
* </p>
|
||||
* <p>
|
||||
* Often RawSql will be used with Aggregate functions (sum, avg, max etc). The
|
||||
* follow example shows an example based on Total Order Amount -
|
||||
@@ -44,38 +37,37 @@ package io.ebean;
|
||||
* on RawSql and not based on a real DB Table or DB View. It has some properties
|
||||
* to hold the values for the aggregate functions (sum etc) and a @OneToOne
|
||||
* to Order.
|
||||
* </p>
|
||||
* <p>
|
||||
* <h3>Example OrderAggregate</h3>
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* // @Sql indicates to that this bean
|
||||
* // is based on RawSql rather than a table
|
||||
* // @Sql indicates to that this bean
|
||||
* // is based on RawSql rather than a table
|
||||
*
|
||||
* @Entity
|
||||
* @Sql
|
||||
* public class OrderAggregate {
|
||||
* @Entity
|
||||
* @Sql
|
||||
* public class OrderAggregate {
|
||||
*
|
||||
* @OneToOne
|
||||
* Order order;
|
||||
* @OneToOne
|
||||
* Order order;
|
||||
*
|
||||
* Double totalAmount;
|
||||
* Double totalAmount;
|
||||
*
|
||||
* Double totalItems;
|
||||
*
|
||||
* // getters and setters
|
||||
* ...
|
||||
* Double totalItems;
|
||||
*
|
||||
* // getters and setters
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Example 1:</h3>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = " select order_id, o.status, c.id, c.name, sum(d.order_qty*d.unit_price) as totalAmount"
|
||||
* + " from o_order o"
|
||||
* + " join o_customer c on c.id = o.kcustomer_id "
|
||||
* + " join o_order_detail d on d.order_id = o.id " + " group by order_id, o.status ";
|
||||
* String sql = " select order_id, o.status, c.id, c.name, sum(l.order_qty*l.unit_price) as totalAmount"
|
||||
* + " from order o"
|
||||
* + " join customer c on c.id = o.customer_id "
|
||||
* + " join order_line l on l.order_id = o.id " + " group by order_id, o.status ";
|
||||
*
|
||||
* RawSql rawSql = RawSqlBuilder.parse(sql)
|
||||
* // map the sql result columns to bean properties
|
||||
@@ -95,18 +87,17 @@ package io.ebean;
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Example 2:</h3>
|
||||
* <p>
|
||||
* The following example uses a FetchConfig().query() so that after the initial
|
||||
* RawSql query is executed Ebean executes a secondary query to fetch the
|
||||
* associated order status, orderDate along with the customer name.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = " select order_id, 'ignoreMe', sum(d.order_qty*d.unit_price) as totalAmount "
|
||||
* + " from o_order_detail d"
|
||||
* String sql = " select order_id, 'ignoreMe', sum(l.order_qty*l.unit_price) as totalAmount "
|
||||
* + " from order_line l"
|
||||
* + " group by order_id ";
|
||||
*
|
||||
* RawSql rawSql = RawSqlBuilder.parse(sql)
|
||||
@@ -125,25 +116,23 @@ package io.ebean;
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <h3>Example 3: tableAliasMapping</h3>
|
||||
* <p>
|
||||
* Instead of mapping each column you can map each table alias to a path using tableAliasMapping().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* String rs = "select o.id, o.status, c.id, c.name, "+
|
||||
* " d.id, d.order_qty, p.id, p.name " +
|
||||
* "from o_order o join o_customer c on c.id = o.kcustomer_id " +
|
||||
* "join o_order_detail d on d.order_id = o.id " +
|
||||
* "join o_product p on p.id = d.product_id " +
|
||||
* " l.id, l.order_qty, p.id, p.name " +
|
||||
* "from orders o join o_customer c on c.id = o.customer_id " +
|
||||
* "join order_line l on l.order_id = o.id " +
|
||||
* "join product p on p.id = l.product_id " +
|
||||
* "where o.id <= :maxOrderId and p.id = :productId "+
|
||||
* "order by o.id, d.id asc";
|
||||
* "order by o.id, l.id asc";
|
||||
*
|
||||
* RawSql rawSql = RawSqlBuilder.parse(rs)
|
||||
* .tableAliasMapping("c", "customer")
|
||||
* .tableAliasMapping("d", "details")
|
||||
* .tableAliasMapping("p", "details.product")
|
||||
* .tableAliasMapping("l", "lines")
|
||||
* .tableAliasMapping("p", "lines.product")
|
||||
* .create();
|
||||
*
|
||||
* List<Order> ordersFromRaw = DB.find(Order.class)
|
||||
@@ -154,9 +143,7 @@ package io.ebean;
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <p>
|
||||
* Note that lazy loading also works with object graphs built with RawSql.
|
||||
* </p>
|
||||
*/
|
||||
public interface RawSql {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.sql.SQLException;
|
||||
* //
|
||||
* class CustomerMapper implements RowMapper<CustomerDto> {
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public CustomerDto map(ResultSet rset, int rowNum) throws SQLException {
|
||||
*
|
||||
* long id = rset.getLong(1);
|
||||
|
||||
@@ -12,26 +12,27 @@ package io.ebean;
|
||||
* The following is an example of named updates on an entity bean.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate(
|
||||
* name = "setTitle",
|
||||
* notifyCache = false,
|
||||
* update = "update topic set title = :title, postCount = :count where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* name = "setPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update f_topic set post_count = :postCount where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* name = "incrementPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update Topic set postCount = postCount + 1 where id = :id")
|
||||
* //update = "update f_topic set post_count = post_count + 1 where id = :id")
|
||||
* })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* public class Topic {
|
||||
* ...
|
||||
* ...
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate(
|
||||
* name = "setTitle",
|
||||
* notifyCache = false,
|
||||
* update = "update topic set title = :title, postCount = :count where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* name = "setPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update f_topic set post_count = :postCount where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* name = "incrementPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update Topic set postCount = postCount + 1 where id = :id")
|
||||
* //update = "update f_topic set post_count = post_count + 1 where id = :id")
|
||||
* })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* public class Topic {
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
|
||||
@@ -82,14 +82,14 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
private static final byte FLAG_CHANGED_PROP = 2;
|
||||
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distingush
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
private static final byte FLAG_EMBEDDED_DIRTY = 4;
|
||||
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distingush
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
@@ -371,13 +371,11 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
/**
|
||||
* Set the loaded state to true.
|
||||
* <p>
|
||||
* Calls to setter methods after the bean is loaded can result in 'Old Values'
|
||||
* being created to support ConcurrencyMode.ALL
|
||||
* </p>
|
||||
* Calls to setter methods after the bean is loaded can result in
|
||||
* 'Old Values' being created.
|
||||
* <p>
|
||||
* Worth noting that this is also set after a insert/update. By doing so it
|
||||
* 'resets' the bean for making further changes and saving again.
|
||||
* </p>
|
||||
*/
|
||||
public void setLoaded() {
|
||||
this.state = STATE_LOADED;
|
||||
@@ -391,8 +389,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* When finished loading for lazy or refresh on an already partially populated
|
||||
* bean.
|
||||
* When finished loading for lazy or refresh on an already partially populated bean.
|
||||
*/
|
||||
public void setLoadedLazy() {
|
||||
this.state = STATE_LOADED;
|
||||
@@ -423,9 +420,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
/**
|
||||
* Set true to turn off lazy loading.
|
||||
* <p>
|
||||
* Typically used to disable lazy loading on SQL based report beans.
|
||||
* </p>
|
||||
*/
|
||||
public void setDisableLazyLoad(boolean disableLazyLoad) {
|
||||
this.disableLazyLoad = disableLazyLoad;
|
||||
@@ -445,7 +439,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return true if the embedded bean is new or dirty and hence needs saving.
|
||||
*/
|
||||
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
|
||||
|
||||
if (embeddedBean == null) {
|
||||
// if it was previously set then the owning bean would
|
||||
// have oldValues containing the previous embedded bean
|
||||
@@ -453,7 +446,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
if (embeddedBean instanceof EntityBean) {
|
||||
return ((EntityBean) embeddedBean)._ebean_getIntercept().isNewOrDirty();
|
||||
|
||||
} else {
|
||||
// non-enhanced so must assume it is new and needs to be saved
|
||||
return true;
|
||||
@@ -471,8 +463,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the index position of a given property. Returns -1 if the property
|
||||
* can not be found.
|
||||
* Finds the index position of a given property. Returns -1 if the
|
||||
* property can not be found.
|
||||
*/
|
||||
public int findProperty(String propertyName) {
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
@@ -495,7 +487,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of properties.s
|
||||
* Return the number of properties.
|
||||
*/
|
||||
public int getPropertyLength() {
|
||||
return owner._ebean_getPropertyNames().length;
|
||||
@@ -517,8 +509,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property to be treated as unloaded. Used for properties initialised in default
|
||||
* constructor.
|
||||
* Set the property to be treated as unloaded. Used for properties initialised in default constructor.
|
||||
*/
|
||||
public void setPropertyUnloaded(int propertyIndex) {
|
||||
flags[propertyIndex] &= ~FLAG_LOADED_PROP;
|
||||
@@ -605,7 +596,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* For forced update on a 'New' bean set all the loaded properties to changed.
|
||||
*/
|
||||
public void setNewBeanForUpdate() {
|
||||
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
|
||||
flags[i] |= FLAG_CHANGED_PROP;
|
||||
@@ -660,8 +650,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
// the property has been changed on this bean
|
||||
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
|
||||
props.add(propName);
|
||||
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
@@ -674,12 +663,10 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return true if any of the given property names are dirty.
|
||||
*/
|
||||
public boolean hasDirtyProperty(Set<String> propertyNames) {
|
||||
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
// the property has been changed on this bean
|
||||
if (propertyNames.contains(names[i])) {
|
||||
return true;
|
||||
}
|
||||
@@ -712,10 +699,9 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
|
||||
Object newVal = owner._ebean_getField(i);
|
||||
Object oldVal = getOrigValue(i);
|
||||
if (!areEqual(oldVal, newVal)) {
|
||||
if (notEqual(oldVal, newVal)) {
|
||||
dirtyValues.put(propName, new ValuePair(newVal, oldVal));
|
||||
}
|
||||
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
@@ -734,10 +720,9 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
// the property has been changed on this bean
|
||||
Object newVal = owner._ebean_getField(i);
|
||||
Object oldVal = getOrigValue(i);
|
||||
if (!areEqual(oldVal, newVal)) {
|
||||
if (notEqual(oldVal, newVal)) {
|
||||
visitor.visit(i, newVal, oldVal);
|
||||
}
|
||||
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
@@ -758,7 +743,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and return a dirty property hash recursing into embedded beans.
|
||||
* Add and return a dirty property hash.
|
||||
*/
|
||||
private void addDirtyPropertyKey(StringBuilder sb) {
|
||||
if (sortOrder > 0) {
|
||||
@@ -818,21 +803,18 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Load the bean when it is a reference.
|
||||
*/
|
||||
protected void loadBean(int loadProperty) {
|
||||
|
||||
synchronized (this) {
|
||||
if (beanLoader == null) {
|
||||
final Database database = DB.byName(ebeanServerName);
|
||||
if (database == null) {
|
||||
throw new PersistenceException("Database [" + ebeanServerName + "] was not found?");
|
||||
}
|
||||
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
loadBeanInternal(loadProperty, database.getPluginApi());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (beanLoader) {
|
||||
// Lazy loading using LoadBeanContext which supports batch loading
|
||||
// Synchronise on the beanLoader (a 'node' of the LoadBeanContext 'tree')
|
||||
@@ -844,32 +826,24 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Invoke the lazy loading. This method is synchronised externally.
|
||||
*/
|
||||
private void loadBeanInternal(int loadProperty, BeanLoader loader) {
|
||||
|
||||
if ((flags[loadProperty] & FLAG_LOADED_PROP) != 0) {
|
||||
// race condition where multiple threads calling preGetter concurrently
|
||||
return;
|
||||
}
|
||||
|
||||
if (lazyLoadFailure) {
|
||||
// failed when batch lazy loaded by another bean in the batch
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
}
|
||||
|
||||
if (lazyLoadProperty == -1) {
|
||||
|
||||
lazyLoadProperty = loadProperty;
|
||||
|
||||
if (nodeUsageCollector != null) {
|
||||
nodeUsageCollector.setLoadProperty(getProperty(lazyLoadProperty));
|
||||
}
|
||||
|
||||
loader.loadBean(this);
|
||||
|
||||
if (lazyLoadFailure) {
|
||||
// failed when lazy loading this bean
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
|
||||
}
|
||||
|
||||
// bean should be loaded and intercepting now. setLoaded() has
|
||||
// been called by the lazy loading mechanism
|
||||
}
|
||||
@@ -879,32 +853,31 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Helper method to check if two objects are equal.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected boolean areEqual(Object obj1, Object obj2) {
|
||||
protected static boolean notEqual(Object obj1, Object obj2) {
|
||||
if (obj1 == null) {
|
||||
return (obj2 == null);
|
||||
return (obj2 != null);
|
||||
}
|
||||
if (obj2 == null) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (obj1 == obj2) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (obj1 instanceof BigDecimal) {
|
||||
// Use comparable for BigDecimal as equals
|
||||
// uses scale in comparison...
|
||||
if (obj2 instanceof BigDecimal) {
|
||||
Comparable com1 = (Comparable) obj1;
|
||||
return (com1.compareTo(obj2) == 0);
|
||||
|
||||
return (com1.compareTo(obj2) != 0);
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (obj1 instanceof URL) {
|
||||
// use the string format to determine if dirty
|
||||
return obj1.toString().equals(obj2.toString());
|
||||
return !obj1.toString().equals(obj2.toString());
|
||||
}
|
||||
return obj1.equals(obj2);
|
||||
return !obj1.equals(obj2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -945,25 +918,20 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* OneToMany and ManyToMany don't have any interception so just check for
|
||||
* PropertyChangeSupport.
|
||||
* OneToMany and ManyToMany only set loaded state.
|
||||
*/
|
||||
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
|
||||
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
|
||||
setLoadedProperty(propertyIndex);
|
||||
}
|
||||
|
||||
private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangedProperty(propertyIndex);
|
||||
|
||||
if (setDirtyState) {
|
||||
setOriginalValue(propertyIndex, origValue);
|
||||
setDirtyStatus();
|
||||
@@ -988,10 +956,9 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* the old values for use with ConcurrencyMode.ALL.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (!areEqual(oldValue, newValue)) {
|
||||
} else if (notEqual(oldValue, newValue)) {
|
||||
setChangedPropertyValue(propertyIndex, intercept, oldValue);
|
||||
}
|
||||
}
|
||||
@@ -1001,7 +968,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Check for primitive boolean.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1013,7 +979,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Check for primitive int.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1025,7 +990,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* long.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1037,7 +1001,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* double.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (Double.compare(oldValue, newValue) != 0) {
|
||||
@@ -1049,7 +1012,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* float.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (Float.compare(oldValue, newValue) != 0) {
|
||||
@@ -1061,7 +1023,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* short.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1073,7 +1034,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* char.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1085,7 +1045,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* byte.
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (oldValue != newValue) {
|
||||
@@ -1097,7 +1056,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* char[].
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (!Arrays.equals(oldValue, newValue)) {
|
||||
@@ -1109,7 +1067,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* byte[].
|
||||
*/
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
|
||||
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else if (!Arrays.equals(oldValue, newValue)) {
|
||||
|
||||
@@ -3,8 +3,6 @@ package io.ebean.config;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.Table;
|
||||
@@ -16,10 +14,6 @@ import javax.persistence.Table;
|
||||
*/
|
||||
public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
|
||||
private static final Pattern TABLE_REPLACE = Pattern.compile("{table}", Pattern.LITERAL);
|
||||
|
||||
private static final Pattern COLUMN_REPLACE = Pattern.compile("{column}", Pattern.LITERAL);
|
||||
|
||||
/**
|
||||
* The Constant DEFAULT_SEQ_FORMAT.
|
||||
*/
|
||||
@@ -85,13 +79,9 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
@Override
|
||||
public String getSequenceName(String rawTableName, String pkColumn) {
|
||||
final String tableNameUnquoted = databasePlatform.unQuote(rawTableName);
|
||||
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableNameUnquoted));
|
||||
if (pkColumn == null) {
|
||||
pkColumn = "";
|
||||
} else {
|
||||
pkColumn = databasePlatform.unQuote(pkColumn);
|
||||
}
|
||||
return COLUMN_REPLACE.matcher(s).replaceAll(Matcher.quoteReplacement(pkColumn));
|
||||
String seqName = sequenceFormat.replace("{table}", tableNameUnquoted);
|
||||
pkColumn = (pkColumn == null) ? "" : databasePlatform.unQuote(pkColumn);
|
||||
return seqName.replace("{column}", pkColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.time.format.DateTimeFormatter;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static io.ebean.util.StringHelper.replace;
|
||||
|
||||
/**
|
||||
* Configuration for the DB migration processing.
|
||||
*/
|
||||
@@ -375,8 +377,8 @@ public class DbMigrationConfig {
|
||||
*/
|
||||
public String getDdlHeader() {
|
||||
if (ddlHeader != null && !ddlHeader.isEmpty()) {
|
||||
ddlHeader = StringHelper.replaceString(ddlHeader, "${version}", EbeanVersion.getVersion());
|
||||
ddlHeader = StringHelper.replaceString(ddlHeader, "${timestamp}", ZonedDateTime.now().format( DateTimeFormatter.ISO_INSTANT ));
|
||||
ddlHeader = replace(ddlHeader, "${version}", EbeanVersion.getVersion());
|
||||
ddlHeader = replace(ddlHeader, "${timestamp}", ZonedDateTime.now().format( DateTimeFormatter.ISO_INSTANT ));
|
||||
}
|
||||
return ddlHeader;
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ServerConfig {
|
||||
* Typically configuration type objects that are passed by this ServerConfig
|
||||
* to plugins. For example - IgniteConfiguration passed to Ignite plugin.
|
||||
*/
|
||||
private Map<String, Object> serviceObject = new HashMap<>();
|
||||
private final Map<String, Object> serviceObject = new HashMap<>();
|
||||
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
@@ -188,7 +188,7 @@ public class ServerConfig {
|
||||
private JsonConfig.Date jsonDate = JsonConfig.Date.ISO8601;
|
||||
|
||||
/**
|
||||
* For writing JSON specify if null values or empty collections should be exluded.
|
||||
* For writing JSON specify if null values or empty collections should be excluded.
|
||||
* By default all values are included.
|
||||
*/
|
||||
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
|
||||
@@ -528,7 +528,6 @@ public class ServerConfig {
|
||||
* Construct a Database Configuration for programmatically creating an Database.
|
||||
*/
|
||||
public ServerConfig() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -593,7 +592,6 @@ public class ServerConfig {
|
||||
* Put a service object into configuration such that it can be passed to a plugin.
|
||||
* <p>
|
||||
* For example, put IgniteConfiguration in to be passed to the Ignite plugin.
|
||||
* </p>
|
||||
*/
|
||||
public void putServiceObject(String key, Object configObject) {
|
||||
serviceObject.put(key, configObject);
|
||||
@@ -704,8 +702,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Set the JSON include mode used when writing JSON.
|
||||
* <p>
|
||||
* Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively.
|
||||
* </p>
|
||||
* Set to NON_NULL or NON_EMPTY to suppress nulls or null and empty collections respectively.
|
||||
*/
|
||||
public void setJsonInclude(JsonConfig.Include jsonInclude) {
|
||||
this.jsonInclude = jsonInclude;
|
||||
@@ -750,7 +747,6 @@ public class ServerConfig {
|
||||
* when it is created.
|
||||
* <p>
|
||||
* By default this is set to true.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isRegister() {
|
||||
return register;
|
||||
@@ -761,7 +757,6 @@ public class ServerConfig {
|
||||
* singleton when it is created.
|
||||
* <p>
|
||||
* By default this is set to true.
|
||||
* </p>
|
||||
*/
|
||||
public void setRegister(boolean register) {
|
||||
this.register = register;
|
||||
@@ -772,7 +767,6 @@ public class ServerConfig {
|
||||
* with the Ebean singleton.
|
||||
* <p>
|
||||
* This is only used when {@link #setRegister(boolean)} is also true.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isDefaultServer() {
|
||||
return defaultServer;
|
||||
@@ -783,7 +777,6 @@ public class ServerConfig {
|
||||
* with the DB singleton.
|
||||
* <p>
|
||||
* This is only used when {@link #setRegister(boolean)} is also true.
|
||||
* </p>
|
||||
*/
|
||||
public void setDefaultServer(boolean defaultServer) {
|
||||
this.defaultServer = defaultServer;
|
||||
@@ -895,7 +888,6 @@ public class ServerConfig {
|
||||
* When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
|
||||
* a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
|
||||
* or the batch size is meet.
|
||||
* </p>
|
||||
*/
|
||||
public PersistBatch getPersistBatch() {
|
||||
return persistBatch;
|
||||
@@ -907,7 +899,6 @@ public class ServerConfig {
|
||||
* When INSERT or ALL is used then save(), delete() etc do not execute immediately but instead go into
|
||||
* a JDBC batch execute buffer that is flushed. The buffer is flushed if a query is executed, transaction ends
|
||||
* or the batch size is meet.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistBatch(PersistBatch persistBatch) {
|
||||
this.persistBatch = persistBatch;
|
||||
@@ -918,10 +909,8 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This makes sense when a save() or delete() cascades and executes multiple child statements. The best case
|
||||
* for this is when saving a master/parent bean this cascade inserts many detail/child beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* This only takes effect when the persistBatch mode at the transaction level does not take effect.
|
||||
* </p>
|
||||
*/
|
||||
public PersistBatch getPersistBatchOnCascade() {
|
||||
return persistBatchOnCascade;
|
||||
@@ -932,10 +921,8 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This makes sense when a save() or delete() etc cascades and executes multiple child statements. The best caase
|
||||
* for this is when saving a master/parent bean this cascade inserts many detail/child beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* This only takes effect when the persistBatch mode at the transaction level does not take effect.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistBatchOnCascade(PersistBatch persistBatchOnCascade) {
|
||||
this.persistBatchOnCascade = persistBatchOnCascade;
|
||||
@@ -944,17 +931,13 @@ public class ServerConfig {
|
||||
/**
|
||||
* Deprecated, please migrate to using setPersistBatch().
|
||||
* <p>
|
||||
* Set to true if you what to use JDBC batching for persisting and deleting
|
||||
* beans.
|
||||
* </p>
|
||||
* Set to true if you what to use JDBC batching for persisting and deleting beans.
|
||||
* <p>
|
||||
* With this Ebean will batch up persist requests and use the JDBC batch api.
|
||||
* This is a performance optimisation designed to reduce the network chatter.
|
||||
* </p>
|
||||
* <p>
|
||||
* When true this is equivalent to {@code setPersistBatch(PersistBatch.ALL)} or
|
||||
* when false to {@code setPersistBatch(PersistBatch.NONE)}
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistBatching(boolean persistBatching) {
|
||||
this.persistBatch = (persistBatching) ? PersistBatch.ALL : PersistBatch.NONE;
|
||||
@@ -971,7 +954,6 @@ public class ServerConfig {
|
||||
* Set the batch size used for JDBC batching. If unset this defaults to 20.
|
||||
* <p>
|
||||
* You can also set the batch size on the transaction.
|
||||
* </p>
|
||||
*
|
||||
* @see Transaction#setBatchSize(int)
|
||||
*/
|
||||
@@ -1033,14 +1015,11 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This is the number of beans or collections loaded when lazy loading is
|
||||
* invoked by default.
|
||||
* </p>
|
||||
* <p>
|
||||
* The default value is for this is 10 (load 10 beans or collections).
|
||||
* </p>
|
||||
* <p>
|
||||
* You can explicitly control the lazy loading batch size for a given join on
|
||||
* a query using +lazy(batchSize) or JoinConfig.
|
||||
* </p>
|
||||
*/
|
||||
public void setLazyLoadBatchSize(int lazyLoadBatchSize) {
|
||||
this.lazyLoadBatchSize = lazyLoadBatchSize;
|
||||
@@ -1052,7 +1031,7 @@ public class ServerConfig {
|
||||
* This is a performance optimisation to reduce the number times Ebean
|
||||
* requests a sequence to be used as an Id for a bean (aka reduce network
|
||||
* chatter).
|
||||
* </p>
|
||||
|
||||
*/
|
||||
public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
|
||||
platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
@@ -1091,7 +1070,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This is used to set user context information to the ChangeSet in the
|
||||
* foreground thread prior to the logging occurring in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public ChangeLogPrepare getChangeLogPrepare() {
|
||||
return changeLogPrepare;
|
||||
@@ -1102,7 +1080,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This is used to set user context information to the ChangeSet in the
|
||||
* foreground thread prior to the logging occurring in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public void setChangeLogPrepare(ChangeLogPrepare changeLogPrepare) {
|
||||
this.changeLogPrepare = changeLogPrepare;
|
||||
@@ -1199,7 +1176,6 @@ public class ServerConfig {
|
||||
* It is expected that an implementation is used that read user context information
|
||||
* (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
|
||||
* to the ReadAuditLogger.
|
||||
* </p>
|
||||
*/
|
||||
public void setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
|
||||
this.readAuditPrepare = readAuditPrepare;
|
||||
@@ -1270,7 +1246,6 @@ public class ServerConfig {
|
||||
* Return the time zone to use when reading/writing Timestamps via JDBC.
|
||||
* <p>
|
||||
* When set a Calendar object is used in JDBC calls when reading/writing Timestamp objects.
|
||||
* </p>
|
||||
*/
|
||||
public String getDataTimeZone() {
|
||||
return System.getProperty("ebean.dataTimeZone", dataTimeZone);
|
||||
@@ -1533,7 +1508,6 @@ public class ServerConfig {
|
||||
* Return the NamingConvention.
|
||||
* <p>
|
||||
* If none has been set the default UnderscoreNamingConvention is used.
|
||||
* </p>
|
||||
*/
|
||||
public NamingConvention getNamingConvention() {
|
||||
return namingConvention;
|
||||
@@ -1543,7 +1517,6 @@ public class ServerConfig {
|
||||
* Set the NamingConvention.
|
||||
* <p>
|
||||
* If none is set the default UnderscoreNamingConvention is used.
|
||||
* </p>
|
||||
*/
|
||||
public void setNamingConvention(NamingConvention namingConvention) {
|
||||
this.namingConvention = namingConvention;
|
||||
@@ -1655,11 +1628,9 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note that the DataSource is expected to use AutoCommit true mode avoiding the need
|
||||
* for explicit commit (or rollback).
|
||||
* </p>
|
||||
* <p>
|
||||
* This read only DataSource will be used for implicit query only transactions. It is not
|
||||
* used if the transaction is created explicitly or if the query is an update or delete query.
|
||||
* </p>
|
||||
*/
|
||||
public void setReadOnlyDataSource(DataSource readOnlyDataSource) {
|
||||
this.readOnlyDataSource = readOnlyDataSource;
|
||||
@@ -1699,12 +1670,10 @@ public class ServerConfig {
|
||||
* Return the configuration for the read only DataSource.
|
||||
* <p>
|
||||
* This is only used if autoReadOnlyDataSource is true.
|
||||
* </p>
|
||||
* <p>
|
||||
* The driver, url, username and password default to the configuration for the main DataSource if they are not
|
||||
* set on this configuration. This means there is actually no need to set any configuration here and we only
|
||||
* set configuration for url, username and password etc if it is different from the main DataSource.
|
||||
* </p>
|
||||
*/
|
||||
public DataSourceConfig getReadOnlyDataSourceConfig() {
|
||||
return readOnlyDataSourceConfig;
|
||||
@@ -1730,7 +1699,6 @@ public class ServerConfig {
|
||||
* By default a prefix of "java:comp/env/jdbc/" is used to lookup the
|
||||
* DataSource. This prefix is not used if dataSourceJndiName starts with
|
||||
* "java:".
|
||||
* </p>
|
||||
*/
|
||||
public void setDataSourceJndiName(String dataSourceJndiName) {
|
||||
this.dataSourceJndiName = dataSourceJndiName;
|
||||
@@ -1740,10 +1708,8 @@ public class ServerConfig {
|
||||
* Return a value used to represent TRUE in the database.
|
||||
* <p>
|
||||
* This is used for databases that do not support boolean natively.
|
||||
* </p>
|
||||
* <p>
|
||||
* The value returned is either a Integer or a String (e.g. "1", or "T").
|
||||
* </p>
|
||||
*/
|
||||
public String getDatabaseBooleanTrue() {
|
||||
return platformConfig.getDatabaseBooleanTrue();
|
||||
@@ -1753,10 +1719,8 @@ public class ServerConfig {
|
||||
* Set the value to represent TRUE in the database.
|
||||
* <p>
|
||||
* This is used for databases that do not support boolean natively.
|
||||
* </p>
|
||||
* <p>
|
||||
* The value set is either a Integer or a String (e.g. "1", or "T").
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabaseBooleanTrue(String databaseTrue) {
|
||||
platformConfig.setDatabaseBooleanTrue(databaseTrue);
|
||||
@@ -1766,10 +1730,8 @@ public class ServerConfig {
|
||||
* Return a value used to represent FALSE in the database.
|
||||
* <p>
|
||||
* This is used for databases that do not support boolean natively.
|
||||
* </p>
|
||||
* <p>
|
||||
* The value returned is either a Integer or a String (e.g. "0", or "F").
|
||||
* </p>
|
||||
*/
|
||||
public String getDatabaseBooleanFalse() {
|
||||
return platformConfig.getDatabaseBooleanFalse();
|
||||
@@ -1779,10 +1741,8 @@ public class ServerConfig {
|
||||
* Set the value to represent FALSE in the database.
|
||||
* <p>
|
||||
* This is used for databases that do not support boolean natively.
|
||||
* </p>
|
||||
* <p>
|
||||
* The value set is either a Integer or a String (e.g. "0", or "F").
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabaseBooleanFalse(String databaseFalse) {
|
||||
this.platformConfig.setDatabaseBooleanFalse(databaseFalse);
|
||||
@@ -1802,13 +1762,11 @@ public class ServerConfig {
|
||||
* This is only used for DB's that use sequences and is a performance
|
||||
* optimisation. This reduces the number of times Ebean needs to get a
|
||||
* sequence value from the Database reducing network chatter.
|
||||
* </p>
|
||||
* <p>
|
||||
* By default this value is 10 so when we need another Id (and don't have one
|
||||
* in our cache) Ebean will fetch 10 id's from the database. Note that when
|
||||
* the cache drops to have full (which is 5 by default) Ebean will fetch
|
||||
* another batch of Id's in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabaseSequenceBatch(int databaseSequenceBatchSize) {
|
||||
this.platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
@@ -1819,7 +1777,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* If null then the platform is determined automatically via the JDBC driver
|
||||
* information.
|
||||
* </p>
|
||||
*/
|
||||
public String getDatabasePlatformName() {
|
||||
return databasePlatformName;
|
||||
@@ -1830,16 +1787,13 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* If none is set then the platform is determined automatically via the JDBC
|
||||
* driver information.
|
||||
* </p>
|
||||
* <p>
|
||||
* This can be used when the Database Platform can not be automatically
|
||||
* detected from the JDBC driver (possibly 3rd party JDBC driver). It is also
|
||||
* useful when you want to do offline DDL generation for a database platform
|
||||
* that you don't have access to.
|
||||
* </p>
|
||||
* <p>
|
||||
* Values are oracle, h2, postgres, mysql, sqlserver16, sqlserver17.
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabasePlatformName(String databasePlatformName) {
|
||||
this.databasePlatformName = databasePlatformName;
|
||||
@@ -1857,7 +1811,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* If none is set then the platform is determined via the databasePlatformName
|
||||
* or automatically via the JDBC driver information.
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabasePlatform(DatabasePlatform databasePlatform) {
|
||||
this.databasePlatform = databasePlatform;
|
||||
@@ -1888,10 +1841,8 @@ public class ServerConfig {
|
||||
* Set the EncryptKeyManager.
|
||||
* <p>
|
||||
* This is required when you want to use encrypted properties.
|
||||
* </p>
|
||||
* <p>
|
||||
* You can also set this in ebean.proprerties:
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* # set via ebean.properties
|
||||
@@ -1907,7 +1858,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This is optionally used to programmatically define which columns are
|
||||
* encrypted instead of using the {@link Encrypted} Annotation.
|
||||
* </p>
|
||||
*/
|
||||
public EncryptDeployManager getEncryptDeployManager() {
|
||||
return encryptDeployManager;
|
||||
@@ -1918,7 +1868,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* This is optionally used to programmatically define which columns are
|
||||
* encrypted instead of using the {@link Encrypted} Annotation.
|
||||
* </p>
|
||||
*/
|
||||
public void setEncryptDeployManager(EncryptDeployManager encryptDeployManager) {
|
||||
this.encryptDeployManager = encryptDeployManager;
|
||||
@@ -1938,7 +1887,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Ebean has a default implementation that it will use if you do not set your
|
||||
* own Encryptor implementation.
|
||||
* </p>
|
||||
*/
|
||||
public void setEncryptor(Encryptor encryptor) {
|
||||
this.encryptor = encryptor;
|
||||
@@ -1956,7 +1904,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Typically used to create an Database instance for DDL Migration generation
|
||||
* without requiring a real DataSource / Database to connect to.
|
||||
* </p>
|
||||
*/
|
||||
public void setDbOffline(boolean dbOffline) {
|
||||
this.dbOffline = dbOffline;
|
||||
@@ -1967,7 +1914,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note that if this is not set then the DbPlatform may already have a
|
||||
* DbEncrypt set and that will be used.
|
||||
* </p>
|
||||
*/
|
||||
public DbEncrypt getDbEncrypt() {
|
||||
return dbEncrypt;
|
||||
@@ -1978,7 +1924,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note that if this is not set then the DbPlatform may already have a
|
||||
* DbEncrypt set (H2, MySql, Postgres and Oracle platforms have a DbEncrypt)
|
||||
* </p>
|
||||
*/
|
||||
public void setDbEncrypt(DbEncrypt dbEncrypt) {
|
||||
this.dbEncrypt = dbEncrypt;
|
||||
@@ -2053,7 +1998,6 @@ public class ServerConfig {
|
||||
* Set to true if LocalTime should be persisted with nanos precision.
|
||||
* <p>
|
||||
* Otherwise it is persisted using java.sql.Time which is seconds precision.
|
||||
* </p>
|
||||
*/
|
||||
public void setLocalTimeWithNanos(boolean localTimeWithNanos) {
|
||||
this.localTimeWithNanos = localTimeWithNanos;
|
||||
@@ -2063,7 +2007,6 @@ public class ServerConfig {
|
||||
* Return true if Duration should be persisted with nanos precision (SQL DECIMAL).
|
||||
* <p>
|
||||
* Otherwise it is persisted with second precision (SQL INTEGER).
|
||||
* </p>
|
||||
*/
|
||||
public boolean isDurationWithNanos() {
|
||||
return durationWithNanos;
|
||||
@@ -2073,7 +2016,6 @@ public class ServerConfig {
|
||||
* Set to true if Duration should be persisted with nanos precision (SQL DECIMAL).
|
||||
* <p>
|
||||
* Otherwise it is persisted with second precision (SQL INTEGER).
|
||||
* </p>
|
||||
*/
|
||||
public void setDurationWithNanos(boolean durationWithNanos) {
|
||||
this.durationWithNanos = durationWithNanos;
|
||||
@@ -2144,7 +2086,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Typically this is a sql script that inserts test seed data when running tests.
|
||||
* Place a sql script in src/test/resources that inserts test seed data.
|
||||
* </p>
|
||||
*/
|
||||
public String getDdlSeedSql() {
|
||||
return ddlSeedSql;
|
||||
@@ -2155,7 +2096,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Typically this is a sql script that inserts test seed data when running tests.
|
||||
* Place a sql script in src/test/resources that inserts test seed data.
|
||||
* </p>
|
||||
*/
|
||||
public void setDdlSeedSql(String ddlSeedSql) {
|
||||
this.ddlSeedSql = ddlSeedSql;
|
||||
@@ -2232,14 +2172,11 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
|
||||
* BeanFinder or BeanPersistController.
|
||||
* </p>
|
||||
* <p>
|
||||
* If no classes are specified then the classes are found automatically via
|
||||
* searching the class path.
|
||||
* </p>
|
||||
* <p>
|
||||
* Alternatively the classes can be added via {@link #setClasses(List)}.
|
||||
* </p>
|
||||
*
|
||||
* @param cls the entity type (or other type) that should be registered by this
|
||||
* database.
|
||||
@@ -2261,7 +2198,6 @@ public class ServerConfig {
|
||||
* Add a package to search for entities via class path search.
|
||||
* <p>
|
||||
* This is only used if classes have not been explicitly specified.
|
||||
* </p>
|
||||
*/
|
||||
public void addPackage(String packageName) {
|
||||
packages.add(packageName);
|
||||
@@ -2271,7 +2207,6 @@ public class ServerConfig {
|
||||
* Return packages to search for entities via class path search.
|
||||
* <p>
|
||||
* This is only used if classes have not been explicitly specified.
|
||||
* </p>
|
||||
*/
|
||||
public List<String> getPackages() {
|
||||
return packages;
|
||||
@@ -2281,7 +2216,6 @@ public class ServerConfig {
|
||||
* Set packages to search for entities via class path search.
|
||||
* <p>
|
||||
* This is only used if classes have not been explicitly specified.
|
||||
* </p>
|
||||
*/
|
||||
public void setPackages(List<String> packages) {
|
||||
this.packages = packages;
|
||||
@@ -2293,10 +2227,8 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* If no classes are specified then the classes are found automatically via
|
||||
* searching the class path.
|
||||
* </p>
|
||||
* <p>
|
||||
* Alternatively the classes can contain added via {@link #addClass(Class)}.
|
||||
* </p>
|
||||
*/
|
||||
public void setClasses(List<Class<?>> classes) {
|
||||
this.classes = classes;
|
||||
@@ -2316,7 +2248,6 @@ public class ServerConfig {
|
||||
* This defaults to true and means that for "find by id" and "find by natural key"
|
||||
* queries that normally hit L2 bean cache automatically will not do so after a write/persist
|
||||
* on the transaction.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -2377,7 +2308,6 @@ public class ServerConfig {
|
||||
* Set to false if by default updates in JDBC batch should not include all properties.
|
||||
* <p>
|
||||
* This mode can be explicitly set per transaction.
|
||||
* </p>
|
||||
*
|
||||
* @see Transaction#setUpdateAllLoadedProperties(boolean)
|
||||
*/
|
||||
@@ -2445,7 +2375,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setQueryAdapters(List)} to set all
|
||||
* the BeanQueryAdapter instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanQueryAdapter beanQueryAdapter) {
|
||||
queryAdapters.add(beanQueryAdapter);
|
||||
@@ -2463,7 +2392,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #add(BeanQueryAdapter)} to add
|
||||
* BeanQueryAdapter instances one at a time.
|
||||
* </p>
|
||||
*/
|
||||
public void setQueryAdapters(List<BeanQueryAdapter> queryAdapters) {
|
||||
this.queryAdapters = queryAdapters;
|
||||
@@ -2495,7 +2423,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPersistControllers(List)} to set
|
||||
* all the BeanPersistController instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPersistController beanPersistController) {
|
||||
persistControllers.add(beanPersistController);
|
||||
@@ -2506,7 +2433,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPostLoaders(List)} to set
|
||||
* all the BeanPostLoad instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPostLoad postLoad) {
|
||||
postLoaders.add(postLoad);
|
||||
@@ -2517,7 +2443,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPostConstructListeners(List)} to set
|
||||
* all the BeanPostConstructListener instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPostConstructListener listener) {
|
||||
postConstructListeners.add(listener);
|
||||
@@ -2577,7 +2502,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #add(BeanPersistController)} to add
|
||||
* BeanPersistController instances one at a time.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistControllers(List<BeanPersistController> persistControllers) {
|
||||
this.persistControllers = persistControllers;
|
||||
@@ -2588,7 +2512,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPersistListeners(List)} to set
|
||||
* all the BeanPersistListener instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPersistListener beanPersistListener) {
|
||||
persistListeners.add(beanPersistListener);
|
||||
@@ -2634,7 +2557,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #add(BeanPersistListener)} to add
|
||||
* BeanPersistListener instances one at a time.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistListeners(List<BeanPersistListener> persistListeners) {
|
||||
this.persistListeners = persistListeners;
|
||||
@@ -2929,14 +2851,12 @@ public class ServerConfig {
|
||||
* @return the classes
|
||||
*/
|
||||
private List<Class<?>> getClasses(PropertiesWrapper properties) {
|
||||
|
||||
String classNames = properties.get("classes", null);
|
||||
if (classNames == null) {
|
||||
return classes;
|
||||
}
|
||||
|
||||
List<Class<?>> classList = new ArrayList<>();
|
||||
|
||||
String[] split = StringHelper.splitNames(classNames);
|
||||
for (String cn : split) {
|
||||
if (!"class".equalsIgnoreCase(cn)) {
|
||||
@@ -2952,13 +2872,10 @@ public class ServerConfig {
|
||||
}
|
||||
|
||||
private List<String> getSearchList(String searchNames, List<String> defaultValue) {
|
||||
|
||||
if (searchNames != null) {
|
||||
String[] entries = StringHelper.splitNames(searchNames);
|
||||
|
||||
List<String> hitList = new ArrayList<>(entries.length);
|
||||
Collections.addAll(hitList, entries);
|
||||
|
||||
return hitList;
|
||||
} else {
|
||||
return defaultValue;
|
||||
@@ -2970,7 +2887,6 @@ public class ServerConfig {
|
||||
* platform supports getGeneratedKeys in batch mode.
|
||||
*/
|
||||
public PersistBatch appliedPersistBatchOnCascade() {
|
||||
|
||||
if (persistBatchOnCascade == PersistBatch.INHERIT) {
|
||||
// use the platform default (ALL except SQL Server which has NONE)
|
||||
return databasePlatform.getPersistBatchOnCascade();
|
||||
@@ -2982,7 +2898,6 @@ public class ServerConfig {
|
||||
* Return the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public Object getObjectMapper() {
|
||||
return objectMapper;
|
||||
@@ -2992,7 +2907,6 @@ public class ServerConfig {
|
||||
* Set the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public void setObjectMapper(Object objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
@@ -3011,7 +2925,6 @@ public class ServerConfig {
|
||||
* Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
|
||||
* ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
|
||||
* which will add "1=1" into the SQL rather than "is null".
|
||||
* </p>
|
||||
*/
|
||||
public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
|
||||
this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
|
||||
@@ -3105,7 +3018,6 @@ public class ServerConfig {
|
||||
* In general we don't want to do that as when we use a distributed cache (like Ignite, Hazelcast etc)
|
||||
* we are making network calls and we prefer to do this in background and not impact the response time
|
||||
* of the executing transaction.
|
||||
* </p>
|
||||
*/
|
||||
public void setNotifyL2CacheInForeground(boolean notifyL2CacheInForeground) {
|
||||
this.notifyL2CacheInForeground = notifyL2CacheInForeground;
|
||||
@@ -3142,7 +3054,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* Typically used in Db Migration generation for many platform targets that might have different
|
||||
* configuration for IdType, UUID, quoted identifiers etc.
|
||||
* </p>
|
||||
*
|
||||
* @param propertiesPath The properties path used for loading and setting properties
|
||||
* @param platformPrefix The prefix used for loading and setting properties
|
||||
@@ -3179,7 +3090,6 @@ public class ServerConfig {
|
||||
* Set mapping locations to search for xml mapping via class path search.
|
||||
* <p>
|
||||
* This is only used if classes have not been explicitly specified.
|
||||
* </p>
|
||||
*/
|
||||
public void setMappingLocations(List<String> mappingLocations) {
|
||||
this.mappingLocations = mappingLocations;
|
||||
@@ -3265,7 +3175,6 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* When false we either register entity classes via application code or use classpath
|
||||
* scanning to find and register entity classes.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isAutoLoadModuleInfo() {
|
||||
return loadModuleInfo && classes.isEmpty();
|
||||
|
||||
@@ -15,7 +15,7 @@ package io.ebean.config;
|
||||
*
|
||||
* public class EbeanConfigProvider implements ServerConfigProvider {
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public void apply(ServerConfig config) {
|
||||
*
|
||||
* // register the entity bean classes explicitly
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Defines the identity/sequence behaviour for the database.
|
||||
*/
|
||||
@@ -10,8 +7,6 @@ public class DbIdentity {
|
||||
|
||||
private static final String TABLE_PLACEHOLDER = "{table}";
|
||||
|
||||
private static final Pattern TABLE_REPLACE = Pattern.compile(TABLE_PLACEHOLDER, Pattern.LITERAL);
|
||||
|
||||
/**
|
||||
* Set if this DB supports sequences. Note some DB's support both Sequences
|
||||
* and Identity.
|
||||
@@ -55,10 +50,7 @@ public class DbIdentity {
|
||||
if (selectLastInsertedIdTemplate == null) {
|
||||
return null;
|
||||
}
|
||||
if (!selectLastInsertedIdTemplate.contains(TABLE_PLACEHOLDER)) {
|
||||
return selectLastInsertedIdTemplate;
|
||||
}
|
||||
return TABLE_REPLACE.matcher(selectLastInsertedIdTemplate).replaceAll(Matcher.quoteReplacement(table));
|
||||
return selectLastInsertedIdTemplate.replace(TABLE_PLACEHOLDER, table);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,7 +25,7 @@ public class MariaDbHistorySupport extends DbStandardHistorySupport {
|
||||
*/
|
||||
@Override
|
||||
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "From";
|
||||
return tableAlias + ".row_start";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -33,6 +33,6 @@ public class MariaDbHistorySupport extends DbStandardHistorySupport {
|
||||
*/
|
||||
@Override
|
||||
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "To";
|
||||
return tableAlias + ".row_end";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.ebean.config.dbplatform.DbStandardHistorySupport;
|
||||
/**
|
||||
* History support only valid on SqlServer 2016 or later.
|
||||
*
|
||||
* @author Vilmos Nagy <vilmos.nagy@outlook.com>
|
||||
* @author Vilmos Nagy
|
||||
*/
|
||||
public class SqlServerHistorySupport extends DbStandardHistorySupport {
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -10,152 +9,10 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class StringHelper {
|
||||
|
||||
private static final char SINGLE_QUOTE = '\'';
|
||||
|
||||
private static final char DOUBLE_QUOTE = '"';
|
||||
|
||||
private static final Pattern SPLIT_NAMES = Pattern.compile("[\\s,;]+");
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
/**
|
||||
* parses a String of the form name1='value1' name2='value2'. Note that you
|
||||
* can use either single or double quotes for any particular name value pair
|
||||
* and the end quote must match the begin quote.
|
||||
*/
|
||||
public static HashMap<String, String> parseNameQuotedValue(String tag) throws RuntimeException {
|
||||
|
||||
if (tag == null || tag.length() < 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// make sure that the quotes are matched...
|
||||
// int remainer = countOccurances(tag, ""+quote) % 2;
|
||||
// if (remainer == 1) {
|
||||
// dp("remainder = "+remainer);
|
||||
// throw new StringParsingException("Unmatched quote in "+tag);
|
||||
// }
|
||||
|
||||
// make sure that th last character is not an equals...
|
||||
// (check now so I don't need to check this every time..)
|
||||
if (tag.charAt(tag.length() - 1) == '=') {
|
||||
throw new RuntimeException("missing quoted value at the end of " + tag);
|
||||
}
|
||||
|
||||
HashMap<String, String> map = new HashMap<>();
|
||||
// recursively parse out the name value pairs...
|
||||
return parseNameQuotedValue(map, tag, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively parse out name value pairs (where the value is quoted, with
|
||||
* either single or double quotes).
|
||||
*/
|
||||
private static HashMap<String, String> parseNameQuotedValue(HashMap<String, String> map,
|
||||
String tag, int pos) throws RuntimeException {
|
||||
while (true) {
|
||||
|
||||
int equalsPos = tag.indexOf('=', pos);
|
||||
if (equalsPos > -1) {
|
||||
// check for begin quote...
|
||||
char firstQuote = tag.charAt(equalsPos + 1);
|
||||
if (firstQuote != SINGLE_QUOTE && firstQuote != DOUBLE_QUOTE) {
|
||||
throw new RuntimeException("missing begin quote at " + (equalsPos) + "["
|
||||
+ tag.charAt(equalsPos + 1) + "] in [" + tag + "]");
|
||||
}
|
||||
|
||||
// check for end quote...
|
||||
int endQuotePos = tag.indexOf(firstQuote, equalsPos + 2);
|
||||
if (endQuotePos == -1) {
|
||||
throw new RuntimeException("missing end quote [" + firstQuote + "] after " + pos + " in [" + tag + "]");
|
||||
}
|
||||
|
||||
// we have a valid name and value...
|
||||
// dp("pos="+pos+" equalsPos="+equalsPos+"
|
||||
// endQuotePos="+endQuotePos);
|
||||
String name = tag.substring(pos, equalsPos);
|
||||
// dp("name="+name+"; value="+value+";");
|
||||
|
||||
// trim off any whitespace from the front of name...
|
||||
name = trimFront(name, " ");
|
||||
if ((name.indexOf(SINGLE_QUOTE) > -1) || (name.indexOf(DOUBLE_QUOTE) > -1)) {
|
||||
throw new RuntimeException("attribute name contains a quote [" + name + "]");
|
||||
}
|
||||
|
||||
String value = tag.substring(equalsPos + 2, endQuotePos);
|
||||
map.put(name, value);
|
||||
|
||||
pos = endQuotePos + 1;
|
||||
|
||||
} else {
|
||||
// no more equals... stop parsing...
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of times a particular String occurs in another String.
|
||||
* e.g. count the number of single quotes.
|
||||
*/
|
||||
public static int countOccurances(String content, String occurs) {
|
||||
return countOccurances(content, occurs, 0, 0);
|
||||
}
|
||||
|
||||
private static int countOccurances(String content, String occurs, int pos, int countSoFar) {
|
||||
while (true) {
|
||||
int equalsPos = content.indexOf(occurs, pos);
|
||||
if (equalsPos > -1) {
|
||||
countSoFar += 1;
|
||||
pos = equalsPos + occurs.length();
|
||||
// dp("countSoFar="+countSoFar+" pos="+pos);
|
||||
} else {
|
||||
return countSoFar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses out a list of Name Value pairs that are delimited together. Will
|
||||
* always return a StringMap. If allNameValuePairs is null, or no name values
|
||||
* can be parsed out an empty StringMap is returned.
|
||||
*
|
||||
* @param allNameValuePairs the entire string to be parsed.
|
||||
* @param listDelimiter (typically ';') the delimited between the list
|
||||
* @param nameValueSeparator (typically '=') the separator between the name and value
|
||||
*/
|
||||
public static Map<String, String> delimitedToMap(String allNameValuePairs,
|
||||
String listDelimiter, String nameValueSeparator) {
|
||||
|
||||
HashMap<String, String> params = new HashMap<>();
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
allNameValuePairs = trimFront(allNameValuePairs, listDelimiter);
|
||||
return getKeyValue(params, 0, allNameValuePairs, listDelimiter, nameValueSeparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims off recurring strings from the front of a string.
|
||||
*
|
||||
* @param source the source string
|
||||
* @param trim the string to trim off the front
|
||||
*/
|
||||
public static String trimFront(String source, String trim) {
|
||||
while (true) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (source.indexOf(trim) == 0) {
|
||||
// dp("trim ...");
|
||||
source = source.substring(trim.length());
|
||||
} else {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the value is null or an empty string.
|
||||
*/
|
||||
@@ -163,110 +20,76 @@ public class StringHelper {
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses out a list of Name Value pairs that are delimited together. Will
|
||||
* always return a StringMap. If allNameValuePairs is null, or no name values
|
||||
* can be parsed out an empty StringMap is returned.
|
||||
*
|
||||
* @param source the entire string to be parsed.
|
||||
* @param listDelimiter (typically ';') the delimited between the list
|
||||
* @param nameValueSeparator (typically '=') the separator between the name and value
|
||||
*/
|
||||
public static Map<String, String> delimitedToMap(String source, String listDelimiter, String nameValueSeparator) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
if (source == null || source.isEmpty()) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
source = trimFront(source, listDelimiter);
|
||||
return delimitedToMap(params, source, listDelimiter, nameValueSeparator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims off recurring strings from the front of a string.
|
||||
*
|
||||
* @param source the source string
|
||||
* @param trim the string to trim off the front
|
||||
*/
|
||||
private static String trimFront(String source, String trim) {
|
||||
while (true) {
|
||||
if (source.indexOf(trim) == 0) {
|
||||
source = source.substring(trim.length());
|
||||
} else {
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively pulls out the key value pairs from a raw string.
|
||||
*/
|
||||
private static HashMap<String, String> getKeyValue(HashMap<String, String> map, int pos,
|
||||
String allNameValuePairs, String listDelimiter, String nameValueSeparator) {
|
||||
private static Map<String, String> delimitedToMap(Map<String, String> map, String source, String listDelimiter, String nameValueSeparator) {
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
|
||||
if (pos >= allNameValuePairs.length()) {
|
||||
// dp("end as "+pos+" >= "+allNameValuePairs.length() );
|
||||
if (pos >= source.length()) {
|
||||
return map;
|
||||
}
|
||||
|
||||
int equalsPos = allNameValuePairs.indexOf(nameValueSeparator, pos);
|
||||
int delimPos = allNameValuePairs.indexOf(listDelimiter, pos);
|
||||
|
||||
int equalsPos = source.indexOf(nameValueSeparator, pos);
|
||||
int delimPos = source.indexOf(listDelimiter, pos);
|
||||
if (delimPos == -1) {
|
||||
delimPos = allNameValuePairs.length();
|
||||
delimPos = source.length();
|
||||
}
|
||||
if (equalsPos == -1) {
|
||||
// dp("no more equals...");
|
||||
return map;
|
||||
}
|
||||
if (delimPos == (equalsPos + 1)) {
|
||||
// dp("Ignoring as nothing between delim and equals...
|
||||
// delim:"+delimPos+" eq:"+equalsPos);
|
||||
pos = delimPos + 1;
|
||||
continue;
|
||||
}
|
||||
if (equalsPos > delimPos) {
|
||||
// there is a key without a value?
|
||||
String key = allNameValuePairs.substring(pos, delimPos);
|
||||
String key = source.substring(pos, delimPos);
|
||||
key = key.trim();
|
||||
if (!key.isEmpty()) {
|
||||
map.put(key, null);
|
||||
}
|
||||
pos = delimPos + 1;
|
||||
continue;
|
||||
|
||||
}
|
||||
String key = allNameValuePairs.substring(pos, equalsPos);
|
||||
|
||||
if (delimPos > -1) {
|
||||
String value = allNameValuePairs.substring(equalsPos + 1, delimPos);
|
||||
// dp("cont "+key+","+value+" pos:"+pos+"
|
||||
// len:"+allNameValuePairs.length());
|
||||
key = key.trim();
|
||||
|
||||
map.put(key, value);
|
||||
pos = delimPos + 1;
|
||||
|
||||
// recurse the rest of the values...
|
||||
|
||||
} else {
|
||||
// dp("ERROR: delimPos < 0 ???");
|
||||
return map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a string that has delimited values (say comma delimited) in a
|
||||
* String[]. You must explicitly choose whether or not to include empty values
|
||||
* (say two commas that a right beside each other.
|
||||
* <p>
|
||||
* e.g. "alpha,beta,,theta"<br>
|
||||
* With keepEmpties true, this results in a String[] of size 4 with the third
|
||||
* one having a String of 0 length. With keepEmpties false, this results in a
|
||||
* String[] of size 3.
|
||||
* <p>
|
||||
* e.g. ",alpha,beta,,theta,"<br>
|
||||
* With keepEmpties true, this results in a String[] of size 6 with the
|
||||
* 1st,4th and 6th one having a String of 0 length. With keepEmpties false,
|
||||
* this results in a String[] of size 3.
|
||||
*/
|
||||
public static String[] delimitedToArray(String str, String delimiter, boolean keepEmpties) {
|
||||
|
||||
ArrayList<String> list = new ArrayList<>();
|
||||
int startPos = 0;
|
||||
delimiter(str, delimiter, keepEmpties, startPos, list);
|
||||
String[] result = new String[list.size()];
|
||||
return list.toArray(result);
|
||||
}
|
||||
|
||||
private static void delimiter(String str, String delimiter, boolean keepEmpties, int startPos,
|
||||
ArrayList<String> list) {
|
||||
|
||||
int endPos = str.indexOf(delimiter, startPos);
|
||||
if (endPos == -1) {
|
||||
if (startPos <= str.length()) {
|
||||
String lastValue = str.substring(startPos, str.length());
|
||||
if (keepEmpties || !lastValue.isEmpty()) {
|
||||
list.add(lastValue);
|
||||
}
|
||||
}
|
||||
// we have finished parsing the string...
|
||||
|
||||
} else {
|
||||
// get the delimited value... add it..
|
||||
String value = str.substring(startPos, endPos);
|
||||
if (keepEmpties || !value.isEmpty()) {
|
||||
list.add(value);
|
||||
}
|
||||
// recursively search as we are not at the end yet...
|
||||
delimiter(str, delimiter, keepEmpties, endPos + 1, list);
|
||||
String key = source.substring(pos, equalsPos);
|
||||
String value = source.substring(equalsPos + 1, delimPos);
|
||||
map.put(key.trim(), value);
|
||||
pos = delimPos + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,177 +102,22 @@ public class StringHelper {
|
||||
* @param replace the string used to replace match with
|
||||
* @return the source string after the search and replace
|
||||
*/
|
||||
public static String replaceString(String source, String match, String replace) {
|
||||
public static String replace(String source, String match, String replace) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (replace == null) {
|
||||
return source;
|
||||
}
|
||||
if (match == null) {
|
||||
throw new NullPointerException("match is null?");
|
||||
}
|
||||
if (match.equals(replace)) {
|
||||
return source;
|
||||
}
|
||||
return replaceString(source, match, replace, 30, 0, source.length());
|
||||
return source.replace(match, replace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Additionally specify the additionalSize to add to the buffer. This will
|
||||
* make the buffer bigger so that it doesn't have to grow when replacement
|
||||
* occurs.
|
||||
* Return new line and carriage return with space.
|
||||
*/
|
||||
public static String replaceString(String source, String match, String replace,
|
||||
int additionalSize, int startPos, int endPos) {
|
||||
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
char match0 = match.charAt(0);
|
||||
|
||||
int matchLength = match.length();
|
||||
|
||||
if (matchLength == 1 && replace.length() == 1) {
|
||||
char replace0 = replace.charAt(0);
|
||||
return source.replace(match0, replace0);
|
||||
}
|
||||
if (matchLength >= replace.length()) {
|
||||
additionalSize = 0;
|
||||
}
|
||||
|
||||
int sourceLength = source.length();
|
||||
int lastMatch = endPos - matchLength;
|
||||
|
||||
StringBuilder sb = new StringBuilder(sourceLength + additionalSize);
|
||||
|
||||
if (startPos > 0) {
|
||||
sb.append(source.substring(0, startPos));
|
||||
}
|
||||
|
||||
char sourceChar;
|
||||
boolean isMatch;
|
||||
int sourceMatchPos;
|
||||
|
||||
for (int i = startPos; i < sourceLength; i++) {
|
||||
sourceChar = source.charAt(i);
|
||||
if (i > lastMatch || sourceChar != match0) {
|
||||
sb.append(sourceChar);
|
||||
|
||||
} else {
|
||||
// check to see if this is a match
|
||||
isMatch = true;
|
||||
sourceMatchPos = i;
|
||||
|
||||
// check each following character...
|
||||
for (int j = 1; j < matchLength; j++) {
|
||||
sourceMatchPos++;
|
||||
if (source.charAt(sourceMatchPos) != match.charAt(j)) {
|
||||
isMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isMatch) {
|
||||
i = i + matchLength - 1;
|
||||
sb.append(replace);
|
||||
} else {
|
||||
// was not a match
|
||||
sb.append(sourceChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A search and replace with multiple matching strings.
|
||||
* <p>
|
||||
* Useful when converting CRNL CR and NL all to a BR tag for example.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String[] multi = { "\r\n", "\r", "\n" };
|
||||
* content = StringHelper.replaceStringMulti(content, multi, "<br/>");
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static String replaceStringMulti(String source, String[] match, String replace) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
return replaceStringMulti(source, match, replace, 30, 0, source.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Additionally specify an additional size estimate for the buffer plus start
|
||||
* and end positions.
|
||||
* <p>
|
||||
* The start and end positions can limit the search and replace. Otherwise
|
||||
* these default to startPos = 0 and endPos = source.length().
|
||||
* </p>
|
||||
*/
|
||||
public static String replaceStringMulti(String source, String[] match, String replace,
|
||||
int additionalSize, int startPos, int endPos) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
int shortestMatch = match[0].length();
|
||||
|
||||
char[] match0 = new char[match.length];
|
||||
for (int i = 0; i < match0.length; i++) {
|
||||
match0[i] = match[i].charAt(0);
|
||||
if (match[i].length() < shortestMatch) {
|
||||
shortestMatch = match[i].length();
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder(source.length() + additionalSize);
|
||||
|
||||
char sourceChar;
|
||||
|
||||
int len = source.length();
|
||||
int lastMatch = endPos - shortestMatch;
|
||||
|
||||
if (startPos > 0) {
|
||||
sb.append(source.substring(0, startPos));
|
||||
}
|
||||
|
||||
int matchCount;
|
||||
|
||||
for (int i = startPos; i < len; i++) {
|
||||
sourceChar = source.charAt(i);
|
||||
if (i > lastMatch) {
|
||||
sb.append(sourceChar);
|
||||
} else {
|
||||
matchCount = 0;
|
||||
for (int k = 0; k < match0.length; k++) {
|
||||
if (matchCount == 0 && sourceChar == match0[k]) {
|
||||
if (match[k].length() + i <= len) {
|
||||
|
||||
++matchCount;
|
||||
int j = 1;
|
||||
for (; j < match[k].length(); j++) {
|
||||
if (source.charAt(i + j) != match[k].charAt(j)) {
|
||||
--matchCount;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matchCount > 0) {
|
||||
i = i + j - 1;
|
||||
sb.append(replace);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (matchCount == 0) {
|
||||
sb.append(sourceChar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
public static String removeNewLines(String source) {
|
||||
source = source.replace('\n', ' ');
|
||||
return source.replace('\r', ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -462,13 +130,13 @@ public class StringHelper {
|
||||
}
|
||||
String[] result = SPLIT_NAMES.split(names);
|
||||
if (result.length == 0) {
|
||||
return EMPTY_STRING_ARRAY; // don't know if this ever can happen
|
||||
return EMPTY_STRING_ARRAY;
|
||||
}
|
||||
if ("".equals(result[0])) { // = input string starts with whitespace
|
||||
if (result.length == 1) { // = input string contains only whitespace
|
||||
if ("".equals(result[0])) { // input string starts with whitespace
|
||||
if (result.length == 1) { // input string contains only whitespace
|
||||
return EMPTY_STRING_ARRAY;
|
||||
} else {
|
||||
String ret[] = new String[result.length-1]; // remove first entry
|
||||
String[] ret = new String[result.length-1]; // remove first entry
|
||||
System.arraycopy(result, 1, ret, 0, ret.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
|
||||
/**
|
||||
* Controls the loading of ManyToOne and OneToOne relationships.
|
||||
*/
|
||||
public interface LoadBeanContext extends LoadSecondaryQuery {
|
||||
|
||||
/**
|
||||
* Register a BeanCollection into the load context.
|
||||
*/
|
||||
void register(BeanPropertyAssocMany<?> many, BeanCollection<?> collection);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
|
||||
/**
|
||||
@@ -56,6 +57,5 @@ public interface LoadContext {
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
void register(String path, BeanCollection<?> bc);
|
||||
|
||||
void register(String path, BeanPropertyAssocMany<?> many, BeanCollection<?> bc);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ 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;
|
||||
@@ -125,8 +124,7 @@ public class LoadManyRequest extends LoadRequest {
|
||||
if (extraWhere != null) {
|
||||
// replace special ${ta} placeholder with the base table alias
|
||||
// which is always t0 and add the extra where clause
|
||||
String ew = StringHelper.replaceString(extraWhere, "${ta}", "t0");
|
||||
query.where().raw(ew);
|
||||
query.where().raw(extraWhere.replace("${ta}", "t0"));
|
||||
}
|
||||
|
||||
query.setLazyLoadForParents(many);
|
||||
|
||||
@@ -33,6 +33,11 @@ import java.util.function.Predicate;
|
||||
*/
|
||||
public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanCollectionLoader {
|
||||
|
||||
/**
|
||||
* Return true if the L2 cache has been disabled.
|
||||
*/
|
||||
boolean isDisableL2Cache();
|
||||
|
||||
/**
|
||||
* Return the log manager.
|
||||
*/
|
||||
|
||||
+4
-55
@@ -33,13 +33,13 @@ import io.ebeaninternal.dbmigration.model.MTableIdentity;
|
||||
import io.ebeaninternal.server.deploy.IdentityMode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.ebean.util.StringHelper.replace;
|
||||
import static io.ebeaninternal.api.PlatformMatch.matchPlatform;
|
||||
import static io.ebeaninternal.dbmigration.ddlgeneration.platform.SplitColumns.split;
|
||||
|
||||
@@ -111,11 +111,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
this.columnName = column.getName();
|
||||
this.defaultValue = platformDdl.convertDefaultValue(column.getDefaultValue());
|
||||
boolean alterNotNull = Boolean.TRUE.equals(column.isNotnull());
|
||||
|
||||
if (column.getBefore().isEmpty() && alterNotNull && defaultValue == null) {
|
||||
handleStrictError(tableName, columnName);
|
||||
}
|
||||
|
||||
before = getScriptsForPlatform(column.getBefore());
|
||||
after = getScriptsForPlatform(column.getAfter());
|
||||
this.withHistory = withHistory;
|
||||
@@ -127,10 +125,8 @@ public class BaseTableDdl implements TableDdl {
|
||||
DdlMigrationHelp(AlterColumn alter) {
|
||||
this.tableName = alter.getTableName();
|
||||
this.columnName = alter.getColumnName();
|
||||
|
||||
String tmp = alter.getDefaultValue() != null ? alter.getDefaultValue() : alter.getCurrentDefaultValue();
|
||||
this.defaultValue = platformDdl.convertDefaultValue(tmp);
|
||||
|
||||
boolean alterNotNull = Boolean.TRUE.equals(alter.isNotnull());
|
||||
// here we add the platform's default update script
|
||||
withHistory = isTrue(alter.isWithHistory());
|
||||
@@ -186,9 +182,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Replaces Table name (${table}), Column name (${column}) and default value (${default}) in DDL.
|
||||
*/
|
||||
private String translate(String ddl, String tableName, String columnName, String defaultValue) {
|
||||
String ret = StringHelper.replaceString(ddl, "${table}", tableName);
|
||||
ret = StringHelper.replaceString(ret, "${column}", columnName);
|
||||
return StringHelper.replaceString(ret, "${default}", defaultValue);
|
||||
String ret = replace(ddl, "${table}", tableName);
|
||||
ret = replace(ret, "${column}", columnName);
|
||||
return replace(ret, "${default}", defaultValue);
|
||||
}
|
||||
|
||||
private void handleStrictError(String tableName, String columnName) {
|
||||
@@ -201,7 +197,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,7 +236,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
@Override
|
||||
public void generate(DdlWrite writer, CreateTable createTable) throws IOException {
|
||||
|
||||
reset();
|
||||
|
||||
String tableName = lowerTableName(createTable.getName());
|
||||
@@ -275,7 +269,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (platformDdl.isInlineForeignKeys()) {
|
||||
writeInlineForeignKeys(writer, createTable);
|
||||
}
|
||||
|
||||
apply.newLine().append(")");
|
||||
addTableStorageEngine(apply, createTable);
|
||||
addTableCommentInline(apply, createTable);
|
||||
@@ -285,9 +278,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
apply.endOfStatement();
|
||||
|
||||
addComments(apply, createTable);
|
||||
|
||||
writeUniqueOneToOneConstraints(writer, createTable);
|
||||
|
||||
if (isTrue(createTable.isWithHistory())) {
|
||||
// create history with rollback before the
|
||||
// associated drop table is written to rollback
|
||||
@@ -305,7 +296,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
// add blank line for a bit of whitespace between tables
|
||||
apply.end();
|
||||
writer.dropAll().end();
|
||||
|
||||
if (!platformDdl.isInlineForeignKeys()) {
|
||||
writeAddForeignKeys(writer, createTable);
|
||||
}
|
||||
@@ -324,7 +314,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (hasValue(tableComment)) {
|
||||
platformDdl.addTableComment(apply, createTable.getName(), tableComment);
|
||||
}
|
||||
|
||||
for (Column column : createTable.getColumn()) {
|
||||
if (!StringHelper.isNull(column.getComment())) {
|
||||
platformDdl.addColumnComment(apply, createTable.getName(), column.getName(), column.getComment());
|
||||
@@ -427,7 +416,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
writeForeignKey(write, createTable.getName(), column);
|
||||
}
|
||||
}
|
||||
|
||||
writeAddCompoundForeignKeys(write, createTable);
|
||||
}
|
||||
|
||||
@@ -448,7 +436,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
// no matching unique constraint so add the index
|
||||
fkeyBuffer.appendStatement(platformDdl.createIndex(new WriteCreateIndex(request.indexName(), tableName, request.cols(), false)));
|
||||
}
|
||||
|
||||
alterTableAddForeignKey(write.getOptions(), fkeyBuffer, request);
|
||||
fkeyBuffer.end();
|
||||
|
||||
@@ -456,7 +443,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (hasValue(request.indexName())) {
|
||||
write.dropAllForeignKeys().appendStatement(platformDdl.dropIndex(request.indexName(), tableName));
|
||||
}
|
||||
|
||||
write.dropAllForeignKeys().end();
|
||||
}
|
||||
|
||||
@@ -513,9 +499,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Write the unique constraints inline with the create table statement.
|
||||
*/
|
||||
protected void writeUniqueConstraints(DdlBuffer apply, CreateTable createTable) throws IOException {
|
||||
|
||||
boolean inlineUniqueWhenNullable = platformDdl.isInlineUniqueWhenNullable();
|
||||
|
||||
List<Column> columns = new WriteUniqueConstraint(createTable.getColumn()).uniqueKeys();
|
||||
for (Column column : columns) {
|
||||
if (Boolean.TRUE.equals(column.isNotnull()) || inlineUniqueWhenNullable) {
|
||||
@@ -532,12 +516,10 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Write the unique constraint inline with the create table statement.
|
||||
*/
|
||||
protected void inlineUniqueConstraintSingle(DdlBuffer buffer, Column column) throws IOException {
|
||||
|
||||
String uqName = column.getUnique();
|
||||
if (uqName == null) {
|
||||
uqName = column.getUniqueOneToOne();
|
||||
}
|
||||
|
||||
buffer.append(",").newLine();
|
||||
buffer.append(" constraint ").append(uqName).append(" unique ");
|
||||
buffer.append("(");
|
||||
@@ -549,7 +531,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Write the primary key constraint inline with the create table statement.
|
||||
*/
|
||||
protected void writePrimaryKeyConstraint(DdlBuffer buffer, String pkName, String[] pkColumns) throws IOException {
|
||||
|
||||
buffer.append(",").newLine();
|
||||
buffer.append(" constraint ").append(pkName).append(" primary key");
|
||||
appendColumns(pkColumns, buffer);
|
||||
@@ -559,7 +540,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Return as an array of string column names.
|
||||
*/
|
||||
protected String[] toColumnNames(List<Column> columns) {
|
||||
|
||||
String[] cols = new String[columns.size()];
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
cols[i] = columns.get(i).getName();
|
||||
@@ -682,13 +662,11 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
@Override
|
||||
public void generate(DdlWrite writer, AddColumn addColumn) throws IOException {
|
||||
|
||||
String tableName = addColumn.getTableName();
|
||||
List<Column> columns = addColumn.getColumn();
|
||||
for (Column column : columns) {
|
||||
alterTableAddColumn(writer.apply(), tableName, column, false, isTrue(addColumn.isWithHistory()));
|
||||
}
|
||||
|
||||
if (isTrue(addColumn.isWithHistory()) && historySupport == HistorySupport.TRIGGER_BASED) {
|
||||
// make same changes to the history table
|
||||
String historyTable = historyTable(tableName);
|
||||
@@ -697,14 +675,11 @@ public class BaseTableDdl implements TableDdl {
|
||||
alterTableAddColumn(writer.apply(), historyTable, column, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
for (Column column : columns) {
|
||||
if (hasValue(column.getReferences())) {
|
||||
writeForeignKey(writer, tableName, column);
|
||||
}
|
||||
}
|
||||
|
||||
// add a bit of whitespace
|
||||
writer.apply().end();
|
||||
}
|
||||
|
||||
@@ -713,9 +688,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
@Override
|
||||
public void generate(DdlWrite writer, DropTable dropTable) throws IOException {
|
||||
|
||||
dropTable(writer.apply(), dropTable.getName());
|
||||
|
||||
if (hasValue(dropTable.getSequenceCol())
|
||||
&& platformDdl.getPlatform().getDbIdentity().isSupportsSequence()) {
|
||||
String sequenceName = dropTable.getSequenceName();
|
||||
@@ -731,9 +704,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
*/
|
||||
@Override
|
||||
public void generate(DdlWrite writer, DropColumn dropColumn) throws IOException {
|
||||
|
||||
String tableName = dropColumn.getTableName();
|
||||
|
||||
alterTableDropColumn(writer.apply(), tableName, dropColumn.getColumnName());
|
||||
|
||||
if (isTrue(dropColumn.isWithHistory()) && historySupport == HistorySupport.TRIGGER_BASED) {
|
||||
@@ -741,7 +712,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
regenerateHistoryTriggers(tableName, HistoryTableUpdate.Change.DROP, dropColumn.getColumnName());
|
||||
alterTableDropColumn(writer.apply(), historyTable(tableName), dropColumn.getColumnName());
|
||||
}
|
||||
|
||||
writer.apply().end();
|
||||
}
|
||||
|
||||
@@ -826,7 +796,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Register the base table that we need to regenerate the history triggers on.
|
||||
*/
|
||||
protected void regenerateHistoryTriggers(String baseTableName, HistoryTableUpdate.Change change, String column) {
|
||||
|
||||
HistoryTableUpdate update = regenerateHistoryTriggers.computeIfAbsent(baseTableName, HistoryTableUpdate::new);
|
||||
update.add(change, column);
|
||||
}
|
||||
@@ -836,7 +805,6 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Will be called, if there is a type, dbdefault or notnull change.
|
||||
*/
|
||||
protected void alterColumnBaseAttributes(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
String ddl = platformDdl.alterColumnBaseAttributes(alter);
|
||||
if (hasValue(ddl)) {
|
||||
writer.apply().appendStatement(ddl);
|
||||
@@ -857,27 +825,22 @@ public class BaseTableDdl implements TableDdl {
|
||||
}
|
||||
|
||||
protected void alterColumnDefaultValue(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterColumnDefaultValue(alter.getTableName(), alter.getColumnName(), alter.getDefaultValue()));
|
||||
}
|
||||
|
||||
protected void dropCheckConstraint(DdlWrite writer, AlterColumn alter, String constraintName) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterTableDropConstraint(alter.getTableName(), constraintName));
|
||||
}
|
||||
|
||||
protected void addCheckConstraint(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterTableAddCheckConstraint(alter.getTableName(), alter.getCheckConstraintName(), alter.getCheckConstraint()));
|
||||
}
|
||||
|
||||
protected void alterColumnNotnull(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterColumnNotnull(alter.getTableName(), alter.getColumnName(), alter.isNotnull()));
|
||||
}
|
||||
|
||||
protected void alterColumnType(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
String ddl = platformDdl.alterColumnType(alter.getTableName(), alter.getColumnName(), alter.getType());
|
||||
if (hasValue(ddl)) {
|
||||
writer.apply().appendStatement(ddl);
|
||||
@@ -891,33 +854,26 @@ public class BaseTableDdl implements TableDdl {
|
||||
}
|
||||
|
||||
protected void alterColumnAddForeignKey(DdlWrite writer, AlterColumn alterColumn) throws IOException {
|
||||
|
||||
alterTableAddForeignKey(writer.getOptions(), writer.apply(), new WriteForeignKey(alterColumn));
|
||||
}
|
||||
|
||||
protected void alterColumnDropForeignKey(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterTableDropForeignKey(alter.getTableName(), alter.getDropForeignKey()));
|
||||
}
|
||||
|
||||
|
||||
protected void alterColumnDropUniqueConstraint(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
writer.apply().appendStatement(platformDdl.alterTableDropUniqueConstraint(alter.getTableName(), alter.getDropUnique()));
|
||||
}
|
||||
|
||||
protected void alterColumnAddUniqueOneToOneConstraint(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
addUniqueConstraint(writer, alter, alter.getUniqueOneToOne());
|
||||
}
|
||||
|
||||
protected void alterColumnAddUniqueConstraint(DdlWrite writer, AlterColumn alter) throws IOException {
|
||||
|
||||
addUniqueConstraint(writer, alter, alter.getUnique());
|
||||
}
|
||||
|
||||
protected void addUniqueConstraint(DdlWrite writer, AlterColumn alter, String uqName) throws IOException {
|
||||
|
||||
String[] cols = {alter.getColumnName()};
|
||||
boolean notNull = alter.isNotnull() != null ? alter.isNotnull() : Boolean.TRUE.equals(alter.isNotnull());
|
||||
writer.apply().appendStatement(platformDdl.alterTableAddUniqueConstraint(alter.getTableName(), uqName, cols, notNull ? null : cols));
|
||||
@@ -965,11 +921,4 @@ public class BaseTableDdl implements TableDdl {
|
||||
return Boolean.TRUE.equals(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return as an int value with 0 when it is null.
|
||||
*/
|
||||
protected int toInt(BigInteger value) {
|
||||
return (value == null) ? 0 : value.intValue();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-51
@@ -14,15 +14,9 @@ import java.io.IOException;
|
||||
*/
|
||||
public class MariaDbHistoryDdl implements PlatformHistoryDdl {
|
||||
|
||||
private String systemPeriodStart;
|
||||
private String systemPeriodEnd;
|
||||
private PlatformDdl platformDdl;
|
||||
|
||||
@Override
|
||||
public void configure(ServerConfig serverConfig, PlatformDdl platformDdl) {
|
||||
this.systemPeriodStart = serverConfig.getAsOfSysPeriod() + "From";
|
||||
this.systemPeriodEnd = serverConfig.getAsOfSysPeriod() + "To";
|
||||
this.platformDdl = platformDdl;
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,50 +25,19 @@ public class MariaDbHistoryDdl implements PlatformHistoryDdl {
|
||||
enableSystemVersioning(writer, baseTable);
|
||||
}
|
||||
|
||||
String getHistoryTable(String baseTable) {
|
||||
String historyTable = baseTable + "_history";
|
||||
if (baseTable.startsWith("[")) {
|
||||
historyTable = historyTable.replace("]", "") + "]";
|
||||
}
|
||||
if (historyTable.indexOf('.') == -1) {
|
||||
// history must contain schema, add the default schema if none was specified
|
||||
historyTable = "dbo." + historyTable;
|
||||
}
|
||||
return historyTable;
|
||||
}
|
||||
|
||||
private void enableSystemVersioning(DdlWrite writer, String baseTable) throws IOException {
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
|
||||
final String systemTime = String.format("system_time(%s, %s),", systemPeriodStart, systemPeriodEnd);
|
||||
apply.append("alter table ").append(baseTable).newLine()
|
||||
.append(" add column ").append(systemPeriodStart).append(" timestamp(6) generated always as row start,").newLine()
|
||||
.append(" add column ").append(systemPeriodEnd).append(" timestamp(6) generated always as row end,").newLine()
|
||||
.append(" add period for ").append(systemTime).newLine()
|
||||
.append(" add system versioning;").newLine();
|
||||
apply.append("alter table ").append(baseTable).append(" add system versioning").endOfStatement();
|
||||
|
||||
DdlBuffer drop = writer.dropAll();
|
||||
//drop.append("IF OBJECT_ID('").append(baseTable).append("', 'U') IS NOT NULL alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
|
||||
//drop.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement();
|
||||
drop.append("alter table ").append(baseTable).append(" drop system versioning").endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropHistoryTable(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException {
|
||||
String baseTable = dropHistoryTable.getBaseTable();
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
apply.append("-- dropping history support for ").append(baseTable).endOfStatement();
|
||||
// drop default constraints
|
||||
|
||||
apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodStart, DdlHelp.DROP_DEFAULT)).endOfStatement();
|
||||
apply.append(platformDdl.alterColumnDefaultValue(baseTable, systemPeriodEnd, DdlHelp.DROP_DEFAULT)).endOfStatement();
|
||||
// switch of versioning & period
|
||||
apply.append("alter table ").append(baseTable).append(" set (system_versioning = off)").endOfStatement();
|
||||
apply.append("alter table ").append(baseTable).append(" drop period for system_time").endOfStatement();
|
||||
// now drop tables & columns
|
||||
apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodStart).endOfStatement();
|
||||
apply.append("alter table ").append(baseTable).append(" drop column ").append(systemPeriodEnd).endOfStatement();
|
||||
//apply.append("IF OBJECT_ID('").append(baseTable).append("_history', 'U') IS NOT NULL drop table ").append(baseTable).append("_history").endOfStatement();
|
||||
apply.end();
|
||||
apply.append("alter table ").append(baseTable).append(" drop system versioning").endOfStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,15 +47,7 @@ public class MariaDbHistoryDdl implements PlatformHistoryDdl {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTriggers(DdlWrite writer, HistoryTableUpdate baseTable) throws IOException {
|
||||
// SQL Server 2016 does not need triggers
|
||||
DdlBuffer apply = writer.applyHistoryView();
|
||||
String baseTableName = baseTable.getBaseTable();
|
||||
apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = off (history_table=")
|
||||
.append(getHistoryTable(baseTableName)).append("))").endOfStatement();
|
||||
apply.append("-- history migration goes here").newLine();
|
||||
apply.append("-- alter table ").append(baseTableName).append(" set (system_versioning = on (history_table=")
|
||||
.append(getHistoryTable(baseTableName)).append("))").endOfStatement();
|
||||
|
||||
public void updateTriggers(DdlWrite writer, HistoryTableUpdate baseTable) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,4 +54,9 @@ public class PostgresDdl extends PlatformDdl {
|
||||
public String asIdentityColumn(String columnDefn, DdlIdentity identity) {
|
||||
return asIdentityStandardOptions(columnDefn, identity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String alterColumnType(String tableName, String columnName, String type) {
|
||||
return super.alterColumnType(tableName, columnName, type) + " using " + columnName + "::" + convert(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public class DatabasePlatformFactory {
|
||||
if (dbProductName.contains("oracle")) {
|
||||
return new OraclePlatform();
|
||||
} else if (dbProductName.contains("microsoft")) {
|
||||
throw new IllegalArgumentException("For SqlServer please explicitly choose either sqlserver16 or sqlserver17 as the platform via ServerConfig.setDatabasePlatformName. Refer to issue #1340 for more details");
|
||||
throw new IllegalArgumentException("For SqlServer please explicitly choose either sqlserver16 or sqlserver17 as the platform via DatabaseConfig.setDatabasePlatformName. Refer to issue #1340 for more details");
|
||||
} else if (dbProductName.contains("h2")) {
|
||||
return new H2Platform();
|
||||
} else if (dbProductName.contains("hsql database engine")) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import io.ebean.Update;
|
||||
import io.ebean.UpdateQuery;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
@@ -248,6 +249,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private final SlowQueryListener slowQueryListener;
|
||||
|
||||
private final boolean disableL2Cache;
|
||||
|
||||
/**
|
||||
* Create the DefaultServer.
|
||||
*/
|
||||
@@ -255,6 +258,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
this.logManager = config.getLogManager();
|
||||
this.dtoBeanManager = config.getDtoBeanManager();
|
||||
this.serverConfig = config.getServerConfig();
|
||||
this.disableL2Cache = serverConfig.isDisableL2Cache();
|
||||
this.serverCacheManager = cache;
|
||||
this.databasePlatform = config.getDatabasePlatform();
|
||||
this.backgroundExecutor = config.getBackgroundExecutor();
|
||||
@@ -311,9 +315,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
private void configureServerPlugins() {
|
||||
|
||||
autoTuneService.startup();
|
||||
|
||||
for (Plugin plugin : serverPlugins) {
|
||||
plugin.configure(this);
|
||||
}
|
||||
@@ -323,7 +325,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* Execute all the plugins with an online flag indicating the DB is up or not.
|
||||
*/
|
||||
public void executePlugins(boolean online) {
|
||||
|
||||
if (!serverConfig.isDocStoreOnly()) {
|
||||
ddlGenerator.execute(online);
|
||||
}
|
||||
@@ -332,6 +333,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableL2Cache() {
|
||||
return disableL2Cache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiLogManager log() {
|
||||
return logManager;
|
||||
@@ -386,6 +392,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return metaInfoManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Platform getPlatform() {
|
||||
return databasePlatform.getPlatform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiServer getPluginApi() {
|
||||
return this;
|
||||
@@ -471,14 +482,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* Shutdown the services like threads and DataSource.
|
||||
*/
|
||||
private void shutdownInternal(boolean shutdownDataSource, boolean deregisterDriver) {
|
||||
|
||||
logger.debug("Shutting down instance:{}", serverName);
|
||||
if (shutdown) {
|
||||
// already shutdown
|
||||
return;
|
||||
}
|
||||
shutdownPlugins();
|
||||
|
||||
autoTuneService.shutdown();
|
||||
// shutdown background threads
|
||||
backgroundExecutor.shutdown();
|
||||
@@ -492,11 +501,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
private void shutdownPlugins() {
|
||||
|
||||
if (serverConfig.isDumpMetricsOnShutdown()) {
|
||||
new DumpMetrics(this, serverConfig.getDumpMetricsOptions()).dump();
|
||||
}
|
||||
|
||||
for (Plugin plugin : serverPlugins) {
|
||||
try {
|
||||
plugin.shutdown();
|
||||
@@ -601,7 +608,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (a == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanDescriptor<?> desc = getBeanDescriptor(a.getClass());
|
||||
return DiffHelp.diff(a, b, desc);
|
||||
}
|
||||
@@ -626,10 +632,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
|
||||
TransactionEventTable evt = new TransactionEventTable();
|
||||
evt.add(tableName, inserts, updates, deletes);
|
||||
|
||||
externalModification(evt);
|
||||
}
|
||||
|
||||
@@ -697,14 +701,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T> T getReference(Class<T> type, Object id) {
|
||||
|
||||
if (id == null) {
|
||||
throw new NullPointerException("The id is null");
|
||||
}
|
||||
|
||||
BeanDescriptor desc = getBeanDescriptor(type);
|
||||
id = desc.convertId(id);
|
||||
|
||||
PersistenceContext pc = null;
|
||||
SpiTransaction t = transactionManager.getActive();
|
||||
if (t != null) {
|
||||
@@ -719,12 +720,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (inheritInfo == null || inheritInfo.isConcrete()) {
|
||||
return (T) desc.contextRef(pc, null, false, id);
|
||||
}
|
||||
|
||||
BeanProperty idProp = desc.getIdProperty();
|
||||
if (idProp == null) {
|
||||
throw new PersistenceException("No ID properties for this type? " + desc);
|
||||
}
|
||||
|
||||
// we actually need to do a query because we don't know the type without the discriminator
|
||||
// value, just select the id property and discriminator column (auto added)
|
||||
return find(type).select(idProp.getName()).setId(id).findOne();
|
||||
@@ -769,13 +768,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
ScopedTransaction scopeTrans = transactionManager.beginScopedTransaction(scope);
|
||||
try {
|
||||
return c.call();
|
||||
|
||||
} catch (Error e) {
|
||||
throw scopeTrans.caughtError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(scopeTrans.caughtThrowable(e));
|
||||
|
||||
} finally {
|
||||
scopeTrans.complete();
|
||||
}
|
||||
@@ -791,13 +787,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
ScopedTransaction t = transactionManager.beginScopedTransaction(scope);
|
||||
try {
|
||||
r.run();
|
||||
|
||||
} catch (Error e) {
|
||||
throw t.caughtError(e);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(t.caughtThrowable(e));
|
||||
|
||||
} finally {
|
||||
t.complete();
|
||||
}
|
||||
@@ -879,7 +872,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> void sort(List<T> list, String sortByClause) {
|
||||
|
||||
if (list == null) {
|
||||
throw new NullPointerException("list is null");
|
||||
}
|
||||
@@ -901,7 +893,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> Set<String> validateQuery(Query<T> query) {
|
||||
|
||||
BeanDescriptor<T> beanDescriptor = getBeanDescriptor(query.getBeanType());
|
||||
if (beanDescriptor == null) {
|
||||
throw new PersistenceException("BeanDescriptor not found, is [" + query.getBeanType() + "] an entity bean?");
|
||||
@@ -1010,13 +1001,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
String m = beanType.getName() + " is NOT an Entity Bean registered with this server?";
|
||||
throw new PersistenceException(m);
|
||||
}
|
||||
|
||||
return new DefaultOrmUpdate<>(beanType, this, desc.getBaseTable(), ormUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> DtoQuery<T> findDto(Class<T> dtoType, String sql) {
|
||||
|
||||
DtoBeanDescriptor<T> descriptor = dtoBeanManager.getDescriptor(dtoType);
|
||||
return new DefaultDtoQuery<>(this, descriptor, sql.trim());
|
||||
}
|
||||
@@ -1033,14 +1022,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> DtoQuery<T> findDto(Class<T> dtoType, SpiQuery<?> ormQuery) {
|
||||
|
||||
DtoBeanDescriptor<T> descriptor = dtoBeanManager.getDescriptor(dtoType);
|
||||
return new DefaultDtoQuery<>(this, descriptor, ormQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiResultSet findResultSet(SpiQuery<?> ormQuery, SpiTransaction transaction) {
|
||||
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(ormQuery.getType(), ormQuery, transaction);
|
||||
request.initTransIfRequired();
|
||||
return request.findResultSet();
|
||||
@@ -1073,7 +1060,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> beanType, Object uid) {
|
||||
|
||||
return find(beanType, uid, null);
|
||||
}
|
||||
|
||||
@@ -1082,33 +1068,27 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public <T> T find(Class<T> beanType, Object id, Transaction t) {
|
||||
|
||||
if (id == null) {
|
||||
throw new NullPointerException("The id is null");
|
||||
}
|
||||
|
||||
Query<T> query = createQuery(beanType).setId(id);
|
||||
return findId(query, t);
|
||||
}
|
||||
|
||||
<T> SpiOrmQueryRequest<T> createQueryRequest(Type type, Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = buildQueryRequest(type, query, t);
|
||||
request.prepareQuery();
|
||||
return request;
|
||||
}
|
||||
|
||||
<T> SpiOrmQueryRequest<T> buildQueryRequest(Type type, Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
spiQuery.setType(type);
|
||||
spiQuery.checkNamedParameters();
|
||||
|
||||
return buildQueryRequest(spiQuery, t);
|
||||
}
|
||||
|
||||
private <T> SpiOrmQueryRequest<T> buildQueryRequest(SpiQuery<T> query, Transaction t) {
|
||||
|
||||
if (t == null) {
|
||||
t = currentServerTransaction();
|
||||
}
|
||||
@@ -1118,9 +1098,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
// to define the 'default' select clause
|
||||
query.setDefaultSelectClause();
|
||||
}
|
||||
|
||||
query.selectAllForLazyLoadProperty();
|
||||
|
||||
ProfileLocation profileLocation = query.getProfileLocation();
|
||||
if (profileLocation != null) {
|
||||
profileLocation.obtain();
|
||||
@@ -1129,7 +1107,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (query.getParentNode() == null) {
|
||||
query.setOrigin(createCallOrigin());
|
||||
}
|
||||
|
||||
return new OrmQueryRequest<>(this, queryEngine, query, (SpiTransaction) t);
|
||||
}
|
||||
|
||||
@@ -1138,15 +1115,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T findIdCheckPersistenceContextAndCache(Transaction transaction, SpiQuery<T> query, Object id) {
|
||||
|
||||
SpiTransaction t = (SpiTransaction) transaction;
|
||||
if (t == null) {
|
||||
t = currentServerTransaction();
|
||||
}
|
||||
|
||||
BeanDescriptor<T> desc = query.getBeanDescriptor();
|
||||
id = desc.convertId(id);
|
||||
|
||||
PersistenceContext pc = null;
|
||||
if (t != null && useTransactionPersistenceContext(query)) {
|
||||
// first look in the transaction scoped persistence context
|
||||
@@ -1162,11 +1136,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!query.isBeanCacheGet() || (t != null && t.isSkipCache())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Hit the L2 bean cache
|
||||
return desc.cacheBeanGet(id, query.isReadOnly(), pc);
|
||||
}
|
||||
@@ -1189,7 +1161,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T findId(Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
spiQuery.setType(Type.BEAN);
|
||||
if (SpiQuery.Mode.NORMAL == spiQuery.getMode() && !spiQuery.isForceHitDatabase()) {
|
||||
@@ -1200,7 +1171,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
SpiOrmQueryRequest<T> request = buildQueryRequest(spiQuery, t);
|
||||
request.prepareQuery();
|
||||
if (request.isUseDocStore()) {
|
||||
@@ -1209,7 +1179,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return (T) request.findId();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1222,17 +1191,14 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> T findOne(Query<T> query, Transaction transaction) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
if (spiQuery.isFindById()) {
|
||||
// actually a find by Id query
|
||||
return findId(query, transaction);
|
||||
}
|
||||
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
}
|
||||
|
||||
// a query that is expected to return either 0 or 1 beans
|
||||
List<T> list = findList(query, transaction, true);
|
||||
return extractUnique(list);
|
||||
@@ -1241,10 +1207,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
private <T> T extractUnique(List<T> list) {
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
|
||||
} else if (list.size() > 1) {
|
||||
throw new NonUniqueResultException("Unique expecting 0 or 1 results but got [" + list.size() + "]");
|
||||
|
||||
} else {
|
||||
return list.get(0);
|
||||
}
|
||||
@@ -1253,7 +1217,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T> Set<T> findSet(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.SET, query, t);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
@@ -1270,7 +1233,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <K, T> Map<K, T> findMap(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.MAP, query, t);
|
||||
request.resetBeanCacheAutoMode(false);
|
||||
if ((t == null || !t.isSkipCache()) && request.getFromBeanCache()) {
|
||||
@@ -1292,7 +1254,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A, T> List<A> findSingleAttributeList(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ATTRIBUTE, query, t);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
@@ -1301,7 +1262,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return (List<A>) request.findSingleAttributeList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1309,7 +1269,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> int findCount(Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> spiQuery = ((SpiQuery<T>) query);
|
||||
if (!spiQuery.isDistinct()) {
|
||||
spiQuery = spiQuery.copy();
|
||||
@@ -1319,7 +1278,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> int findCountWithCopy(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.COUNT, query, t);
|
||||
Integer result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
@@ -1328,7 +1286,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findCount();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1342,7 +1299,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> boolean exists(Query<?> ormQuery, Transaction transaction) {
|
||||
|
||||
Query<?> ormQueryCopy = ormQuery.copy();
|
||||
ormQueryCopy.setMaxRows(1);
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, ormQueryCopy, transaction);
|
||||
@@ -1350,7 +1306,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
request.initTransIfRequired();
|
||||
List<Object> ids = request.findIds();
|
||||
return !ids.isEmpty();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1358,14 +1313,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <A, T> List<A> findIds(Query<T> query, Transaction t) {
|
||||
|
||||
return findIdsWithCopy(((SpiQuery<T>) query).copy(), t);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <A, T> List<A> findIdsWithCopy(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query, t);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
@@ -1378,7 +1331,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findIds();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1386,7 +1338,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> int delete(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.DELETE, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1410,7 +1361,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> int update(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.UPDATE, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1423,82 +1373,60 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> FutureRowCount<T> findFutureCount(Query<T> q, Transaction t) {
|
||||
|
||||
SpiQuery<T> copy = ((SpiQuery<T>) q).copy();
|
||||
copy.setFutureFetch(true);
|
||||
|
||||
Transaction newTxn = createTransaction();
|
||||
|
||||
CallableQueryCount<T> call = new CallableQueryCount<>(this, copy, newTxn);
|
||||
|
||||
QueryFutureRowCount<T> queryFuture = new QueryFutureRowCount<>(call);
|
||||
QueryFutureRowCount<T> queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<T>(this, copy, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> copy = ((SpiQuery<T>) query).copy();
|
||||
copy.setFutureFetch(true);
|
||||
|
||||
Transaction newTxn = createTransaction();
|
||||
|
||||
CallableQueryIds<T> call = new CallableQueryIds<>(this, copy, newTxn);
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(call);
|
||||
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<T>(this, copy, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(Query<T> query, Transaction t) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
spiQuery.setFutureFetch(true);
|
||||
|
||||
// FutureList query always run in it's own persistence content
|
||||
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
|
||||
|
||||
if (!spiQuery.isDisableReadAudit()) {
|
||||
BeanDescriptor<T> desc = beanDescriptorManager.getBeanDescriptor(spiQuery.getBeanType());
|
||||
desc.readAuditFutureList(spiQuery);
|
||||
}
|
||||
|
||||
// Create a new transaction solely to execute the findList() at some future time
|
||||
Transaction newTxn = createTransaction();
|
||||
CallableQueryList<T> call = new CallableQueryList<>(this, spiQuery, newTxn);
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(call);
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<T>(this, spiQuery, newTxn));
|
||||
backgroundExecutor.execute(queryFuture.getFutureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction) {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
int maxRows = spiQuery.getMaxRows();
|
||||
if (maxRows == 0) {
|
||||
throw new PersistenceException("maxRows must be specified for findPagedList() query");
|
||||
}
|
||||
|
||||
if (spiQuery.isUseDocStore()) {
|
||||
return docStore().findPagedList(createQueryRequest(Type.LIST, query, transaction));
|
||||
}
|
||||
|
||||
return new LimitOffsetPagedList<>(this, spiQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryIterator<T> findIterate(Query<T> query, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findIterate();
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.endTransIfRequired();
|
||||
throw ex;
|
||||
@@ -1542,14 +1470,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> void findEach(Query<T> query, Consumer<T> consumer, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
|
||||
if (request.isUseDocStore()) {
|
||||
docStore().findEach(request, consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
request.initTransIfRequired();
|
||||
request.findEach(consumer);
|
||||
// no try finally - findEach guarantee's cleanup of the transaction if required
|
||||
@@ -1557,13 +1482,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
if (request.isUseDocStore()) {
|
||||
docStore().findEachWhile(request, consumer);
|
||||
return;
|
||||
}
|
||||
|
||||
request.initTransIfRequired();
|
||||
request.findEachWhile(consumer);
|
||||
// no try finally - findEachWhile guarantee's cleanup of the transaction if required
|
||||
@@ -1571,12 +1494,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> List<Version<T>> findVersions(Query<T> query, Transaction transaction) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, transaction);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findVersions();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1589,14 +1510,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> findList(Query<T> query, Transaction t, boolean findOne) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.LIST, query, t);
|
||||
request.resetBeanCacheAutoMode(findOne);
|
||||
if ((t == null || !t.isSkipCache()) && request.getFromBeanCache()) {
|
||||
// hit bean cache and got all results from cache
|
||||
return request.getBeanCacheHits();
|
||||
}
|
||||
|
||||
request.prepareQuery();
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
@@ -1605,11 +1524,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (request.isUseDocStore()) {
|
||||
return docStore().findList(request);
|
||||
}
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1617,7 +1534,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public SqlRow findOne(SqlQuery query, Transaction t) {
|
||||
|
||||
// no findId() method for SqlQuery...
|
||||
// a query that is expected to return either 0 or 1 rows
|
||||
List<SqlRow> list = findList(query, t);
|
||||
@@ -1626,7 +1542,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction) {
|
||||
|
||||
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, transaction);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1638,7 +1553,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction) {
|
||||
|
||||
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, transaction);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1650,12 +1564,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public List<SqlRow> findList(SqlQuery query, Transaction t) {
|
||||
|
||||
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1702,7 +1614,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
request.findEach(consumer);
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1714,7 +1625,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
request.findEachWhile(consumer);
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1726,7 +1636,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1738,7 +1647,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return extractUnique(request.findList());
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
@@ -1789,7 +1697,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public void updateAll(Collection<?> beans, Transaction transaction) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -1830,7 +1737,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public void insertAll(Collection<?> beans, Transaction transaction) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -1844,7 +1750,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> List<T> publish(Query<T> query, Transaction transaction) {
|
||||
|
||||
return executeInTrans((txn) -> persister.publish(query, txn), transaction);
|
||||
}
|
||||
|
||||
@@ -1860,7 +1765,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> T publish(Class<T> beanType, Object id, Transaction transaction) {
|
||||
|
||||
Query<T> query = find(beanType).setId(id);
|
||||
List<T> liveBeans = publish(query, transaction);
|
||||
return (liveBeans.size() == 1) ? liveBeans.get(0) : null;
|
||||
@@ -1868,13 +1772,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public <T> List<T> draftRestore(Query<T> query, Transaction transaction) {
|
||||
|
||||
return executeInTrans((txn) -> persister.draftRestore(query, txn), transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T draftRestore(Class<T> beanType, Object id, Transaction transaction) {
|
||||
|
||||
Query<T> query = find(beanType).setId(id);
|
||||
List<T> beans = draftRestore(query, transaction);
|
||||
return (beans.size() == 1) ? beans.get(0) : null;
|
||||
@@ -1919,7 +1821,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* Save all beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
private int saveAllInternal(Collection<?> beans, Transaction transaction) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1930,7 +1831,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
persister.save(checkEntityBean(bean), txn);
|
||||
saveCount++;
|
||||
}
|
||||
|
||||
txn.flushBatchOnCollection();
|
||||
return saveCount;
|
||||
}, transaction);
|
||||
@@ -1957,7 +1857,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
private int delete(Class<?> beanType, Object id, Transaction transaction, boolean permanent) {
|
||||
|
||||
return executeInTrans((txn) -> persister.delete(beanType, id, txn, permanent), transaction);
|
||||
}
|
||||
|
||||
@@ -2043,19 +1942,16 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* Delete all the beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
private int deleteAllInternal(Collection<?> beans, Transaction transaction, boolean permanent) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return executeInTrans((txn) -> {
|
||||
|
||||
txn.checkBatchEscalationOnCollection();
|
||||
int deleteCount = 0;
|
||||
for (Object bean : beans) {
|
||||
persister.delete(checkEntityBean(bean), txn, permanent);
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
txn.flushBatchOnCollection();
|
||||
return deleteCount;
|
||||
}, transaction);
|
||||
@@ -2156,7 +2052,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public boolean isSupportedType(java.lang.reflect.Type genericType) {
|
||||
|
||||
TypeInfo typeInfo = ParamTypeHelper.getTypeInfo(genericType);
|
||||
return typeInfo != null && getBeanDescriptor(typeInfo.getBeanType()) != null;
|
||||
}
|
||||
@@ -2279,7 +2174,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
P result = fun.apply(wrap.transaction());
|
||||
wrap.commitIfCreated();
|
||||
return result;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
wrap.endIfCreated();
|
||||
throw e;
|
||||
@@ -2292,7 +2186,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* Create a transaction if one is not currently active.
|
||||
*/
|
||||
ObtainedTransaction initTransIfRequired(Transaction t) {
|
||||
|
||||
if (t != null) {
|
||||
return new ObtainedTransaction((SpiTransaction) t);
|
||||
}
|
||||
@@ -2361,16 +2254,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public Set<Property> checkUniqueness(Object bean, Transaction transaction) {
|
||||
|
||||
EntityBean entityBean = checkEntityBean(bean);
|
||||
BeanDescriptor<?> beanDesc = getBeanDescriptor(entityBean.getClass());
|
||||
|
||||
BeanProperty idProperty = beanDesc.getIdProperty();
|
||||
// if the ID of the Property is null we are unable to check uniqueness
|
||||
if (idProperty == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
Object id = idProperty.getVal(entityBean);
|
||||
if (entityBean._ebean_getIntercept().isNew() && id != null) {
|
||||
// Primary Key is changeable only on new models - so skip check if we are not
|
||||
@@ -2383,7 +2273,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
for (BeanProperty[] props : beanDesc.getUniqueProps()) {
|
||||
Set<Property> ret = checkUniqueness(entityBean, beanDesc, props, transaction);
|
||||
if (ret != null) {
|
||||
@@ -2400,12 +2289,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
BeanProperty idProperty = beanDesc.getIdProperty();
|
||||
Query<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
|
||||
ExpressionList<?> exprList = query.where();
|
||||
|
||||
if (!entityBean._ebean_getIntercept().isNew()) {
|
||||
// if model is not new, exclude ourself.
|
||||
exprList.ne(idProperty.getName(), idProperty.getVal(entityBean));
|
||||
}
|
||||
|
||||
for (Property prop : props) {
|
||||
Object value = prop.getVal(entityBean);
|
||||
if (value == null) {
|
||||
@@ -2413,7 +2300,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
exprList.eq(prop.getName(), value);
|
||||
}
|
||||
|
||||
if (findCount(query, transaction) > 0) {
|
||||
Set<Property> ret = new LinkedHashSet<>();
|
||||
Collections.addAll(ret, props);
|
||||
|
||||
@@ -7,22 +7,18 @@ import java.util.HashMap;
|
||||
* <p>
|
||||
* Using this for now instead of String.intern() to avoid any unexpected
|
||||
* increase in PermGen space.
|
||||
* </p>
|
||||
*/
|
||||
public final class InternString {
|
||||
|
||||
private static final HashMap<String, String> map = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Return the shared instance of this string.
|
||||
*/
|
||||
public static String intern(String s) {
|
||||
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (map) {
|
||||
String v = map.get(s);
|
||||
@@ -32,7 +28,6 @@ public final class InternString {
|
||||
map.put(s, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,7 +505,7 @@ public class InternalConfiguration {
|
||||
private DataTimeZone initDataTimeZone() {
|
||||
String tz = serverConfig.getDataTimeZone();
|
||||
if (tz == null) {
|
||||
if (isMySqlOrMariaDB(getPlatform())) {
|
||||
if (isMySql(getPlatform())) {
|
||||
return new MySqlDataTimeZone();
|
||||
}
|
||||
return new NoDataTimeZone();
|
||||
@@ -517,8 +517,8 @@ public class InternalConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMySqlOrMariaDB(Platform platform) {
|
||||
return platform.base() == Platform.MYSQL || platform.base() == Platform.MARIADB;
|
||||
private boolean isMySql(Platform platform) {
|
||||
return platform.base() == Platform.MYSQL;
|
||||
}
|
||||
|
||||
public DataTimeZone getDataTimeZone() {
|
||||
|
||||
@@ -8,7 +8,9 @@ import io.ebean.bean.CallStack;
|
||||
*/
|
||||
class NoopCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
private final CallOrigin COMMON = new CallStack(Thread.currentThread().getStackTrace(), 0, 0);
|
||||
private static final StackTraceElement E0 = new StackTraceElement("none", "none", "none", 0);
|
||||
|
||||
private final CallOrigin COMMON = new CallStack(new StackTraceElement[]{E0}, 0, 0);
|
||||
|
||||
@Override
|
||||
public CallOrigin createCallOrigin() {
|
||||
|
||||
@@ -698,8 +698,9 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getFromQueryCache() {
|
||||
|
||||
if (query.getUseQueryCache() == CacheMode.OFF || (transaction != null && transaction.isSkipCache())) {
|
||||
if (query.getUseQueryCache() == CacheMode.OFF
|
||||
|| (transaction != null && transaction.isSkipCache())
|
||||
|| ebeanServer.isDisableL2Cache()) {
|
||||
return null;
|
||||
} else {
|
||||
cacheKey = query.queryHash();
|
||||
|
||||
@@ -188,7 +188,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type, int flags) {
|
||||
|
||||
super(server, t, persistExecute);
|
||||
this.entityBean = (EntityBean) bean;
|
||||
this.intercept = entityBean._ebean_getIntercept();
|
||||
@@ -204,7 +203,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
if (Flags.isRecurse(flags)) {
|
||||
this.persistCascade = t.isPersistCascade();
|
||||
}
|
||||
|
||||
if (this.type == Type.UPDATE) {
|
||||
if (intercept.isNew()) {
|
||||
// 'stateless update' - set loaded properties as dirty
|
||||
@@ -279,7 +277,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Init the transaction and also check for batch on cascade escalation.
|
||||
*/
|
||||
public void initTransIfRequiredWithBatchCascade() {
|
||||
|
||||
if (createImplicitTransIfRequired()) {
|
||||
docStoreMode = calcDocStoreMode(transaction, type);
|
||||
}
|
||||
@@ -317,9 +314,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void onUpdateGeneratedProperties() {
|
||||
|
||||
for (BeanProperty prop : beanDescriptor.propertiesGenUpdate()) {
|
||||
|
||||
GeneratedProperty generatedProperty = prop.getGeneratedProperty();
|
||||
if (prop.isVersion()) {
|
||||
if (isLoadedProperty(prop)) {
|
||||
@@ -451,7 +446,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Return true if any of the given properties are dirty.
|
||||
*/
|
||||
public boolean hasDirtyProperty(int[] propertyPositions) {
|
||||
|
||||
for (int propertyPosition : propertyPositions) {
|
||||
if (dirtyProperties[propertyPosition]) {
|
||||
return true;
|
||||
@@ -517,7 +511,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
@Override
|
||||
public void docStoreUpdate(DocStoreUpdateContext txn) throws IOException {
|
||||
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
beanDescriptor.docStoreInsert(idValue, this, txn);
|
||||
@@ -554,7 +547,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
public void addToPersistMap(BeanPersistIdMap beanPersistMap) {
|
||||
|
||||
beanPersistMap.add(beanDescriptor, type, idValue);
|
||||
}
|
||||
|
||||
@@ -564,19 +556,15 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
case INSERT:
|
||||
beanPersistListener.inserted(bean);
|
||||
break;
|
||||
|
||||
case UPDATE:
|
||||
beanPersistListener.updated(bean, updatedProperties);
|
||||
break;
|
||||
|
||||
case DELETE:
|
||||
beanPersistListener.deleted(bean);
|
||||
break;
|
||||
|
||||
case DELETE_SOFT:
|
||||
beanPersistListener.softDeleted(bean);
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
@@ -785,7 +773,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
case INSERT:
|
||||
executeInsert();
|
||||
return -1;
|
||||
|
||||
case UPDATE:
|
||||
if (beanPersistListener != null) {
|
||||
// store the updated properties for sending later
|
||||
@@ -793,15 +780,12 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
executeUpdate();
|
||||
return -1;
|
||||
|
||||
case DELETE_SOFT:
|
||||
prepareForSoftDelete();
|
||||
executeSoftDelete();
|
||||
return -1;
|
||||
|
||||
case DELETE:
|
||||
return executeDelete();
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Invalid type " + type);
|
||||
}
|
||||
@@ -811,13 +795,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Soft delete is executed as update so we want to set deleted=true property.
|
||||
*/
|
||||
private void prepareForSoftDelete() {
|
||||
|
||||
beanDescriptor.setSoftDeleteValue(entityBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeOrQueue() {
|
||||
|
||||
boolean batch = isBatchThisRequest();
|
||||
try {
|
||||
BatchControl control = transaction.getBatchControl();
|
||||
@@ -827,7 +809,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
if (batch) {
|
||||
control = persistExecute.createBatchControl(transaction);
|
||||
return control.executeOrQueue(this, true);
|
||||
|
||||
} else {
|
||||
return executeNoBatch();
|
||||
}
|
||||
@@ -926,7 +907,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
controllerPost();
|
||||
}
|
||||
setNotifyCache();
|
||||
|
||||
boolean isChangeLog = beanDescriptor.isChangeLog();
|
||||
if (type == Type.UPDATE && (isChangeLog || notifyCache || docStoreMode == DocStoreMode.UPDATE)) {
|
||||
// get the dirty properties for update notification to the doc store
|
||||
@@ -935,16 +915,13 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
if (isChangeLog) {
|
||||
changeLog();
|
||||
}
|
||||
|
||||
// if bean persisted again then should result in an update
|
||||
intercept.setLoaded();
|
||||
if (isInsert()) {
|
||||
postInsert();
|
||||
}
|
||||
|
||||
addPostCommitListeners();
|
||||
notifyCacheOnPostExecute();
|
||||
|
||||
if (isLogSummary()) {
|
||||
logSummary();
|
||||
}
|
||||
@@ -994,7 +971,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void logSummary() {
|
||||
|
||||
String draft = (beanDescriptor.isDraftable() && !publish) ? " draft[true]" : "";
|
||||
String name = beanDescriptor.getName();
|
||||
switch (type) {
|
||||
@@ -1136,7 +1112,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* of queue events or list of update events.
|
||||
*/
|
||||
public void addDocStoreUpdates(DocStoreUpdates docStoreUpdates) {
|
||||
|
||||
if (type == Type.UPDATE) {
|
||||
beanDescriptor.docStoreUpdateEmbedded(this, docStoreUpdates);
|
||||
}
|
||||
@@ -1165,7 +1140,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* </p>
|
||||
*/
|
||||
private boolean determineUpdateAllLoadedProperties() {
|
||||
|
||||
Boolean txnUpdateAll = transaction.isUpdateAllLoadedProperties();
|
||||
if (txnUpdateAll != null) {
|
||||
// use the setting explicitly set on the transaction
|
||||
@@ -1174,7 +1148,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
// if using batch use the server default setting
|
||||
requestUpdateAllLoadedProps = isBatchThisRequest() && ebeanServer.isUpdateAllPropertiesInBatch();
|
||||
}
|
||||
|
||||
return requestUpdateAllLoadedProps;
|
||||
}
|
||||
|
||||
@@ -1196,25 +1169,21 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Return the key for an update persist request.
|
||||
*/
|
||||
public String getUpdatePlanHash() {
|
||||
|
||||
StringBuilder key;
|
||||
if (determineUpdateAllLoadedProperties()) {
|
||||
key = intercept.getLoadedPropertyKey();
|
||||
} else {
|
||||
key = intercept.getDirtyPropertyKey();
|
||||
}
|
||||
|
||||
BeanProperty versionProperty = beanDescriptor.getVersionProperty();
|
||||
if (versionProperty != null) {
|
||||
if (intercept.isLoadedProperty(versionProperty.getPropertyIndex())) {
|
||||
key.append('v');
|
||||
}
|
||||
}
|
||||
|
||||
if (publish) {
|
||||
key.append('p');
|
||||
}
|
||||
|
||||
return key.toString();
|
||||
}
|
||||
|
||||
@@ -1380,13 +1349,10 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Build the bean update for the L2 cache.
|
||||
*/
|
||||
public void addBeanUpdate(CacheChangeSet changeSet) {
|
||||
|
||||
if (!updatedManysOnly || collectionChanges != null) {
|
||||
|
||||
boolean updateNaturalKey = false;
|
||||
|
||||
String key = beanDescriptor.cacheKey(idValue);
|
||||
|
||||
Map<String, Object> changes = new LinkedHashMap<>();
|
||||
EntityBean bean = getEntityBean();
|
||||
boolean[] dirtyProperties = getDirtyProperties();
|
||||
@@ -1410,7 +1376,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
// add element collection update
|
||||
changes.putAll(collectionChanges);
|
||||
}
|
||||
|
||||
changeSet.addBeanUpdate(beanDescriptor, key, changes, updateNaturalKey, getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.BeanCacheResult;
|
||||
import io.ebeaninternal.api.CQueryPlanKey;
|
||||
import io.ebeaninternal.api.ConcurrencyMode;
|
||||
import io.ebeaninternal.api.LoadBeanContext;
|
||||
import io.ebeaninternal.api.LoadContext;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
@@ -105,7 +106,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -219,9 +219,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
private final BeanProperty draftDirty;
|
||||
|
||||
/**
|
||||
* Map of BeanProperty Linked so as to preserve order.
|
||||
*/
|
||||
private final LinkedHashMap<String, BeanProperty> propMap;
|
||||
|
||||
/**
|
||||
@@ -234,44 +231,17 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
private final Map<String, BeanPropertyAssoc<?>> tablePath = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The type of bean this describes.
|
||||
*/
|
||||
final Class<T> beanType;
|
||||
|
||||
final Class<?> rootBeanType;
|
||||
|
||||
/**
|
||||
* This is not sent to a remote client.
|
||||
*/
|
||||
private final BeanDescriptorMap owner;
|
||||
|
||||
|
||||
final String[] properties;
|
||||
|
||||
/**
|
||||
* Intercept pre post on insert,update, and delete .
|
||||
*/
|
||||
private volatile BeanPersistController persistController;
|
||||
|
||||
private final BeanPostLoad beanPostLoad;
|
||||
private final BeanPostConstructListener beanPostConstructListener;
|
||||
|
||||
/**
|
||||
* Listens for post commit insert update and delete events.
|
||||
*/
|
||||
private volatile BeanPersistController persistController;
|
||||
private volatile BeanPersistListener persistListener;
|
||||
|
||||
private final BeanQueryAdapter queryAdapter;
|
||||
|
||||
/**
|
||||
* If set overrides the find implementation. Server side only.
|
||||
*/
|
||||
private final BeanFindController beanFinder;
|
||||
|
||||
/**
|
||||
* Used for fine grain filtering for the change log.
|
||||
*/
|
||||
private final ChangeLogFilter changeLogFilter;
|
||||
|
||||
/**
|
||||
@@ -281,22 +251,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
private final boolean abstractType;
|
||||
|
||||
/**
|
||||
* Derived list of properties that make up the unique id.
|
||||
*/
|
||||
private final BeanProperty idProperty;
|
||||
|
||||
private final int idPropertyIndex;
|
||||
|
||||
/**
|
||||
* Derived list of properties that are used for version concurrency checking.
|
||||
*/
|
||||
private final BeanProperty versionProperty;
|
||||
|
||||
private final int versionPropertyIndex;
|
||||
|
||||
private final BeanProperty whenModifiedProperty;
|
||||
|
||||
private final BeanProperty whenCreatedProperty;
|
||||
|
||||
/**
|
||||
@@ -313,14 +273,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Scalar mutable properties (need to dirty check on update).
|
||||
*/
|
||||
private final BeanProperty[] propertiesMutable;
|
||||
|
||||
|
||||
private final BeanPropertyAssocOne<?> unidirectional;
|
||||
private final BeanProperty orderColumn;
|
||||
|
||||
/**
|
||||
* list of properties that are Lists/Sets/Maps (Derived).
|
||||
*/
|
||||
private final BeanProperty[] propertiesNonMany;
|
||||
private final BeanProperty[] propertiesAggregate;
|
||||
private final BeanPropertyAssocMany<?>[] propertiesMany;
|
||||
@@ -332,25 +287,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* list of properties that are associated beans and not embedded (Derived).
|
||||
*/
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOne;
|
||||
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneImported;
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneImportedSave;
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneImportedDelete;
|
||||
|
||||
//private final BeanPropertyAssocOne<?>[] propertiesOneExported;
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneExportedSave;
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneExportedDelete;
|
||||
|
||||
/**
|
||||
* list of properties that are embedded beans.
|
||||
*/
|
||||
private final BeanPropertyAssocOne<?>[] propertiesEmbedded;
|
||||
|
||||
/**
|
||||
* List of the scalar properties excluding id and secondary table properties.
|
||||
*/
|
||||
private final BeanProperty[] propertiesBaseScalar;
|
||||
|
||||
private final BeanProperty[] propertiesTransient;
|
||||
|
||||
/**
|
||||
@@ -382,11 +326,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
private final EntityBean prototypeEntityBean;
|
||||
|
||||
private final IdBinder idBinder;
|
||||
|
||||
private String idBinderInLHSSql;
|
||||
|
||||
private String idBinderIdSql;
|
||||
|
||||
private String deleteByIdSql;
|
||||
private String deleteByIdInSql;
|
||||
private String whereIdInSql;
|
||||
@@ -394,29 +335,19 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
private String softDeleteByIdInSql;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String baseTableAlias;
|
||||
|
||||
private final boolean cacheSharableBeans;
|
||||
|
||||
private final String docStoreQueueId;
|
||||
|
||||
private final BeanDescriptorDraftHelp<T> draftHelp;
|
||||
private final BeanDescriptorCacheHelp<T> cacheHelp;
|
||||
private final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
private DocStoreBeanAdapter<T> docStoreAdapter;
|
||||
private DocumentMapping docMapping;
|
||||
private boolean docStoreEmbeddedInvalidation;
|
||||
|
||||
private final String defaultSelectClause;
|
||||
|
||||
private SpiEbeanServer ebeanServer;
|
||||
|
||||
/**
|
||||
* Construct the BeanDescriptor.
|
||||
*/
|
||||
public BeanDescriptor(BeanDescriptorMap owner, DeployBeanDescriptor<T> deploy) {
|
||||
|
||||
this.owner = owner;
|
||||
this.multiValueSupported = owner.isMultiValueSupported();
|
||||
this.entityType = deploy.getEntityType();
|
||||
@@ -431,7 +362,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.namedQuery = deploy.getNamedQuery();
|
||||
this.namedRawSql = deploy.getNamedRawSql();
|
||||
this.inheritInfo = deploy.getInheritInfo();
|
||||
|
||||
this.beanFinder = deploy.getBeanFinder();
|
||||
this.persistController = deploy.getPersistController();
|
||||
this.persistListener = deploy.getPersistListener();
|
||||
@@ -439,7 +369,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.beanPostLoad = deploy.getPostLoad();
|
||||
this.queryAdapter = deploy.getQueryAdapter();
|
||||
this.changeLogFilter = deploy.getChangeLogFilter();
|
||||
|
||||
this.defaultSelectClause = deploy.getDefaultSelectClause();
|
||||
this.identityMode = deploy.buildIdentityMode();
|
||||
this.idType = identityMode.getIdType();
|
||||
@@ -449,7 +378,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.selectLastInsertedIdDraft = deploy.getSelectLastInsertedIdDraft();
|
||||
this.concurrencyMode = deploy.getConcurrencyMode();
|
||||
this.indexDefinitions = deploy.getIndexDefinitions();
|
||||
|
||||
this.readAuditing = deploy.isReadAuditing();
|
||||
this.draftable = deploy.isDraftable();
|
||||
this.draftableElement = deploy.isDraftableElement();
|
||||
@@ -464,10 +392,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.partitionMeta = deploy.getPartitionMeta();
|
||||
this.storageEngine = deploy.getStorageEngine();
|
||||
this.autoTunable = beanFinder == null && (entityType == EntityType.ORM || entityType == EntityType.VIEW);
|
||||
|
||||
// helper object used to derive lists of properties
|
||||
DeployBeanPropertyLists listHelper = new DeployBeanPropertyLists(owner, this, deploy);
|
||||
|
||||
this.softDeleteProperty = listHelper.getSoftDeleteProperty();
|
||||
// if formula is set, the property is virtual only (there is no column in db) the formula must evaluate to true,
|
||||
// if there is a join to a deleted bean. Example: '@Formula(select = "${ta}.user_id is null")'
|
||||
@@ -503,22 +429,17 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.propertiesGenInsert = listHelper.getGeneratedInsert();
|
||||
this.propertiesGenUpdate = listHelper.getGeneratedUpdate();
|
||||
this.idOnlyReference = isIdOnlyReference(propertiesBaseScalar);
|
||||
|
||||
boolean noRelationships = propertiesOne.length + propertiesMany.length == 0;
|
||||
|
||||
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
|
||||
this.cacheHelp = new BeanDescriptorCacheHelp<>(this, owner.getCacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported);
|
||||
this.jsonHelp = new BeanDescriptorJsonHelp<>(this);
|
||||
this.draftHelp = new BeanDescriptorDraftHelp<>(this);
|
||||
|
||||
this.docStoreAdapter = owner.createDocStoreBeanAdapter(this, deploy);
|
||||
this.docStoreQueueId = docStoreAdapter.getQueueId();
|
||||
|
||||
// Check if there are no cascade save associated beans ( subject to change
|
||||
// in initialiseOther()). Note that if we are in an inheritance hierarchy
|
||||
// then we also need to check every BeanDescriptors in the InheritInfo as
|
||||
// well. We do that later in initialiseOther().
|
||||
|
||||
saveRecurseSkippable = (0 == (propertiesOneExportedSave.length + propertiesOneImportedSave.length + propertiesManySave.length));
|
||||
|
||||
// Check if there are no cascade delete associated beans (also subject to
|
||||
@@ -529,7 +450,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.idBinder = owner.createIdBinder(idProperty);
|
||||
this.whenModifiedProperty = findWhenModifiedProperty();
|
||||
this.whenCreatedProperty = findWhenCreatedProperty();
|
||||
|
||||
// derive the index position of the Id and Version properties
|
||||
this.abstractType = Modifier.isAbstract(beanType.getModifiers());
|
||||
if (abstractType) {
|
||||
@@ -537,7 +457,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.versionPropertyIndex = -1;
|
||||
this.unloadProperties = new int[0];
|
||||
this.propertiesIndex = new BeanProperty[0];
|
||||
|
||||
} else {
|
||||
EntityBeanIntercept ebi = prototypeEntityBean._ebean_getIntercept();
|
||||
this.idPropertyIndex = (idProperty == null) ? -1 : ebi.findProperty(idProperty.getName());
|
||||
@@ -568,23 +487,19 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* These properties need to be unloaded when populating beans for queries.
|
||||
*/
|
||||
private int[] derivePropertiesToUnload(EntityBean prototypeEntityBean) {
|
||||
|
||||
boolean[] loaded = prototypeEntityBean._ebean_getIntercept().getLoaded();
|
||||
int[] props = new int[loaded.length];
|
||||
int pos = 0;
|
||||
|
||||
// collect the positions of the properties initialised in the default constructor.
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (loaded[i]) {
|
||||
props[pos++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos == 0) {
|
||||
// nothing set in the constructor
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
// populate a smaller/minimal array
|
||||
int[] unload = new int[pos];
|
||||
System.arraycopy(props, 0, unload, 0, pos);
|
||||
@@ -665,14 +580,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* These properties need to be initialised prior to the association properties
|
||||
* as they are used to get the imported and exported properties.
|
||||
* </p>
|
||||
*/
|
||||
void initialiseId(BeanDescriptorInitContext initContext) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("BeanDescriptor initialise " + fullName);
|
||||
}
|
||||
|
||||
if (draftable) {
|
||||
initContext.addDraft(baseTable, draftTable);
|
||||
}
|
||||
@@ -680,7 +592,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
// add mapping (used to swap out baseTable for asOf queries)
|
||||
initContext.addHistory(baseTable, baseTableAsOf);
|
||||
}
|
||||
|
||||
if (inheritInfo != null) {
|
||||
inheritInfo.setDescriptor(this);
|
||||
}
|
||||
@@ -695,19 +606,17 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Initialise the exported and imported parts for associated properties.
|
||||
*/
|
||||
public void initialiseOther(BeanDescriptorInitContext initContext) {
|
||||
|
||||
for (BeanPropertyAssocMany<?> many : propertiesManyToMany) {
|
||||
// register associated draft table for M2M intersection
|
||||
many.registerDraftIntersectionTable(initContext);
|
||||
}
|
||||
|
||||
if (historySupport) {
|
||||
// history support on this bean so check all associated intersection tables
|
||||
// and if they are not excluded register the associated 'with history' table
|
||||
for (BeanPropertyAssocMany<?> aPropertiesManyToMany : propertiesManyToMany) {
|
||||
for (BeanPropertyAssocMany<?> manyToMany : propertiesManyToMany) {
|
||||
// register associated history table for M2M intersection
|
||||
if (!aPropertiesManyToMany.isExcludedFromHistory()) {
|
||||
TableJoin intersectionTableJoin = aPropertiesManyToMany.getIntersectionTableJoin();
|
||||
if (!manyToMany.isExcludedFromHistory()) {
|
||||
TableJoin intersectionTableJoin = manyToMany.getIntersectionTableJoin();
|
||||
initContext.addHistoryIntersection(intersectionTableJoin.getTable());
|
||||
}
|
||||
}
|
||||
@@ -730,11 +639,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
idBinderIdSql = idBinder.getBindIdSql(baseTableAlias);
|
||||
String idBinderInLHSSqlNoAlias = idBinder.getBindIdInSql(null);
|
||||
String idEqualsSql = idBinder.getBindIdSql(null);
|
||||
|
||||
deleteByIdSql = "delete from " + baseTable + " where " + idEqualsSql;
|
||||
whereIdInSql = " where " + idBinderInLHSSqlNoAlias + " ";
|
||||
deleteByIdInSql = "delete from " + baseTable + whereIdInSql;
|
||||
|
||||
if (softDelete) {
|
||||
softDeleteByIdSql = "update " + baseTable + " set " + getSoftDeleteDbSet() + " where " + idEqualsSql;
|
||||
softDeleteByIdInSql = "update " + baseTable + " set " + getSoftDeleteDbSet() + " where " + idBinderInLHSSqlNoAlias + " ";
|
||||
@@ -765,7 +672,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean hasCircularImportedIdTo(BeanDescriptor sourceDesc) {
|
||||
boolean hasCircularImportedIdTo(BeanDescriptor<?> sourceDesc) {
|
||||
for (BeanPropertyAssocOne<?> assocOne : propertiesOneImportedSave) {
|
||||
if (assocOne.getTargetDescriptor() == sourceDesc) {
|
||||
return true;
|
||||
@@ -792,7 +699,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Perform last initialisation for the descriptor.
|
||||
*/
|
||||
void initLast() {
|
||||
|
||||
for (BeanProperty prop : propertiesNonTransient) {
|
||||
if (prop.isUnique()) {
|
||||
propertiesUnique.add(new BeanProperty[]{prop});
|
||||
@@ -895,13 +801,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
|
||||
EntityBeanIntercept fromEbi = bean._ebean_getIntercept();
|
||||
EntityBeanIntercept toEbi = existing._ebean_getIntercept();
|
||||
|
||||
int propertyLength = toEbi.getPropertyLength();
|
||||
String[] names = getProperties();
|
||||
|
||||
for (int i = 0; i < propertyLength; i++) {
|
||||
|
||||
if (fromEbi.isLoadedProperty(i)) {
|
||||
@@ -977,14 +880,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Return the bean change for an update generating 'new values' and 'old values' in JSON form.
|
||||
*/
|
||||
private BeanChange updateBeanChange(PersistRequestBean<T> request) {
|
||||
|
||||
try {
|
||||
BeanChangeJson changeJson = new BeanChangeJson(this, request.isStatelessUpdate());
|
||||
request.getEntityBeanIntercept().addDirtyPropertyValues(changeJson);
|
||||
changeJson.flush();
|
||||
|
||||
return beanChange(ChangeType.UPDATE, request.getBeanId(), changeJson.newJson(), changeJson.oldJson());
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
logger.error("Failed to write ChangeLog entry for update", e);
|
||||
return null;
|
||||
@@ -995,16 +895,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Return the bean change for an insert.
|
||||
*/
|
||||
private BeanChange insertBeanChange(PersistRequestBean<T> request) {
|
||||
|
||||
try {
|
||||
StringWriter writer = new StringWriter(200);
|
||||
SpiJsonWriter jsonWriter = createJsonWriter(writer);
|
||||
|
||||
jsonWriteForInsert(jsonWriter, request.getEntityBean());
|
||||
jsonWriter.flush();
|
||||
|
||||
return beanChange(ChangeType.INSERT, request.getBeanId(), writer.toString(), null);
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to write ChangeLog entry for insert", e);
|
||||
return null;
|
||||
@@ -1063,12 +959,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* concurrency checking.
|
||||
*/
|
||||
private SqlUpdate deleteByIdList(List<Object> idList, DeleteMode mode) {
|
||||
|
||||
String baseSql = mode.isHard() ? deleteByIdInSql : softDeleteByIdInSql;
|
||||
StringBuilder sb = new StringBuilder(baseSql);
|
||||
String inClause = idBinder.getIdInValueExprDelete(idList.size());
|
||||
sb.append(inClause);
|
||||
|
||||
DefaultSqlUpdate delete = new DefaultSqlUpdate(sb.toString());
|
||||
idBinder.addIdInBindValues(delete, idList);
|
||||
return delete;
|
||||
@@ -1079,15 +973,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* concurrency checking.
|
||||
*/
|
||||
private SqlUpdate deleteById(Object id, DeleteMode mode) {
|
||||
|
||||
String baseSql = mode.isHard() ? deleteByIdSql : softDeleteByIdSql;
|
||||
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(baseSql);
|
||||
|
||||
Object[] bindValues = idBinder.getBindValues(id);
|
||||
for (Object bindValue : bindValues) {
|
||||
sqlDelete.setParameter(bindValue);
|
||||
}
|
||||
|
||||
return sqlDelete;
|
||||
}
|
||||
|
||||
@@ -1100,9 +991,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
void initialiseFkeys() {
|
||||
for (BeanPropertyAssocOne<?> aPropertiesOneImported : propertiesOneImported) {
|
||||
if (!aPropertiesOneImported.isFormula()) {
|
||||
aPropertiesOneImported.addFkey();
|
||||
for (BeanPropertyAssocOne<?> oneImported : propertiesOneImported) {
|
||||
if (!oneImported.isFormula()) {
|
||||
oneImported.addFkey();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1210,12 +1101,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Build the Document mapping recursively with the given prefix relative to the root of the document.
|
||||
*/
|
||||
public void docStoreMapping(final DocMappingBuilder mapping, final String prefix) {
|
||||
|
||||
if (prefix != null && idProperty != null) {
|
||||
// id property not included in the
|
||||
idProperty.docStoreMapping(mapping, prefix);
|
||||
}
|
||||
|
||||
if (inheritInfo != null) {
|
||||
String discCol = inheritInfo.getDiscriminatorColumn();
|
||||
if (Types.VARCHAR == inheritInfo.getDiscriminatorType()) {
|
||||
@@ -1702,13 +1591,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Trim query plans not used since the passed in epoch time.
|
||||
*/
|
||||
void trimQueryPlans(long unusedSince) {
|
||||
Iterator<CQueryPlan> it = queryPlanCache.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CQueryPlan queryPlan = it.next();
|
||||
if (queryPlan.getLastQueryTime() < unusedSince) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
queryPlanCache.values().removeIf(queryPlan -> queryPlan.getLastQueryTime() < unusedSince);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1804,9 +1687,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Find a property annotated with @WhenCreated or @CreatedTimestamp.
|
||||
*/
|
||||
private BeanProperty findWhenCreatedProperty() {
|
||||
for (BeanProperty aPropertiesBaseScalar : propertiesBaseScalar) {
|
||||
if (aPropertiesBaseScalar.isGeneratedWhenCreated()) {
|
||||
return aPropertiesBaseScalar;
|
||||
for (BeanProperty baseScalar : propertiesBaseScalar) {
|
||||
if (baseScalar.isGeneratedWhenCreated()) {
|
||||
return baseScalar;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1816,10 +1699,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Find a property annotated with @WhenModified or @UpdatedTimestamp.
|
||||
*/
|
||||
private BeanProperty findWhenModifiedProperty() {
|
||||
|
||||
for (BeanProperty aPropertiesBaseScalar : propertiesBaseScalar) {
|
||||
if (aPropertiesBaseScalar.isGeneratedWhenModified()) {
|
||||
return aPropertiesBaseScalar;
|
||||
for (BeanProperty baseScalar : propertiesBaseScalar) {
|
||||
if (baseScalar.isGeneratedWhenModified()) {
|
||||
return baseScalar;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -1829,14 +1711,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Return the many property included in the query or null if one is not.
|
||||
*/
|
||||
public BeanPropertyAssocMany<?> getManyProperty(SpiQuery<?> query) {
|
||||
|
||||
OrmQueryDetail detail = query.getDetail();
|
||||
for (BeanPropertyAssocMany<?> aPropertiesMany : propertiesMany) {
|
||||
if (detail.includesPath(aPropertiesMany.getName())) {
|
||||
return aPropertiesMany;
|
||||
for (BeanPropertyAssocMany<?> many : propertiesMany) {
|
||||
if (detail.includesPath(many.getName())) {
|
||||
return many;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1905,7 +1785,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Bind the idValue to the preparedStatement.
|
||||
* <p>
|
||||
* This takes care of the various id types such as embedded beans etc.
|
||||
* </p>
|
||||
*/
|
||||
public void bindId(DataBind dataBind, Object idValue) throws SQLException {
|
||||
idBinder.bindId(dataBind, idValue);
|
||||
@@ -1915,7 +1794,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Return the id as an array of scalar bindable values.
|
||||
* <p>
|
||||
* This 'flattens' any EmbeddedId or multiple Id property cases.
|
||||
* </p>
|
||||
*/
|
||||
public Object[] getBindIdValues(Object idValue) {
|
||||
return idBinder.getBindValues(idValue);
|
||||
@@ -1940,7 +1818,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
try {
|
||||
EntityBean bean = (EntityBean) prototypeEntityBean._ebean_newInstance();
|
||||
|
||||
if (beanPostConstructListener != null) {
|
||||
beanPostConstructListener.autowire(bean); // calls all registered listeners
|
||||
beanPostConstructListener.postConstruct(bean); // calls first the @PostConstruct method and then the listeners
|
||||
@@ -1959,7 +1836,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
@@ -1999,7 +1875,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createReference(Boolean readOnly, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
|
||||
if (cacheSharableBeans && !disableLazyLoad && !Boolean.FALSE.equals(readOnly)) {
|
||||
CachedBeanData d = cacheHelp.beanCacheGetData(cacheKey(id));
|
||||
if (d != null) {
|
||||
@@ -2016,10 +1891,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
if (inheritInfo != null && !inheritInfo.isConcrete()) {
|
||||
return findReferenceBean(id, pc);
|
||||
}
|
||||
|
||||
EntityBean eb = createEntityBean();
|
||||
id = convertSetId(id, eb);
|
||||
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
if (disableLazyLoad) {
|
||||
ebi.setDisableLazyLoad(true);
|
||||
@@ -2034,9 +1907,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
contextPut(pc, id, eb);
|
||||
ebi.setPersistenceContext(pc);
|
||||
}
|
||||
|
||||
return (T) eb;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
@@ -2086,14 +1957,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
public BeanProperty findPropertyFromPath(String path) {
|
||||
BeanDescriptor<?> other = this;
|
||||
while (true) {
|
||||
|
||||
String[] split = SplitName.splitBegin(path);
|
||||
if (split[1] == null) {
|
||||
return other._findBeanProperty(split[0]);
|
||||
}
|
||||
BeanPropertyAssoc<?> assocProp = (BeanPropertyAssoc<?>) other._findBeanProperty(split[0]);
|
||||
if (assocProp == null) {
|
||||
throw new IllegalStateException("Unknown property path [" + split[0] + "] from[" + path + "]");
|
||||
}
|
||||
BeanDescriptor<?> targetDesc = assocProp.getTargetDescriptor();
|
||||
|
||||
path = split[1];
|
||||
other = targetDesc;
|
||||
}
|
||||
@@ -2114,13 +1986,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return result;
|
||||
}
|
||||
String[] splitBegin = SplitName.splitBegin(path);
|
||||
|
||||
BeanProperty beanProperty = result.findProperty(splitBegin[0]);
|
||||
if (beanProperty instanceof BeanPropertyAssoc<?>) {
|
||||
BeanPropertyAssoc<?> assocProp = (BeanPropertyAssoc<?>) beanProperty;
|
||||
path = splitBegin[1];
|
||||
result = assocProp.getTargetDescriptor();
|
||||
|
||||
} else {
|
||||
throw new PersistenceException("Invalid path " + path + " from " + result.getFullName());
|
||||
}
|
||||
@@ -2147,7 +2017,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* For bidirectional this is a real property on the bean. For unidirectional
|
||||
* relationships we have this 'shadow' property which is not externally
|
||||
* visible.
|
||||
* </p>
|
||||
*/
|
||||
public BeanPropertyAssocOne<?> getUnidirectional() {
|
||||
BeanDescriptor<?> other = this;
|
||||
@@ -2168,7 +2037,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* If this is false and the Id is null it is assumed that a database auto
|
||||
* increment feature is being used to populate the id.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isUseIdGenerator() {
|
||||
return idGenerator != null;
|
||||
@@ -2195,7 +2063,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* If this BeanDescriptor is for a table then this returns the table name
|
||||
* instead.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
@Nonnull
|
||||
@@ -2315,7 +2182,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Return the Id value for the bean with embeddedId beans converted into maps.
|
||||
* <p>
|
||||
* The usage is to provide simple id types for JSON processing (for embeddedId's).
|
||||
* </p>
|
||||
*/
|
||||
public Object getIdForJson(Object bean) {
|
||||
return idBinder.getIdForJson((EntityBean) bean);
|
||||
@@ -2325,7 +2191,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Convert the idValue assuming embeddedId values are Maps.
|
||||
* <p>
|
||||
* The usage is to provide simple id types for JSON processing (for embeddedId's).
|
||||
* </p>
|
||||
*/
|
||||
Object convertIdFromJson(Object idValue) {
|
||||
return idBinder.convertIdFromJson(idValue);
|
||||
@@ -2359,7 +2224,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* If the bean is not null, the id value is set to the id property of the bean
|
||||
* after it has been converted to the correct type.
|
||||
* </p>
|
||||
*/
|
||||
public Object convertSetId(Object idValue, EntityBean bean) {
|
||||
return idBinder.convertSetId(idValue, bean);
|
||||
@@ -2385,9 +2249,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
public void sort(List<T> list, String sortByClause) {
|
||||
|
||||
ElComparator<T> comparator = getElComparator(sortByClause);
|
||||
list.sort(comparator);
|
||||
list.sort(getElComparator(sortByClause));
|
||||
}
|
||||
|
||||
public ElComparator<T> getElComparator(String propNameOrSortBy) {
|
||||
@@ -2398,10 +2260,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Register all the assoc many properties on this bean that are not populated with the load context.
|
||||
* <p>
|
||||
* This provides further lazy loading via the load context.
|
||||
* </p>
|
||||
*/
|
||||
public void lazyLoadRegister(String prefix, EntityBeanIntercept ebi, EntityBean bean, LoadContext loadContext) {
|
||||
|
||||
// load the List/Set/Map proxy objects (deferred fetching of lists)
|
||||
BeanPropertyAssocMany<?>[] manys = propertiesMany();
|
||||
for (BeanPropertyAssocMany<?> many : manys) {
|
||||
@@ -2409,7 +2269,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
BeanCollection<?> ref = many.createReferenceIfNull(bean);
|
||||
if (ref != null && !ref.isRegisteredWithLoadContext()) {
|
||||
String path = SplitName.add(prefix, many.getName());
|
||||
loadContext.register(path, ref);
|
||||
loadContext.register(path, many, ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2420,16 +2280,18 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* define a Reference for the collection and not invoke a query.
|
||||
*/
|
||||
public boolean lazyLoadMany(EntityBeanIntercept ebi) {
|
||||
return lazyLoadMany(ebi, null);
|
||||
}
|
||||
|
||||
public boolean lazyLoadMany(EntityBeanIntercept ebi, LoadBeanContext parent) {
|
||||
int lazyLoadProperty = ebi.getLazyLoadPropertyIndex();
|
||||
if (lazyLoadProperty == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inheritInfo != null) {
|
||||
return descOf(ebi.getOwner().getClass()).lazyLoadMany(ebi, lazyLoadProperty);
|
||||
return descOf(ebi.getOwner().getClass()).lazyLoadMany(ebi, lazyLoadProperty, parent);
|
||||
}
|
||||
return lazyLoadMany(ebi, lazyLoadProperty);
|
||||
return lazyLoadMany(ebi, lazyLoadProperty, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2442,13 +2304,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Check for lazy loading of many property.
|
||||
*/
|
||||
private boolean lazyLoadMany(EntityBeanIntercept ebi, int lazyLoadProperty) {
|
||||
|
||||
private boolean lazyLoadMany(EntityBeanIntercept ebi, int lazyLoadProperty, LoadBeanContext loadBeanContext) {
|
||||
BeanProperty lazyLoadBeanProp = propertiesIndex[lazyLoadProperty];
|
||||
if (lazyLoadBeanProp instanceof BeanPropertyAssocMany<?>) {
|
||||
BeanPropertyAssocMany<?> manyProp = (BeanPropertyAssocMany<?>) lazyLoadBeanProp;
|
||||
manyProp.createReference(ebi.getOwner());
|
||||
final BeanCollection<?> collection = manyProp.createReference(ebi.getOwner());
|
||||
ebi.setLoadedLazy();
|
||||
if (loadBeanContext != null) {
|
||||
loadBeanContext.register(manyProp, collection);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -2468,7 +2332,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private ElComparator<T> createComparator(String sortByClause) {
|
||||
|
||||
SortByClause sortBy = SortByClauseParser.parse(sortByClause);
|
||||
if (sortBy.size() == 1) {
|
||||
// simple comparator for a single property
|
||||
@@ -2477,24 +2340,20 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
// create a compound comparator based on the list of properties
|
||||
ElComparator<T>[] comparators = new ElComparator[sortBy.size()];
|
||||
|
||||
List<SortByClause.Property> sortProps = sortBy.getProperties();
|
||||
for (int i = 0; i < sortProps.size(); i++) {
|
||||
SortByClause.Property sortProperty = sortProps.get(i);
|
||||
comparators[i] = createPropertyComparator(sortProperty);
|
||||
}
|
||||
|
||||
return new ElComparatorCompound<>(comparators);
|
||||
}
|
||||
|
||||
private ElComparator<T> createPropertyComparator(SortByClause.Property sortProp) {
|
||||
|
||||
ElPropertyValue elGetValue = getElGetValue(sortProp.getName());
|
||||
if (elGetValue == null) {
|
||||
logger.error("Sort property [" + sortProp + "] not found in " + beanType + ". Cannot sort.");
|
||||
return new ElComparatorNoop<>();
|
||||
}
|
||||
|
||||
if (elGetValue.isAssocMany()) {
|
||||
logger.error("Sort property [" + sortProp + "] in " + beanType + " is a many-property. Cannot sort.");
|
||||
return new ElComparatorNoop<>();
|
||||
@@ -2539,7 +2398,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Similar to ElPropertyValue but also uses foreign key shortcuts.
|
||||
* <p>
|
||||
* The foreign key shortcuts means we can avoid unnecessary joins.
|
||||
* </p>
|
||||
*/
|
||||
public ElPropertyDeploy getElPropertyDeploy(String propName) {
|
||||
ElPropertyDeploy elProp = elDeployCache.get(propName);
|
||||
@@ -2560,7 +2418,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
ElPropertyValue buildElGetValue(String propName, ElPropertyChainBuilder chain, boolean propertyDeploy) {
|
||||
|
||||
if (propertyDeploy && chain != null) {
|
||||
ElPropertyDeploy fk = elDeployCache.get(propName);
|
||||
if (fk instanceof BeanFkeyProperty) {
|
||||
@@ -2568,17 +2425,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return ((BeanFkeyProperty) fk).create(chain.getExpression(), chain.isContainsMany());
|
||||
}
|
||||
}
|
||||
|
||||
int basePos = propName.indexOf('.');
|
||||
if (basePos > -1) {
|
||||
// nested or embedded property
|
||||
String baseName = propName.substring(0, basePos);
|
||||
|
||||
BeanProperty assocProp = _findBeanProperty(baseName);
|
||||
if (assocProp == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String remainder = propName.substring(basePos + 1);
|
||||
return assocProp.buildElPropertyValue(propName, remainder, chain, propertyDeploy);
|
||||
}
|
||||
@@ -2639,7 +2493,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* This searches this BeanDescriptor and then searches further down the
|
||||
* inheritance tree (not up).
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public BeanProperty findProperty(String propName) {
|
||||
@@ -2666,11 +2519,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Reset the many properties to empty state ready for reloading.
|
||||
*/
|
||||
public void resetManyProperties(Object dbBean) {
|
||||
|
||||
EntityBean bean = (EntityBean) dbBean;
|
||||
for (BeanPropertyAssocMany<?> aPropertiesMany : propertiesMany) {
|
||||
if (aPropertiesMany.isCascadeRefresh()) {
|
||||
aPropertiesMany.resetMany(bean);
|
||||
for (BeanPropertyAssocMany<?> many : propertiesMany) {
|
||||
if (many.isCascadeRefresh()) {
|
||||
many.resetMany(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2680,7 +2532,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* This means is has no relationships and has readOnly=true in its cache
|
||||
* options.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isCacheSharableBeans() {
|
||||
return cacheSharableBeans;
|
||||
@@ -2781,8 +2632,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* De-register the BeanPersistListener.
|
||||
*/
|
||||
public void deregister(BeanPersistListener listener) {
|
||||
|
||||
// volatile read...
|
||||
BeanPersistListener currentListener = persistListener;
|
||||
if (currentListener != null) {
|
||||
if (currentListener instanceof ChainedBeanPersistListener) {
|
||||
@@ -2798,8 +2647,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* De-register the BeanPersistController.
|
||||
*/
|
||||
public void deregister(BeanPersistController controller) {
|
||||
|
||||
// volatile read...
|
||||
BeanPersistController currentController = persistController;
|
||||
if (currentController != null) {
|
||||
if (currentController instanceof ChainedBeanPersistController) {
|
||||
@@ -2815,9 +2662,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Register the new BeanPersistController.
|
||||
*/
|
||||
public void register(BeanPersistListener newPersistListener) {
|
||||
|
||||
if (newPersistListener.isRegisterFor(beanType)) {
|
||||
// volatile read...
|
||||
BeanPersistListener currentListener = persistListener;
|
||||
if (currentListener == null) {
|
||||
persistListener = newPersistListener;
|
||||
@@ -2837,18 +2682,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Register the new BeanPersistController.
|
||||
*/
|
||||
public void register(BeanPersistController newController) {
|
||||
|
||||
if (newController.isRegisterFor(beanType)) {
|
||||
// volatile read...
|
||||
BeanPersistController currentController = persistController;
|
||||
if (currentController == null) {
|
||||
persistController = newController;
|
||||
} else {
|
||||
if (currentController instanceof ChainedBeanPersistController) {
|
||||
// add it to the existing chain
|
||||
persistController = ((ChainedBeanPersistController) currentController).register(newController);
|
||||
} else {
|
||||
// build new chain of the 2
|
||||
persistController = new ChainedBeanPersistController(currentController, newController);
|
||||
}
|
||||
}
|
||||
@@ -2901,17 +2742,13 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
/**
|
||||
* Return the dependent tables for a view based entity.
|
||||
* <p>
|
||||
* These tables
|
||||
* </p>
|
||||
*/
|
||||
public String[] getDependentTables() {
|
||||
return dependentTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base table. Only properties mapped to the base table are by
|
||||
* default persisted.
|
||||
* Return the base table. Only properties mapped to the base table are by default persisted.
|
||||
*/
|
||||
@Override
|
||||
public String getBaseTable() {
|
||||
@@ -3012,7 +2849,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
@Override
|
||||
public ExtraJoin extraJoin(String propertyPath) {
|
||||
|
||||
ElPropertyValue elGetValue = getElGetValue(propertyPath);
|
||||
if (elGetValue != null) {
|
||||
BeanProperty beanProperty = elGetValue.getBeanProperty();
|
||||
@@ -3150,7 +2986,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* This is only used with Identity columns and getGeneratedKeys is not
|
||||
* supported.
|
||||
* </p>
|
||||
*/
|
||||
public String getSelectLastInsertedId(boolean publish) {
|
||||
return publish ? selectLastInsertedId : selectLastInsertedIdDraft;
|
||||
@@ -3198,8 +3033,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the beans that are embedded. These share the base table with the
|
||||
* owner bean.
|
||||
* Return the beans that are embedded. These share the base table with the owner bean.
|
||||
*/
|
||||
public BeanPropertyAssocOne<?>[] propertiesEmbedded() {
|
||||
return propertiesEmbedded;
|
||||
@@ -3252,12 +3086,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* @param insertMode true if the 'root request' was an insert rather than an update
|
||||
*/
|
||||
public boolean isInsertMode(EntityBeanIntercept ebi, boolean insertMode) {
|
||||
|
||||
if (ebi.isLoaded()) {
|
||||
// must be an update as the bean is loaded
|
||||
return false;
|
||||
}
|
||||
|
||||
if (idProperty.isEmbedded()) {
|
||||
// not using Id generator so just base on isLoaded()
|
||||
return !ebi.isLoaded();
|
||||
@@ -3329,7 +3161,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
|
||||
public ConcurrencyMode getConcurrencyMode(EntityBeanIntercept ebi) {
|
||||
|
||||
if (!hasVersionProperty(ebi)) {
|
||||
return ConcurrencyMode.NONE;
|
||||
} else {
|
||||
@@ -3350,15 +3181,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Populate the diff for updates with flattened non-null property values.
|
||||
*/
|
||||
public void diff(String prefix, Map<String, ValuePair> map, EntityBean newBean, EntityBean oldBean) {
|
||||
|
||||
for (BeanProperty aPropertiesBaseScalar : propertiesBaseScalar) {
|
||||
aPropertiesBaseScalar.diff(prefix, map, newBean, oldBean);
|
||||
for (BeanProperty baseScalar : propertiesBaseScalar) {
|
||||
baseScalar.diff(prefix, map, newBean, oldBean);
|
||||
}
|
||||
for (BeanPropertyAssocOne<?> aPropertiesOne : propertiesOne) {
|
||||
aPropertiesOne.diff(prefix, map, newBean, oldBean);
|
||||
for (BeanPropertyAssocOne<?> one : propertiesOne) {
|
||||
one.diff(prefix, map, newBean, oldBean);
|
||||
}
|
||||
for (BeanPropertyAssocOne<?> aPropertiesEmbedded : propertiesEmbedded) {
|
||||
aPropertiesEmbedded.diff(prefix, map, newBean, oldBean);
|
||||
for (BeanPropertyAssocOne<?> embedded : propertiesEmbedded) {
|
||||
embedded.diff(prefix, map, newBean, oldBean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3368,10 +3198,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* <p>
|
||||
* This is primarily used for paging queries to ensure that an order by clause is provided and that the order by
|
||||
* provides unique ordering of the rows (so that the paging is predicable).
|
||||
* </p>
|
||||
*/
|
||||
public void appendOrderById(SpiQuery<T> query) {
|
||||
|
||||
if (idProperty != null && !idProperty.isEmbedded() && !query.order().containsProperty(idProperty.getName())) {
|
||||
query.order().asc(idProperty.getName());
|
||||
}
|
||||
@@ -3409,7 +3237,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Returns ManyToOnes and OneToOnes on the imported owning side.
|
||||
* <p>
|
||||
* Excludes OneToOnes on the exported side.
|
||||
* </p>
|
||||
*/
|
||||
public BeanPropertyAssocOne<?>[] propertiesOneImported() {
|
||||
return propertiesOneImported;
|
||||
@@ -3483,7 +3310,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* no version property exists on the bean.
|
||||
* <p>
|
||||
* Note that this DOES NOT find a version property on an embedded bean.
|
||||
* </p>
|
||||
*/
|
||||
public BeanProperty getVersionProperty() {
|
||||
return versionProperty;
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy;
|
||||
import io.ebean.config.BeanNotRegisteredException;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -15,7 +16,6 @@ class BeanEmbeddedMetaFactory {
|
||||
* Create BeanProperties for embedded beans using the deployment specific DB column name and table alias.
|
||||
*/
|
||||
public static BeanEmbeddedMeta create(BeanDescriptorMap owner, DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
// we can get a BeanDescriptor for an Embedded bean
|
||||
// and know that it is NOT recursive, as Embedded beans are
|
||||
// only allow to hold simple scalar types...
|
||||
@@ -28,23 +28,20 @@ class BeanEmbeddedMetaFactory {
|
||||
|
||||
// deployment override information (column names)
|
||||
String columnPrefix = prop.getColumnPrefix();
|
||||
Map<String, String> propColMap = prop.getDeployEmbedded().getPropertyColumnMap();
|
||||
Map<String, Column> propColMap = prop.getDeployEmbedded().getPropertyColumnMap();
|
||||
|
||||
BeanProperty[] sourceProperties = targetDesc.propertiesNonTransient();
|
||||
BeanProperty[] embeddedProperties = new BeanProperty[sourceProperties.length];
|
||||
|
||||
for (int i = 0; i < sourceProperties.length; i++) {
|
||||
String propertyName = sourceProperties[i].getName();
|
||||
String dbColumn = propColMap.get(propertyName);
|
||||
if (dbColumn == null) {
|
||||
// dbColumn not overridden so take original
|
||||
dbColumn = sourceProperties[i].getDbColumn();
|
||||
if (columnPrefix != null) {
|
||||
dbColumn = columnPrefix + dbColumn;
|
||||
}
|
||||
}
|
||||
|
||||
BeanPropertyOverride overrides = new BeanPropertyOverride(dbColumn);
|
||||
Column column = propColMap.get(propertyName);
|
||||
String dbColumn = dbColumn(columnPrefix, column, sourceProperties[i]);
|
||||
boolean dbNullable = dbNullable(column, sourceProperties[i]);
|
||||
int dbLength = dbLength(column, sourceProperties[i]);
|
||||
int dbScale = dbScale(column, sourceProperties[i]);
|
||||
String colDefn = getDbColumnDefn(column, sourceProperties[i]);
|
||||
BeanPropertyOverride overrides = new BeanPropertyOverride(dbColumn, dbNullable, dbLength, dbScale, colDefn);
|
||||
if (sourceProperties[i] instanceof BeanPropertyAssocOne) {
|
||||
embeddedProperties[i] = new BeanPropertyAssocOne((BeanPropertyAssocOne)sourceProperties[i], overrides);
|
||||
} else {
|
||||
@@ -54,4 +51,26 @@ class BeanEmbeddedMetaFactory {
|
||||
|
||||
return new BeanEmbeddedMeta(embeddedProperties);
|
||||
}
|
||||
|
||||
private static String dbColumn(String prefix, Column override, BeanProperty source) {
|
||||
String dbCol = (override != null && !override.name().isEmpty()) ? override.name() : source.getDbColumn();
|
||||
return prefix == null ? dbCol : prefix + dbCol;
|
||||
}
|
||||
|
||||
private static boolean dbNullable(Column override, BeanProperty source) {
|
||||
return (override != null) ? override.nullable() : source.isNullable();
|
||||
}
|
||||
|
||||
private static int dbLength(Column override, BeanProperty source) {
|
||||
return (override != null && (override.length() != 255)) ? override.length() : source.getDbLength();
|
||||
}
|
||||
|
||||
private static int dbScale(Column override, BeanProperty source) {
|
||||
return (override != null && (override.scale() != 0)) ? override.scale() : source.getDbScale();
|
||||
}
|
||||
|
||||
private static String getDbColumnDefn(Column override, BeanProperty source) {
|
||||
return (override != null && !override.columnDefinition().isEmpty()) ? override.columnDefinition() : source.getDbColumnDefn();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -55,6 +55,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.ebean.util.StringHelper.replace;
|
||||
|
||||
/**
|
||||
* Description of a property of a bean. Includes its deployment information such
|
||||
* as database column mapping information.
|
||||
@@ -274,7 +276,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
public BeanProperty(BeanDescriptor<?> descriptor, DeployBeanProperty deploy) {
|
||||
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
@@ -314,36 +315,30 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.dbColumnDefn = InternString.intern(deploy.getDbColumnDefn());
|
||||
this.dbColumnDefault = deploy.getDbColumnDefaultSqlLiteral();
|
||||
this.dbMigrationInfos = deploy.getDbMigrationInfos();
|
||||
|
||||
this.inherited = false;// deploy.isInherited();
|
||||
this.owningType = deploy.getOwningType();
|
||||
this.local = deploy.isLocal();
|
||||
|
||||
this.version = deploy.isVersionColumn();
|
||||
this.embedded = deploy.isEmbedded();
|
||||
this.id = deploy.isId();
|
||||
this.generatedProperty = deploy.getGeneratedProperty();
|
||||
this.getter = deploy.getGetter();
|
||||
this.setter = deploy.getSetter();
|
||||
|
||||
this.dbColumn = tableAliasIntern(descriptor, deploy.getDbColumn(), false, null);
|
||||
this.dbComment = deploy.getDbComment();
|
||||
this.aggregation = deploy.parseAggregation();
|
||||
this.sqlFormulaJoin = InternString.intern(deploy.getSqlFormulaJoin());
|
||||
this.sqlFormulaSelect = InternString.intern(deploy.getSqlFormulaSelect());
|
||||
this.formula = sqlFormulaSelect != null;
|
||||
|
||||
this.dbType = deploy.getDbType();
|
||||
this.scalarType = deploy.getScalarType();
|
||||
this.lob = isLobType(dbType);
|
||||
this.propertyType = deploy.getPropertyType();
|
||||
this.field = deploy.getField();
|
||||
this.docOptions = deploy.getDocPropertyOptions();
|
||||
|
||||
this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), false, null);
|
||||
this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), dbEncrypted, dbColumn);
|
||||
this.elPrefix = deploy.getElPrefix();
|
||||
|
||||
this.softDelete = deploy.isSoftDelete();
|
||||
if (softDelete) {
|
||||
ScalarTypeBoolean.BooleanBase boolType = (ScalarTypeBoolean.BooleanBase) scalarType;
|
||||
@@ -353,20 +348,18 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.softDeleteDbSet = null;
|
||||
this.softDeleteDbPredicate = null;
|
||||
}
|
||||
|
||||
this.jsonSerialize = deploy.isJsonSerialize();
|
||||
this.jsonDeserialize = deploy.isJsonDeserialize();
|
||||
}
|
||||
|
||||
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
|
||||
if (descriptor != null) {
|
||||
s = StringHelper.replaceString(s, "${ta}.", "${}");
|
||||
s = StringHelper.replaceString(s, "${ta}", "${}");
|
||||
|
||||
s = replace(s, "${ta}.", "${}");
|
||||
s = replace(s, "${ta}", "${}");
|
||||
if (dbEncrypted) {
|
||||
s = dbEncryptFunction.getDecryptSql(s);
|
||||
String namedParam = ":encryptkey_" + descriptor.getBaseTable() + "___" + dbColumn;
|
||||
s = StringHelper.replaceString(s, "?", namedParam);
|
||||
s = replace(s, "?", namedParam);
|
||||
}
|
||||
}
|
||||
return InternString.intern(s);
|
||||
@@ -377,20 +370,21 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* <p>
|
||||
* Primarily for supporting Embedded beans with overridden dbColumn
|
||||
* mappings.
|
||||
* </p>
|
||||
*/
|
||||
public BeanProperty(BeanProperty source, BeanPropertyOverride override) {
|
||||
|
||||
this.descriptor = source.descriptor;
|
||||
this.name = InternString.intern(source.getName());
|
||||
this.propertyIndex = source.propertyIndex;
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
this.name = source.getName();
|
||||
this.dbColumn = override.getDbColumn();
|
||||
this.nullable = override.isDbNullable();
|
||||
this.dbLength = override.getDbLength();
|
||||
this.dbScale = override.getDbScale();
|
||||
this.dbColumnDefn = InternString.intern(override.getDbColumnDefn());
|
||||
// override with sqlFormula not currently supported
|
||||
this.sqlFormulaJoin = null;
|
||||
this.sqlFormulaSelect = null;
|
||||
this.formula = false;
|
||||
this.aggregation = null;
|
||||
|
||||
this.excludedFromHistory = source.excludedFromHistory;
|
||||
this.tenantId = source.tenantId;
|
||||
this.draft = source.draft;
|
||||
@@ -409,7 +403,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.secondaryTable = source.isSecondaryTable();
|
||||
this.secondaryTableJoin = source.secondaryTableJoin;
|
||||
this.secondaryTableJoinPrefix = source.secondaryTableJoinPrefix;
|
||||
|
||||
this.dbComment = source.dbComment;
|
||||
this.dbBind = source.getDbBind();
|
||||
this.dbEncrypted = source.isDbEncrypted();
|
||||
@@ -418,19 +411,13 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.dbRead = source.isDbRead();
|
||||
this.dbInsertable = source.isDbInsertable();
|
||||
this.dbUpdatable = source.isDbUpdatable();
|
||||
this.nullable = source.isNullable();
|
||||
this.unique = source.isUnique();
|
||||
this.naturalKey = source.isNaturalKey();
|
||||
this.dbLength = source.getDbLength();
|
||||
this.dbScale = source.getDbScale();
|
||||
this.dbColumnDefn = InternString.intern(source.getDbColumnDefn());
|
||||
this.dbColumnDefault = source.dbColumnDefault;
|
||||
this.dbMigrationInfos = source.dbMigrationInfos;
|
||||
|
||||
this.inherited = source.isInherited();
|
||||
this.owningType = source.owningType;
|
||||
this.local = owningType.equals(descriptor.getBeanType());
|
||||
|
||||
this.version = source.isVersion();
|
||||
this.embedded = source.isEmbedded();
|
||||
this.id = source.isId();
|
||||
@@ -444,11 +431,9 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.field = source.getField();
|
||||
this.docOptions = source.docOptions;
|
||||
this.unmappedJson = source.unmappedJson;
|
||||
|
||||
this.elPrefix = override.replace(source.elPrefix, source.dbColumn);
|
||||
this.elPlaceHolder = override.replace(source.elPlaceHolder, source.dbColumn);
|
||||
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
|
||||
|
||||
this.jsonSerialize = source.jsonSerialize;
|
||||
this.jsonDeserialize = source.jsonDeserialize;
|
||||
}
|
||||
@@ -563,9 +548,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
if (formula && sqlFormulaJoin != null) {
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType);
|
||||
|
||||
} else if (secondaryTableJoin != null) {
|
||||
|
||||
String relativePrefix = ctx.getRelativePrefix(secondaryTableJoinPrefix);
|
||||
secondaryTableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
@@ -586,7 +569,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
|
||||
@Override
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
if (aggregation != null) {
|
||||
ctx.appendFormulaSelect(aggregation);
|
||||
} else if (formula) {
|
||||
@@ -597,15 +579,12 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
if (secondaryTableJoin != null) {
|
||||
ctx.pushTableAlias(ctx.getRelativePrefix(secondaryTableJoinPrefix));
|
||||
}
|
||||
|
||||
if (dbEncrypted) {
|
||||
ctx.appendRawColumn(getDecryptSqlWithColumnAlias(ctx.peekTableAlias()));
|
||||
ctx.addEncryptedProp(this);
|
||||
|
||||
} else {
|
||||
ctx.appendColumn(dbColumn);
|
||||
}
|
||||
|
||||
if (secondaryTableJoin != null) {
|
||||
ctx.popTableAlias();
|
||||
}
|
||||
@@ -662,7 +641,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
|
||||
try {
|
||||
Object value = scalarType.read(ctx.getDataReader());
|
||||
if (bean != null) {
|
||||
@@ -716,7 +694,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* Copy/set the property value from the draft bean to the live bean.
|
||||
*/
|
||||
public void publish(EntityBean draftBean, EntityBean liveBean) {
|
||||
|
||||
if (!version && !draftOnly) {
|
||||
// set property value from draft to live
|
||||
Object value = getValueIntercept(draftBean);
|
||||
@@ -899,7 +876,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
|
||||
@Override
|
||||
public void pathSet(Object bean, Object value) {
|
||||
|
||||
if (bean != null) {
|
||||
Object logicalVal = convertToLogicalType(value);
|
||||
setValueIntercept((EntityBean) bean, logicalVal);
|
||||
@@ -1074,14 +1050,14 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
/**
|
||||
* Return the DB scale for numeric columns.
|
||||
*/
|
||||
private int getDbScale() {
|
||||
public int getDbScale() {
|
||||
return dbScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a specific column DDL definition if specified (otherwise null).
|
||||
*/
|
||||
private String getDbColumnDefn() {
|
||||
public String getDbColumnDefn() {
|
||||
return dbColumnDefn;
|
||||
}
|
||||
|
||||
@@ -1279,7 +1255,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
case Types.LONGVARCHAR:
|
||||
case Types.LONGVARBINARY:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -1500,7 +1475,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
public void jsonRead(SpiJsonReader ctx, EntityBean bean) throws IOException {
|
||||
|
||||
JsonToken event = ctx.nextToken();
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
if (jsonDeserialize) {
|
||||
@@ -1551,7 +1525,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* Add to the document mapping if this property is included for this index.
|
||||
*/
|
||||
public void docStoreMapping(DocMappingBuilder mapping, String prefix) {
|
||||
|
||||
if (mapping.includesProperty(prefix, name)) {
|
||||
DocPropertyType type = scalarType.getDocType();
|
||||
DocPropertyOptions options = docOptions.copy();
|
||||
@@ -1571,7 +1544,6 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
public void registerColumn(BeanDescriptor<?> desc, String prefix) {
|
||||
|
||||
String path = SplitName.add(prefix, name);
|
||||
if (formula && dbColumn != null) {
|
||||
// trim off table alias placeholder if found
|
||||
|
||||
@@ -213,6 +213,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanPropertyAssocMany<?> asMany() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isManyToManyWithHistory() {
|
||||
return manyToMany && !excludedFromHistory && descriptor.isHistorySupport();
|
||||
|
||||
@@ -12,16 +12,40 @@ import io.ebeaninternal.server.core.InternString;
|
||||
class BeanPropertyOverride {
|
||||
|
||||
private final String dbColumn;
|
||||
private final boolean dbNullable;
|
||||
private final int dbLength;
|
||||
private final int dbScale;
|
||||
private final String dbColumnDefn;
|
||||
|
||||
BeanPropertyOverride(String dbColumn) {
|
||||
BeanPropertyOverride(String dbColumn, boolean dbNullable, int dbLength, int dbScale, String dbColumnDefn) {
|
||||
this.dbColumn = InternString.intern(dbColumn);
|
||||
this.dbNullable = dbNullable;
|
||||
this.dbLength = dbLength;
|
||||
this.dbScale = dbScale;
|
||||
this.dbColumnDefn = dbColumnDefn;
|
||||
}
|
||||
|
||||
public String getDbColumn() {
|
||||
String getDbColumn() {
|
||||
return dbColumn;
|
||||
}
|
||||
|
||||
public String replace(String src, String srcDbColumn) {
|
||||
return StringHelper.replaceString(src, srcDbColumn, dbColumn);
|
||||
boolean isDbNullable() {
|
||||
return dbNullable;
|
||||
}
|
||||
|
||||
int getDbLength() {
|
||||
return dbLength;
|
||||
}
|
||||
|
||||
int getDbScale() {
|
||||
return dbScale;
|
||||
}
|
||||
|
||||
String getDbColumnDefn() {
|
||||
return dbColumnDefn;
|
||||
}
|
||||
|
||||
String replace(String src, String srcDbColumn) {
|
||||
return StringHelper.replace(src, srcDbColumn, dbColumn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public interface DbReadContext {
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
void register(String path, BeanCollection<?> bc);
|
||||
void register(BeanPropertyAssocMany<?> many, BeanCollection<?> bc);
|
||||
|
||||
/**
|
||||
* Return the property that is associated with the many. There can only be
|
||||
|
||||
@@ -53,7 +53,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
private String idInExpanded() {
|
||||
|
||||
StringBuilder sb = new StringBuilder(30);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
@@ -66,13 +65,11 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
sb.append("=?");
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String idInCompressed() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(");
|
||||
StringBuilder sb = new StringBuilder(20).append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
@@ -80,7 +77,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
sb.append("?");
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -99,7 +95,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
if (pathPrefix != null) {
|
||||
sb.append(pathPrefix).append(".");
|
||||
}
|
||||
|
||||
sb.append(embIdProperty.getName()).append(".");
|
||||
sb.append(props[i].getName());
|
||||
if (!ascending) {
|
||||
@@ -120,9 +115,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
|
||||
prefix = SplitName.add(prefix, embIdProperty.getName());
|
||||
|
||||
for (BeanProperty prop : props) {
|
||||
prop.buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
@@ -145,18 +138,15 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getDefaultOrderBy() {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
sb.append(embIdProperty.getName());
|
||||
sb.append(".");
|
||||
sb.append(props[i].getName());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -172,10 +162,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
if (!idInExpandedForm) {
|
||||
return getIdInValueExpr(false, size);
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(");
|
||||
|
||||
for (int j = 0; j < size; j++) {
|
||||
if (j > 0) {
|
||||
sb.append(" or ");
|
||||
@@ -233,12 +221,11 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object[] getBindValues(Object value) {
|
||||
|
||||
Object[] bindvalues = new Object[props.length];
|
||||
Object[] bindValues = new Object[props.length];
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
bindvalues[i] = props[i].getValue((EntityBean) value);
|
||||
bindValues[i] = props[i].getValue((EntityBean) value);
|
||||
}
|
||||
return bindvalues;
|
||||
return bindValues;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,7 +233,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
*/
|
||||
@Override
|
||||
public Object getIdForJson(EntityBean bean) {
|
||||
|
||||
EntityBean ebValue = (EntityBean) embIdProperty.getValue(bean);
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
for (BeanProperty prop : props) {
|
||||
@@ -261,7 +247,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertIdFromJson(Object value) {
|
||||
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
EntityBean idValue = idDesc.createEntityBean();
|
||||
for (BeanProperty prop : props) {
|
||||
@@ -270,7 +255,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
return idValue;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
|
||||
for (BeanProperty prop : props) {
|
||||
@@ -281,7 +265,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException {
|
||||
|
||||
for (BeanProperty prop : props) {
|
||||
Object embFieldValue = prop.getValue((EntityBean) value);
|
||||
prop.bind(dataBind, embFieldValue);
|
||||
@@ -306,10 +289,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
|
||||
EntityBean embId = idDesc.createEntityBean();
|
||||
boolean notNull = true;
|
||||
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.readData(dataInput);
|
||||
prop.setValue(embId, value);
|
||||
@@ -317,12 +298,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
notNull = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (notNull) {
|
||||
return embId;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return notNull ? embId : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -342,10 +318,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
EntityBean embId = idDesc.createEntityBean();
|
||||
boolean nullValue = true;
|
||||
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.read(ctx);
|
||||
if (value != null) {
|
||||
@@ -353,17 +327,11 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
nullValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (nullValue) {
|
||||
return null;
|
||||
} else {
|
||||
return embId;
|
||||
}
|
||||
return nullValue ? null : embId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
|
||||
Object embId = read(ctx);
|
||||
if (embId != null) {
|
||||
embIdProperty.setValue(bean, embId);
|
||||
@@ -382,7 +350,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
@@ -401,7 +368,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -411,7 +377,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
sb.append(prefix);
|
||||
sb.append(".");
|
||||
}
|
||||
|
||||
sb.append(embIdProperty.getName());
|
||||
sb.append(".");
|
||||
sb.append(props[i].getName());
|
||||
@@ -422,7 +387,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -440,11 +404,9 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
|
||||
if (idInExpandedForm) {
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
@@ -476,19 +438,16 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object convertSetId(Object idValue, EntityBean bean) {
|
||||
|
||||
// can not cast/convert if it is embedded
|
||||
if (bean != null) {
|
||||
// support PropertyChangeSupport
|
||||
embIdProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
|
||||
return idValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cacheKey(Object value) {
|
||||
|
||||
EntityBean bean = (EntityBean)value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (BeanProperty prop : props) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -8,28 +9,26 @@ import java.util.Map;
|
||||
* <p>
|
||||
* Typically collects the overridden column names mapped
|
||||
* to the Embedded bean.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployBeanEmbedded {
|
||||
|
||||
/**
|
||||
* A map of property names to dbColumns.
|
||||
*/
|
||||
private final Map<String, String> propMap = new HashMap<>();
|
||||
private final Map<String, Column> propMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Set a Map of property names to dbColumns.
|
||||
*/
|
||||
public void putAll(Map<String, String> propertyColumnMap) {
|
||||
public void putAll(Map<String, Column> propertyColumnMap) {
|
||||
propMap.putAll(propertyColumnMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of property names to dbColumns.
|
||||
*/
|
||||
public Map<String, String> getPropertyColumnMap() {
|
||||
public Map<String, Column> getPropertyColumnMap() {
|
||||
return propMap;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.validation.groups.Default;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -89,9 +90,9 @@ public abstract class AnnotationParser extends AnnotationBase {
|
||||
|
||||
Set<AttributeOverride> attrOverrides = annotationAttributeOverrides(prop);
|
||||
if (!attrOverrides.isEmpty()) {
|
||||
HashMap<String, String> propMap = new HashMap<>(attrOverrides.size());
|
||||
Map<String, Column> propMap = new HashMap<>(attrOverrides.size());
|
||||
for (AttributeOverride attrOverride : attrOverrides) {
|
||||
propMap.put(attrOverride.name(), attrOverride.column().name());
|
||||
propMap.put(attrOverride.name(), attrOverride.column());
|
||||
}
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static io.ebean.util.StringHelper.replaceString;
|
||||
|
||||
/**
|
||||
* Holds property and constructor meta data for a given DTO bean type.
|
||||
*
|
||||
@@ -88,7 +86,7 @@ class DtoMeta {
|
||||
property = propMap.get(upperLabel.substring(3));
|
||||
}
|
||||
if (property == null) {
|
||||
property = propMap.get(replaceString(upperLabel, "_", ""));
|
||||
property = propMap.get(upperLabel.replace("_", ""));
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import io.ebeaninternal.server.type.TypeManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -34,32 +32,49 @@ class DtoMetaBuilder {
|
||||
this.typeManager = typeManager;
|
||||
}
|
||||
|
||||
public DtoMeta build() throws IntrospectionException {
|
||||
|
||||
DtoMeta build() {
|
||||
readConstructors();
|
||||
readProperties();
|
||||
|
||||
return new DtoMeta(dtoType, constructorList, properties);
|
||||
}
|
||||
|
||||
private void readProperties() throws IntrospectionException {
|
||||
|
||||
BeanInfo beanInfo = Introspector.getBeanInfo(dtoType);
|
||||
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
|
||||
if (include(propertyDescriptor)) {
|
||||
private void readProperties() {
|
||||
for (Method method : dtoType.getMethods()) {
|
||||
if (includeMethod(method)) {
|
||||
try {
|
||||
properties.add(new DtoMetaProperty(typeManager, propertyDescriptor, dtoType));
|
||||
final String name = propertyName(method.getName());
|
||||
final Class<?> propertyType = propertyType(method);
|
||||
properties.add(new DtoMetaProperty(typeManager, dtoType, method, name, propertyType));
|
||||
} catch (Exception e) {
|
||||
log.debug("exclude on " + dtoType + " property " + propertyDescriptor.getName(), e);
|
||||
log.debug("exclude on " + dtoType + " method " + method, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Class<?> propertyType(Method method) {
|
||||
return method.getParameterTypes()[0];
|
||||
}
|
||||
|
||||
static String propertyName(String methodName) {
|
||||
final String name = methodName.substring(3);
|
||||
return Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Include a public "setter" method - 1 argument, returns void.
|
||||
*/
|
||||
static boolean includeMethod(Method method) {
|
||||
final int modifiers = method.getModifiers();
|
||||
return Modifier.isPublic(modifiers)
|
||||
&& !Modifier.isStatic(modifiers)
|
||||
&& Void.TYPE.equals(method.getReturnType())
|
||||
&& method.getParameterTypes().length == 1
|
||||
&& method.getName().startsWith("set") && method.getName().length() > 3;
|
||||
}
|
||||
|
||||
private void readConstructors() {
|
||||
|
||||
Constructor<?>[] constructors = dtoType.getConstructors();
|
||||
|
||||
for (Constructor<?> constructor : constructors) {
|
||||
try {
|
||||
constructorList.add(new DtoMetaConstructor(typeManager, constructor, dtoType));
|
||||
@@ -70,8 +85,4 @@ class DtoMetaBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean include(PropertyDescriptor property) {
|
||||
return !property.getName().equals("class");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
import io.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
@@ -20,19 +19,12 @@ class DtoMetaProperty implements DtoReadSet {
|
||||
private final MethodHandle setter;
|
||||
private final ScalarType<?> scalarType;
|
||||
|
||||
DtoMetaProperty(TypeManager typeManager, PropertyDescriptor descriptor, Class<?> dtoType) throws IllegalAccessException, NoSuchMethodException {
|
||||
|
||||
DtoMetaProperty(TypeManager typeManager, Class<?> dtoType, Method writeMethod, String name, Class<?> propertyType) throws IllegalAccessException, NoSuchMethodException {
|
||||
this.dtoType = dtoType;
|
||||
this.name = descriptor.getName();
|
||||
|
||||
Method writeMethod = descriptor.getWriteMethod();
|
||||
this.name = name;
|
||||
if (writeMethod != null) {
|
||||
|
||||
Class<?> propertyType = descriptor.getPropertyType();
|
||||
|
||||
this.setter = LOOKUP.findVirtual(dtoType, writeMethod.getName(), MethodType.methodType(void.class, propertyType));
|
||||
this.scalarType = typeManager.getScalarType(propertyType);
|
||||
|
||||
} else {
|
||||
this.scalarType = null;
|
||||
this.setter = null;
|
||||
@@ -58,11 +50,11 @@ class DtoMetaProperty implements DtoReadSet {
|
||||
try {
|
||||
setter.invoke(instance, arg);
|
||||
} catch (Throwable e) {
|
||||
throw new RuntimeException("Error calling setter for property " + fullname() + " with arg: " + arg, e);
|
||||
throw new RuntimeException("Error calling setter for property " + fullName() + " with arg: " + arg, e);
|
||||
}
|
||||
}
|
||||
|
||||
private String fullname() {
|
||||
private String fullName() {
|
||||
return dtoType.getName() + "." + name;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.ebean.bean.EntityBean;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.text.StringParser;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
@@ -99,14 +98,12 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
if (prefix == null) {
|
||||
return lastElPropertyValue.getElPlaceholder(encrypted);
|
||||
}
|
||||
|
||||
String el = lastElPropertyValue.getElPlaceholder(encrypted);
|
||||
|
||||
if (!el.contains("${}")) {
|
||||
// typically a secondary table property
|
||||
return StringHelper.replaceString(el, "${", "${" + prefix + ".");
|
||||
return el.replace("${", "${" + prefix + ".");
|
||||
} else {
|
||||
return StringHelper.replaceString(el, ROOT_ELPREFIX, "${" + prefix + "}");
|
||||
return el.replace(ROOT_ELPREFIX, "${" + prefix + "}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.loadcontext;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.BeanLoader;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
@@ -10,6 +11,7 @@ import io.ebeaninternal.api.LoadBeanRequest;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -32,7 +34,13 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
this.cache = (queryProps == null) ? false : queryProps.isCache();
|
||||
this.cache = (queryProps != null) && queryProps.isCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(BeanPropertyAssocMany<?> many, BeanCollection<?> collection) {
|
||||
String path = fullPath + "." + many.getName();
|
||||
parent.register(path, many, collection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,7 +183,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
// A synchronized (this) is effectively held by EntityBeanIntercept.loadBean()
|
||||
if (context.desc.lazyLoadMany(ebi)) {
|
||||
if (context.desc.lazyLoadMany(ebi, context)) {
|
||||
// lazy load property was a Many
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -283,8 +283,8 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String path, BeanCollection<?> bc) {
|
||||
getManyContext(path).register(bc);
|
||||
public void register(String path, BeanPropertyAssocMany<?> many, BeanCollection<?> bc) {
|
||||
getManyContext(path, many).register(bc);
|
||||
}
|
||||
|
||||
DLoadBeanContext getBeanContext(String path) {
|
||||
@@ -315,11 +315,12 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
}
|
||||
|
||||
DLoadManyContext getManyContext(String path) {
|
||||
if (path == null) {
|
||||
throw new RuntimeException("path is null?");
|
||||
}
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, defaultBatchSize, null));
|
||||
DLoadManyContext getManyContext(String path, BeanPropertyAssocMany<?> many) {
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, many, defaultBatchSize));
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, BeanPropertyAssocMany<?> many, int batchSize) {
|
||||
return new DLoadManyContext(this, many, path, batchSize, null);
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
package io.ebeaninternal.server.persist;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility to improve logging of raw SQL that contains new line characters.
|
||||
*/
|
||||
public class TrimLogSql {
|
||||
|
||||
/**
|
||||
* Statically compiled Regex, to avoid having it be compiled every time it is used.
|
||||
*/
|
||||
private static final Pattern LINUX_NEW_LINE_REPLACE_PATTERN = Pattern.compile("\n", Pattern.LITERAL);
|
||||
|
||||
/**
|
||||
* Replace new line chars for nicer logging of multi-line sql strings.
|
||||
*/
|
||||
public static String trim(String sql) {
|
||||
return LINUX_NEW_LINE_REPLACE_PATTERN.matcher(sql).replaceAll(Matcher.quoteReplacement("\\n "));
|
||||
return sql.replace("\n","\\n ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,8 +75,7 @@ public final class DmlBeanPersister implements BeanPersister {
|
||||
|
||||
} catch (SQLException e) {
|
||||
// log the error to the transaction log
|
||||
String errMsg = StringHelper.replaceStringMulti(e.getMessage(), new String[]{"\r", "\n"}, " ");
|
||||
String msg = "Error[" + errMsg + "]";
|
||||
String msg = "Error[" + StringHelper.removeNewLines(e.getMessage()) + "]";
|
||||
if (request.getTransaction().isLogSummary()) {
|
||||
request.getTransaction().logSummary(msg);
|
||||
}
|
||||
|
||||
@@ -636,10 +636,9 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String path, BeanCollection<?> bc) {
|
||||
|
||||
path = getPath(path);
|
||||
request.getGraphContext().register(path, bc);
|
||||
public void register(BeanPropertyAssocMany<?> many, BeanCollection<?> bc) {
|
||||
String path = getPath(many.getName());
|
||||
request.getGraphContext().register(path, many, bc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,6 @@ import io.ebean.config.dbplatform.SqlLimiter;
|
||||
import io.ebean.event.readaudit.ReadAuditQueryPlan;
|
||||
import io.ebean.text.PathProperties;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -176,16 +175,14 @@ class CQueryBuilder {
|
||||
* Strip the root table alias.
|
||||
*/
|
||||
private String aliasStrip(String sql) {
|
||||
sql = StringHelper.replaceString(sql, "${RTA}.", "");
|
||||
return StringHelper.replaceString(sql, " ${RTA}", "");
|
||||
return sql.replace("${RTA}.", "").replace(" ${RTA}", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the root table alias.
|
||||
*/
|
||||
private String aliasReplace(String sql, String replaceWith) {
|
||||
sql = StringHelper.replaceString(sql, "${RTA}.", replaceWith + ".");
|
||||
return StringHelper.replaceString(sql, "${RTA}", replaceWith);
|
||||
return sql.replace("${RTA}.", replaceWith + ".").replace("${RTA}", replaceWith);
|
||||
}
|
||||
|
||||
CQueryFetchSingleAttribute buildFetchAttributeQuery(OrmQueryRequest<?> request) {
|
||||
@@ -680,7 +677,7 @@ class CQueryBuilder {
|
||||
}
|
||||
if (updateStatement) {
|
||||
// strip the table alias for use in update statement
|
||||
idSql = StringHelper.replaceString(idSql, "t0.", "");
|
||||
idSql = idSql.replace("t0.", "");
|
||||
}
|
||||
sb.append(idSql).append(" ");
|
||||
hasWhere = true;
|
||||
|
||||
@@ -136,8 +136,7 @@ public class CQueryEngine {
|
||||
SpiTransaction t = request.getTransaction();
|
||||
if (t.isLogSummary()) {
|
||||
// log the error to the transaction log
|
||||
String errMsg = StringHelper.replaceStringMulti(e.getMessage(), new String[]{"\r", "\n"}, "\\n ");
|
||||
String msg = "ERROR executing query, bindLog[" + bindLog + "] error[" + errMsg + "]";
|
||||
String msg = "ERROR executing query, bindLog[" + bindLog + "] error[" + StringHelper.removeNewLines(e.getMessage()) + "]";
|
||||
t.logSummary(msg);
|
||||
}
|
||||
|
||||
@@ -260,10 +259,8 @@ public class CQueryEngine {
|
||||
query.where().lt(sysPeriodLower, query.getVersionEnd());
|
||||
}
|
||||
|
||||
// order by id asc, lower sys period desc
|
||||
query.order().asc(request.getBeanDescriptor().getIdProperty().getName());
|
||||
// order by lower sys period desc
|
||||
query.order().desc(sysPeriodLower);
|
||||
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
try {
|
||||
cquery.prepareBindExecuteQuery();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import io.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
@@ -150,26 +149,21 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
if (pair.getForeignSqlFormula() != null) {
|
||||
sb.append(StringHelper.replaceString(pair.getForeignSqlFormula(), tableAliasPlaceHolder, a2));
|
||||
sb.append(pair.getForeignSqlFormula().replace(tableAliasPlaceHolder, a2));
|
||||
} else {
|
||||
sb.append(a2).append(".").append(pair.getForeignDbColumn());
|
||||
}
|
||||
|
||||
sb.append(" = ");
|
||||
|
||||
if (pair.getLocalSqlFormula() != null) {
|
||||
sb.append(StringHelper.replaceString(pair.getLocalSqlFormula(), tableAliasPlaceHolder, a1));
|
||||
sb.append(pair.getLocalSqlFormula().replace(tableAliasPlaceHolder, a1));
|
||||
} else {
|
||||
sb.append(a1).append(".").append(pair.getLocalDbColumn());
|
||||
}
|
||||
}
|
||||
|
||||
if (addAsOfOnClause) {
|
||||
sb.append(" and ").append(historySupport.getAsOfPredicate(a2));
|
||||
}
|
||||
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
@@ -228,7 +222,7 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
// replace ${ta} place holder with the real table alias...
|
||||
String tableAlias = tableAliasStack.peek();
|
||||
String converted = StringHelper.replaceString(sqlFormulaJoin, tableAliasPlaceHolder, tableAlias);
|
||||
String converted = sqlFormulaJoin.replace(tableAliasPlaceHolder, tableAlias);
|
||||
|
||||
if (formulaJoins == null) {
|
||||
formulaJoins = new HashSet<>();
|
||||
@@ -268,12 +262,9 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
@Override
|
||||
public void appendFormulaSelect(String sqlFormulaSelect) {
|
||||
|
||||
String tableAlias = tableAliasStack.peek();
|
||||
String converted = StringHelper.replaceString(sqlFormulaSelect, tableAliasPlaceHolder, tableAlias);
|
||||
sb.append(COMMA);
|
||||
sb.append(converted);
|
||||
|
||||
sb.append(sqlFormulaSelect.replace(tableAliasPlaceHolder, tableAlias));
|
||||
appendColumnAlias();
|
||||
}
|
||||
|
||||
@@ -308,12 +299,10 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
@Override
|
||||
public void appendColumn(String tableAlias, String column) {
|
||||
sb.append(COMMA);
|
||||
|
||||
if (column.contains("${}")) {
|
||||
// support DB functions such as lower() etc
|
||||
// with the use of secondary columns
|
||||
String x = StringHelper.replaceString(column, "${}", tableAlias);
|
||||
sb.append(x);
|
||||
sb.append(column.replace("${}", tableAlias));
|
||||
} else {
|
||||
sb.append(tableAlias);
|
||||
sb.append(PERIOD);
|
||||
|
||||
@@ -2,11 +2,17 @@ package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
|
||||
public interface STreePropertyAssocMany extends STreePropertyAssoc {
|
||||
|
||||
/**
|
||||
* Return as BeanPropertyAssocMany.
|
||||
*/
|
||||
BeanPropertyAssocMany<?> asMany();
|
||||
|
||||
/**
|
||||
* Append exported columns to the select.
|
||||
*/
|
||||
|
||||
@@ -8,16 +8,12 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Special Map of the logical property joins to table alias.
|
||||
*/
|
||||
class SqlTreeAlias {
|
||||
|
||||
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
|
||||
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
|
||||
private int counter;
|
||||
@@ -87,15 +83,12 @@ class SqlTreeAlias {
|
||||
* Build a set of table alias for the given bean and fetch joined properties.
|
||||
*/
|
||||
void buildAlias() {
|
||||
|
||||
for (String joinProp : joinProps) {
|
||||
calcAlias(joinProp);
|
||||
}
|
||||
|
||||
for (String joinProp : manyWhereJoinProps) {
|
||||
calcAliasManyWhere(joinProp);
|
||||
}
|
||||
|
||||
mapEmbeddedPropertyAlias();
|
||||
}
|
||||
|
||||
@@ -111,14 +104,12 @@ class SqlTreeAlias {
|
||||
}
|
||||
|
||||
private String calcAlias(String prefix) {
|
||||
|
||||
String alias = nextTableAlias();
|
||||
aliasMap.put(prefix, alias);
|
||||
return alias;
|
||||
}
|
||||
|
||||
private void calcAliasManyWhere(String prefix) {
|
||||
|
||||
String alias = nextManyWhereTableAlias();
|
||||
manyWhereAliasMap.put(prefix, alias);
|
||||
}
|
||||
@@ -176,12 +167,11 @@ class SqlTreeAlias {
|
||||
/**
|
||||
* Parse the clause replacing the table alias place holders.
|
||||
*/
|
||||
private String parseRootAlias(String clause) {
|
||||
|
||||
String parseRootAlias(String clause) {
|
||||
if (rootTableAlias == null) {
|
||||
return TABLE_ALIAS_REPLACE.matcher(clause).replaceAll("");
|
||||
return clause.replace("${}", "");
|
||||
} else {
|
||||
return TABLE_ALIAS_REPLACE.matcher(clause).replaceAll(Matcher.quoteReplacement(rootTableAlias + "."));
|
||||
return clause.replace("${}", rootTableAlias + ".");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,12 +179,10 @@ class SqlTreeAlias {
|
||||
* Parse the clause replacing the table alias place holders.
|
||||
*/
|
||||
private String parseAliasMap(String clause, HashMap<String, String> parseAliasMap) {
|
||||
|
||||
for (Map.Entry<String, String> e : parseAliasMap.entrySet()) {
|
||||
String k = "${" + e.getKey() + "}";
|
||||
clause = clause.replace(k, e.getValue() + ".");
|
||||
}
|
||||
|
||||
return clause;
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +299,7 @@ public final class SqlTreeBuilder {
|
||||
Collection<PropertyJoin> includes = manyWhereJoins.getPropertyJoins();
|
||||
for (PropertyJoin joinProp : includes) {
|
||||
STreePropertyAssoc beanProperty = (STreePropertyAssoc) desc.findPropertyFromPath(joinProp.getProperty());
|
||||
SqlTreeNodeManyWhereJoin nodeJoin = new SqlTreeNodeManyWhereJoin(joinProp.getProperty(), beanProperty, joinProp.getSqlJoinType());
|
||||
SqlTreeNodeManyWhereJoin nodeJoin = new SqlTreeNodeManyWhereJoin(joinProp.getProperty(), beanProperty, joinProp.getSqlJoinType(), temporalMode);
|
||||
myJoinList.add(nodeJoin);
|
||||
}
|
||||
if (manyWhereJoins.isFormulaWithJoin()) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiQuery.Mode;
|
||||
import io.ebeaninternal.server.deploy.DbReadContext;
|
||||
@@ -107,7 +106,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
private SqlTreeNodeBean(String prefix, STreePropertyAssoc beanProp, STreeType desc, SqlTreeProperties props,
|
||||
List<SqlTreeNode> myChildren, boolean withId, STreePropertyAssocMany lazyLoadParent,
|
||||
SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
|
||||
|
||||
this.lazyLoadParent = lazyLoadParent;
|
||||
this.lazyLoadParentIdBinder = (lazyLoadParent == null) ? null : lazyLoadParent.getIdBinder();
|
||||
this.prefix = prefix;
|
||||
@@ -116,21 +114,16 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
this.idBinder = desc.getIdBinder();
|
||||
this.temporalMode = temporalMode;
|
||||
this.temporalVersions = temporalMode == SpiQuery.TemporalMode.VERSIONS;
|
||||
|
||||
this.nodeBeanProp = beanProp;
|
||||
this.extraWhere = (beanProp == null) ? null : beanProp.getExtraWhere();
|
||||
|
||||
this.aggregation = props.isAggregation();
|
||||
boolean aggregationRoot = props.isAggregationRoot();
|
||||
|
||||
// the bean has an Id property and we want to use it
|
||||
this.readId = !aggregationRoot && withId && desc.hasId();
|
||||
this.disableLazyLoad = disableLazyLoad || !readId || desc.isRawSqlBased() || temporalVersions;
|
||||
|
||||
this.partialObject = props.isPartialObject();
|
||||
this.properties = props.getProps();
|
||||
this.children = myChildren == null ? NO_CHILDREN : myChildren.toArray(new SqlTreeNode[0]);
|
||||
|
||||
pathMap = createPathMap(prefix, desc);
|
||||
}
|
||||
|
||||
@@ -163,7 +156,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
}
|
||||
|
||||
private Map<String, String> createPathMap(String prefix, STreeType desc) {
|
||||
|
||||
HashMap<String, String> m = new HashMap<>();
|
||||
for (STreePropertyAssocMany many : desc.propsMany()) {
|
||||
String name = many.getName();
|
||||
@@ -206,13 +198,11 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Version<T> loadVersion(DbReadContext ctx) throws SQLException {
|
||||
|
||||
// read the sys period lower and upper bounds
|
||||
// these are always the first 2 columns in the resultSet
|
||||
Timestamp start = ctx.getDataReader().getTimestamp();
|
||||
Timestamp end = ctx.getDataReader().getTimestamp();
|
||||
T bean = (T) load(ctx, null, null);
|
||||
|
||||
return new Version<>(bean, start, end);
|
||||
}
|
||||
|
||||
@@ -326,7 +316,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
private void readIdNullBean() {
|
||||
// bean must be null...
|
||||
localBean = null;
|
||||
|
||||
// ... but there may exist as reference bean in parent which has to be marked as deleted.
|
||||
if (parentBean != null && nodeBeanProp instanceof STreePropertyAssocOne) {
|
||||
contextBean = ((STreePropertyAssocOne)nodeBeanProp).getValueAsEntityBean(parentBean);
|
||||
@@ -355,7 +344,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
localBean = contextBean;
|
||||
lazyLoadMany = true;
|
||||
}
|
||||
|
||||
// recursively continue reading...
|
||||
for (SqlTreeNode aChildren : children) {
|
||||
// read each child... and let them set their
|
||||
@@ -430,7 +418,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
ref.setDisableLazyLoad(true);
|
||||
}
|
||||
if (!ref.isRegisteredWithLoadContext()) {
|
||||
ctx.register(many.getName(), ref);
|
||||
ctx.register(many.asMany(), ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -476,7 +464,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
*/
|
||||
@Override
|
||||
public EntityBean load(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) throws SQLException {
|
||||
|
||||
Load load = (inheritInfo != null) ? new LoadInherit(ctx, parentBean) : new Load(ctx, parentBean);
|
||||
load.initialise();
|
||||
if (load.isLazyLoadManyRoot()) {
|
||||
@@ -489,7 +476,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
@Override
|
||||
public void appendGroupBy(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
ctx.pushJoin(prefix);
|
||||
ctx.pushTableAlias(prefix);
|
||||
if (lazyLoadParent != null) {
|
||||
@@ -525,19 +511,15 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
*/
|
||||
@Override
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
|
||||
ctx.pushJoin(prefix);
|
||||
ctx.pushTableAlias(prefix);
|
||||
|
||||
if (temporalVersions) {
|
||||
// select sys_period lower and upper columns
|
||||
ctx.appendHistorySysPeriod();
|
||||
}
|
||||
|
||||
if (lazyLoadParent != null) {
|
||||
lazyLoadParent.addSelectExported(ctx, prefix);
|
||||
}
|
||||
|
||||
if (readId) {
|
||||
if (!subQuery && inheritInfo != null) {
|
||||
ctx.appendColumn(inheritInfo.getDiscriminatorColumn());
|
||||
@@ -551,7 +533,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
// values back to this localBean
|
||||
aChildren.appendSelect(ctx, subQuery);
|
||||
}
|
||||
|
||||
ctx.popTableAlias();
|
||||
ctx.popJoin();
|
||||
}
|
||||
@@ -586,7 +567,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
@Override
|
||||
public void appendWhere(DbSqlContext ctx) {
|
||||
|
||||
// Only apply inheritance to root node as any join will already have the inheritance join include - see TableJoin
|
||||
if (inheritInfo != null && nodeBeanProp == null) {
|
||||
if (!inheritInfo.isRoot()) {
|
||||
@@ -598,9 +578,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
ctx.append(inheritInfo.getWhere());
|
||||
}
|
||||
}
|
||||
|
||||
appendExtraWhere(ctx);
|
||||
|
||||
for (SqlTreeNode aChildren : children) {
|
||||
// recursively add to the where clause any
|
||||
// fixed predicates (extraWhere etc)
|
||||
@@ -614,8 +592,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
ctx.append(" and");
|
||||
}
|
||||
String ta = ctx.getTableAlias(prefix);
|
||||
String ew = StringHelper.replaceString(extraWhere, "${ta}", ta);
|
||||
ctx.append(" ").append(ew).append(" ");
|
||||
ctx.append(" ").append(extraWhere.replace("${ta}", ta)).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,7 +628,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
@Override
|
||||
public void addSoftDeletePredicate(SpiQuery<?> query) {
|
||||
|
||||
if (desc.isSoftDelete()) {
|
||||
query.addSoftDeletePredicate(desc.getSoftDeletePredicate(baseTableAlias));
|
||||
}
|
||||
@@ -688,17 +664,17 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
* table if this is a ManyToMany node.
|
||||
*/
|
||||
SqlJoinType appendFromBaseTable(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
SqlJoinType sqlJoinType = appendFromAsJoin(ctx, joinType);
|
||||
if (temporalMode != SpiQuery.TemporalMode.SOFT_DELETED && desc.isSoftDelete()) {
|
||||
// add the soft delete predicate to the join clause
|
||||
if (inheritInfo != null) {
|
||||
appendJoinDiscriminator(ctx);
|
||||
}
|
||||
if (desc.isSoftDelete() && temporalMode != SpiQuery.TemporalMode.SOFT_DELETED) {
|
||||
ctx.append("and ").append(desc.getSoftDeletePredicate(ctx.getTableAlias(prefix))).append(" ");
|
||||
}
|
||||
return sqlJoinType;
|
||||
}
|
||||
|
||||
SqlJoinType appendFromAsJoin(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
if (nodeBeanProp instanceof STreePropertyAssocMany) {
|
||||
STreePropertyAssocMany manyProp = (STreePropertyAssocMany) nodeBeanProp;
|
||||
if (manyProp.hasJoinTable()) {
|
||||
@@ -714,14 +690,18 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (!manyProp.isExcludedFromHistory()) {
|
||||
intersectionAsOfTableAlias = true;
|
||||
}
|
||||
|
||||
return nodeBeanProp.addJoin(joinType, alias2, alias, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return nodeBeanProp.addJoin(joinType, prefix, ctx);
|
||||
}
|
||||
|
||||
void appendJoinDiscriminator(DbSqlContext ctx) {
|
||||
if (inheritInfo.getWhere() == null) return;
|
||||
String alias = ctx.getTableAlias(prefix);
|
||||
ctx.append(" and ").append(alias).append(".").append(inheritInfo.getWhere());
|
||||
}
|
||||
|
||||
/**
|
||||
* Summary description.
|
||||
*/
|
||||
@@ -735,14 +715,12 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (queryMode.isLoadContextBean()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// reload if contextBean is partial object
|
||||
return !contextBean._ebean_getIntercept().isFullyLoadedBean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMany() {
|
||||
|
||||
for (SqlTreeNode child : children) {
|
||||
if (child.hasMany()) {
|
||||
return true;
|
||||
|
||||
@@ -23,16 +23,21 @@ class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
|
||||
|
||||
private final STreePropertyAssoc nodeBeanProp;
|
||||
|
||||
private final STreeType target;
|
||||
|
||||
/**
|
||||
* The many where join which is either INNER or OUTER.
|
||||
*/
|
||||
private final SqlJoinType manyJoinType;
|
||||
|
||||
SqlTreeNodeManyWhereJoin(String prefix, STreePropertyAssoc prop, SqlJoinType manyJoinType) {
|
||||
private final boolean softDelete;
|
||||
|
||||
SqlTreeNodeManyWhereJoin(String prefix, STreePropertyAssoc prop, SqlJoinType manyJoinType, SpiQuery.TemporalMode temporalMode) {
|
||||
this.nodeBeanProp = prop;
|
||||
this.prefix = prefix;
|
||||
this.manyJoinType = manyJoinType;
|
||||
|
||||
this.target = nodeBeanProp.target();
|
||||
this.softDelete = (temporalMode != SpiQuery.TemporalMode.SOFT_DELETED && target.isSoftDelete());
|
||||
String[] split = SplitName.split(prefix);
|
||||
this.parentPrefix = split[0];
|
||||
}
|
||||
@@ -94,12 +99,16 @@ class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
|
||||
|
||||
if (nodeBeanProp instanceof STreePropertyAssocOne) {
|
||||
nodeBeanProp.addJoin(joinType, parentAlias, alias, ctx);
|
||||
|
||||
if (softDelete) {
|
||||
ctx.append("and ").append(target.getSoftDeletePredicate(alias)).append(" ");
|
||||
}
|
||||
} else {
|
||||
STreePropertyAssocMany manyProp = (STreePropertyAssocMany) nodeBeanProp;
|
||||
if (!manyProp.hasJoinTable()) {
|
||||
manyProp.addJoin(joinType, parentAlias, alias, ctx);
|
||||
|
||||
if (softDelete) {
|
||||
ctx.append("and ").append(target.getSoftDeletePredicate(alias)).append(" ");
|
||||
}
|
||||
} else {
|
||||
String alias2 = alias + "z_";
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.ebeaninternal.server.querydefn;
|
||||
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.util.StringHelper;
|
||||
import io.ebeaninternal.server.util.DSelectColumnsParser;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -77,12 +76,12 @@ class OrmQueryPropertiesParser {
|
||||
}
|
||||
int pos = inputProperties.indexOf("+readonly");
|
||||
if (pos > -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, "+readonly", "");
|
||||
inputProperties = inputProperties.replace("+readonly", "");
|
||||
readOnly = true;
|
||||
}
|
||||
pos = inputProperties.indexOf("+cache");
|
||||
if (pos > -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, "+cache", "");
|
||||
inputProperties = inputProperties.replace("+cache", "");
|
||||
cache = true;
|
||||
}
|
||||
pos = inputProperties.indexOf("+query");
|
||||
@@ -162,7 +161,7 @@ class OrmQueryPropertiesParser {
|
||||
int startPos = pos + option.length();
|
||||
int endPos = findEndPos(startPos, inputProperties);
|
||||
if (endPos == -1) {
|
||||
inputProperties = StringHelper.replaceString(inputProperties, option, "");
|
||||
inputProperties = inputProperties.replace(option, "");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Set properties for a UpdateQuery.
|
||||
@@ -19,8 +18,6 @@ public class OrmUpdateProperties {
|
||||
|
||||
private static final NoneValue NONE_VALUE = new NoneValue();
|
||||
|
||||
private static final Pattern TABLE_ALIAS_REPLACE = Pattern.compile("${}", Pattern.LITERAL);
|
||||
|
||||
/**
|
||||
* Bind value used in the set clause for update query.
|
||||
* It may/may not have bind values etc.
|
||||
@@ -172,21 +169,22 @@ public class OrmUpdateProperties {
|
||||
* Build the actual set clause converting logical property names to db columns etc.
|
||||
*/
|
||||
public String buildSetClause(DeployParser deployParser) {
|
||||
|
||||
int setCount = 0;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (Map.Entry<String, Value> entry : values.entrySet()) {
|
||||
String property = entry.getKey();
|
||||
if (setCount++ > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
// translate to db columns and remove table alias placeholders
|
||||
sb.append(TABLE_ALIAS_REPLACE.matcher(deployParser.parse(property)).replaceAll(""));
|
||||
sb.append(trim(deployParser.parse(property)));
|
||||
sb.append(entry.getValue().bindClause());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
static String trim(String dbColumn) {
|
||||
return dbColumn.replace("${}", "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -189,27 +189,34 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
|
||||
private int initialSize;
|
||||
|
||||
private ClassContext parent;
|
||||
|
||||
private ClassContext() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create as a shallow copy.
|
||||
*/
|
||||
private ClassContext(ClassContext parent, boolean initial) {
|
||||
if (initial || parent.isInitialSize()) {
|
||||
this.map.putAll(parent.map);
|
||||
this.initialSize = map.size();
|
||||
if (parent.deleteSet != null) {
|
||||
this.deleteSet = new HashSet<>(parent.deleteSet);
|
||||
private ClassContext(ClassContext source, boolean initial) {
|
||||
if (initial || source.isTransfer()) {
|
||||
parent = source.transferParent();
|
||||
initialSize = parent.size();
|
||||
if (source.deleteSet != null) {
|
||||
deleteSet = new HashSet<>(source.deleteSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the map has not changed from it's initial size (no additions).
|
||||
* True if this should be transferred to a new iterator persistence context.
|
||||
*/
|
||||
private boolean isInitialSize() {
|
||||
return map.size() == initialSize;
|
||||
private boolean isTransfer() {
|
||||
// map not added to and has some original/parent beans
|
||||
return map.isEmpty() && initialSize > 0;
|
||||
}
|
||||
|
||||
private ClassContext transferParent() {
|
||||
return (parent != null) ? parent : this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,10 +227,10 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if grown above the reset limit size.
|
||||
* Return true if grown above the reset limit size of 1000.
|
||||
*/
|
||||
private boolean resetLimit() {
|
||||
return map.size() > initialSize + 1000;
|
||||
return map.size() > 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -231,20 +238,21 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
return "size:" + map.size();
|
||||
}
|
||||
|
||||
private Object get(Object id) {
|
||||
Object bean = (parent == null) ? null : parent.get(id);
|
||||
return bean != null ? bean : map.get(id);
|
||||
}
|
||||
|
||||
private WithOption getWithOption(Object id) {
|
||||
if (deleteSet != null && deleteSet.contains(id)) {
|
||||
return WithOption.DELETED;
|
||||
}
|
||||
Object bean = map.get(id);
|
||||
Object bean = get(id);
|
||||
return (bean == null) ? null : new WithOption(bean);
|
||||
}
|
||||
|
||||
private Object get(Object id) {
|
||||
return map.get(id);
|
||||
}
|
||||
|
||||
private Object putIfAbsent(Object id, Object bean) {
|
||||
Object existingValue = map.get(id);
|
||||
Object existingValue = get(id);
|
||||
if (existingValue != null) {
|
||||
// it is not absent
|
||||
return existingValue;
|
||||
@@ -259,7 +267,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
|
||||
private int size() {
|
||||
return map.size();
|
||||
return map.size() + initialSize;
|
||||
}
|
||||
|
||||
private void clear() {
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* JDBC Connection based transaction.
|
||||
@@ -346,55 +347,36 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
callbackList.add(callback);
|
||||
}
|
||||
|
||||
private void firePreRollback() {
|
||||
private void withEachCallback(Consumer<TransactionCallback> consumer) {
|
||||
if (callbackList != null) {
|
||||
for (TransactionCallback callback : callbackList) {
|
||||
// using old style loop to cater for case when new callbacks are added recursively (as otherwise iterator fails fast)
|
||||
for (int i = 0; i < callbackList.size(); i++) {
|
||||
try {
|
||||
callback.preRollback();
|
||||
consumer.accept(callbackList.get(i));
|
||||
} catch (Exception e) {
|
||||
logger.error("Error executing preRollback callback", e);
|
||||
logger.error("Error executing transaction callback", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void firePreRollback() {
|
||||
withEachCallback(TransactionCallback::preRollback);
|
||||
}
|
||||
|
||||
private void firePostRollback() {
|
||||
if (callbackList != null) {
|
||||
for (TransactionCallback callback : callbackList) {
|
||||
try {
|
||||
callback.postRollback();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error executing postRollback callback", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
withEachCallback(TransactionCallback::postRollback);
|
||||
if (changeLogHolder != null) {
|
||||
changeLogHolder.postRollback();
|
||||
}
|
||||
}
|
||||
|
||||
private void firePreCommit() {
|
||||
if (callbackList != null) {
|
||||
for (TransactionCallback callback : callbackList) {
|
||||
try {
|
||||
callback.preCommit();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error executing preCommit callback", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
withEachCallback(TransactionCallback::preCommit);
|
||||
}
|
||||
|
||||
private void firePostCommit() {
|
||||
if (callbackList != null) {
|
||||
for (TransactionCallback callback : callbackList) {
|
||||
try {
|
||||
callback.postCommit();
|
||||
} catch (Exception e) {
|
||||
logger.error("Error executing postCommit callback", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
withEachCallback(TransactionCallback::postCommit);
|
||||
if (changeLogHolder != null) {
|
||||
changeLogHolder.postCommit();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:05:12.077911Z
|
||||
-- Generated by ebean unknown at 2020-08-31T02:36:16.679053Z
|
||||
create table asimple_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -275,7 +275,7 @@ create table drel_booking (
|
||||
constraint uq_drel_booking_client_invoice unique (client_invoice),
|
||||
constraint pk_drel_booking primary key (id)
|
||||
);
|
||||
create sequence drel_booking_seq increment by 50;
|
||||
create sequence drel_booking_seq increment by 1;
|
||||
|
||||
create table bw_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -307,6 +307,28 @@ create table cepproduct_category (
|
||||
priority integer
|
||||
);
|
||||
|
||||
create table ciaddress (
|
||||
id bigint generated by default as identity not null,
|
||||
street_id bigint,
|
||||
constraint pk_ciaddress primary key (id)
|
||||
);
|
||||
|
||||
create table cicustomer_parent (
|
||||
dtype integer(31) not null,
|
||||
id bigint generated by default as identity not null,
|
||||
address_id bigint,
|
||||
notes varchar(255),
|
||||
constraint pk_cicustomer_parent primary key (id)
|
||||
);
|
||||
|
||||
create table cistreet_parent (
|
||||
dtype integer(31) not null,
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
num varchar(255),
|
||||
constraint pk_cistreet_parent primary key (id)
|
||||
);
|
||||
|
||||
create table cinh_ref (
|
||||
id integer generated by default as identity not null,
|
||||
ref_id integer,
|
||||
@@ -396,7 +418,7 @@ create table sp_car_car (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_car primary key (id)
|
||||
);
|
||||
create sequence sp_car_car_seq increment by 50;
|
||||
create sequence sp_car_car_seq increment by 1;
|
||||
|
||||
create table sp_car_car_wheels (
|
||||
car bigint not null,
|
||||
@@ -417,7 +439,7 @@ create table sa_car (
|
||||
version integer not null,
|
||||
constraint pk_sa_car primary key (id)
|
||||
);
|
||||
create sequence sa_car_seq increment by 50;
|
||||
create sequence sa_car_seq increment by 1;
|
||||
|
||||
create table car_accessory (
|
||||
id integer generated by default as identity not null,
|
||||
@@ -641,7 +663,7 @@ create table d_machine_aux_use (
|
||||
name varchar(255),
|
||||
edate date,
|
||||
use_secs bigint not null,
|
||||
fuel decimal(38),
|
||||
fuel decimal(16,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_aux_use primary key (id)
|
||||
);
|
||||
@@ -652,8 +674,8 @@ create table d_machine_stats (
|
||||
edate date,
|
||||
total_kms bigint not null,
|
||||
hours bigint not null,
|
||||
rate decimal(38),
|
||||
cost decimal(38),
|
||||
rate decimal(16,3),
|
||||
cost decimal(16,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_stats primary key (id)
|
||||
);
|
||||
@@ -664,7 +686,7 @@ create table d_machine_use (
|
||||
edate date,
|
||||
distance_kms bigint not null,
|
||||
time_secs bigint not null,
|
||||
fuel decimal(38),
|
||||
fuel decimal(9,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_use primary key (id)
|
||||
);
|
||||
@@ -680,7 +702,7 @@ create table dperson (
|
||||
id bigint generated by default as identity not null,
|
||||
first_name varchar(255),
|
||||
last_name varchar(255),
|
||||
salary decimal(38),
|
||||
salary decimal(16,3),
|
||||
constraint pk_dperson primary key (id)
|
||||
);
|
||||
|
||||
@@ -729,6 +751,16 @@ create table dc_master (
|
||||
constraint pk_dc_master primary key (id)
|
||||
);
|
||||
|
||||
create table defaults_model (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_defaults_model primary key (id)
|
||||
);
|
||||
|
||||
create table defaults_model_draft (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_defaults_model_draft primary key (id)
|
||||
);
|
||||
|
||||
create table dfk_cascade (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -864,7 +896,7 @@ create table sp_car_door (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_door primary key (id)
|
||||
);
|
||||
create sequence sp_car_door_seq increment by 50;
|
||||
create sequence sp_car_door_seq increment by 1;
|
||||
|
||||
create table earray_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -1309,11 +1341,11 @@ create table einvoice (
|
||||
invoice_date timestamp,
|
||||
state integer,
|
||||
person_id bigint,
|
||||
ship_street varchar(255),
|
||||
ship_street varchar(255) not null,
|
||||
ship_suburb varchar(255),
|
||||
ship_city varchar(255),
|
||||
ship_status varchar(3),
|
||||
bill_street varchar(255),
|
||||
bill_street varchar(255) not null,
|
||||
bill_suburb varchar(255),
|
||||
bill_city varchar(255),
|
||||
bill_status varchar(3),
|
||||
@@ -1389,7 +1421,7 @@ create table eperson (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
notes varchar(255),
|
||||
street varchar(255),
|
||||
street varchar(255) not null,
|
||||
suburb varchar(255),
|
||||
addr_city varchar(255),
|
||||
addr_status varchar(3),
|
||||
@@ -1398,6 +1430,31 @@ create table eperson (
|
||||
constraint pk_eperson primary key (id)
|
||||
);
|
||||
|
||||
create table eperson2 (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
notes varchar(255),
|
||||
street varchar(10),
|
||||
suburb varchar(100),
|
||||
city varchar(255) not null,
|
||||
status varchar(3) not null,
|
||||
version bigint not null,
|
||||
constraint ck_eperson2_status check ( status in ('ONE','TWO')),
|
||||
constraint pk_eperson2 primary key (id)
|
||||
);
|
||||
|
||||
create table eperson3 (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
street varchar(255),
|
||||
suburb varchar(255),
|
||||
city varchar(255),
|
||||
status varchar(3),
|
||||
version bigint not null,
|
||||
constraint ck_eperson3_status check ( status in ('ONE','TWO')),
|
||||
constraint pk_eperson3 primary key (id)
|
||||
);
|
||||
|
||||
create table e_person_online (
|
||||
id bigint generated by default as identity not null,
|
||||
email varchar(127),
|
||||
@@ -1511,7 +1568,7 @@ create table esoft_del_user_esoft_del_role (
|
||||
create table esome_convert_type (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
money decimal(38),
|
||||
money decimal(16,3),
|
||||
constraint pk_esome_convert_type primary key (id)
|
||||
);
|
||||
|
||||
@@ -1801,13 +1858,7 @@ create table gen_key_sequence (
|
||||
description varchar(255),
|
||||
constraint pk_gen_key_sequence primary key (id)
|
||||
);
|
||||
create sequence SEQ start with 1 increment by 50;
|
||||
|
||||
create table gen_key_table (
|
||||
id bigint generated by default as identity not null,
|
||||
description varchar(255),
|
||||
constraint pk_gen_key_table primary key (id)
|
||||
);
|
||||
create sequence SEQ_NAME increment by 1;
|
||||
|
||||
create table grand_parent_person (
|
||||
identifier integer generated by default as identity not null,
|
||||
@@ -2018,7 +2069,7 @@ create table drel_invoice (
|
||||
version integer not null,
|
||||
constraint pk_drel_invoice primary key (id)
|
||||
);
|
||||
create sequence drel_invoice_seq increment by 50;
|
||||
create sequence drel_invoice_seq increment by 1;
|
||||
|
||||
create table item (
|
||||
customer integer not null,
|
||||
@@ -2739,6 +2790,23 @@ create table om_ordered_master (
|
||||
constraint pk_om_ordered_master primary key (id)
|
||||
);
|
||||
|
||||
create table oml_bar (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_oml_bar primary key (id)
|
||||
);
|
||||
|
||||
create table oml_baz (
|
||||
id bigint generated by default as identity not null,
|
||||
foo_id bigint not null,
|
||||
constraint pk_oml_baz primary key (id)
|
||||
);
|
||||
|
||||
create table oml_foo (
|
||||
id bigint generated by default as identity not null,
|
||||
bar_id bigint not null,
|
||||
constraint pk_oml_foo primary key (id)
|
||||
);
|
||||
|
||||
create table only_id_entity (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_only_id_entity primary key (id)
|
||||
@@ -2778,10 +2846,30 @@ create table s_order_items (
|
||||
product_variant_uuid varchar(255),
|
||||
order_uuid varchar(40),
|
||||
quantity integer not null,
|
||||
amount decimal(38),
|
||||
amount decimal(16,3),
|
||||
constraint pk_s_order_items primary key (uuid)
|
||||
);
|
||||
|
||||
create table order_master (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_order_master primary key (id)
|
||||
);
|
||||
|
||||
create table order_master_inheritance (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_order_master_inheritance primary key (id)
|
||||
);
|
||||
|
||||
create table order_referenced_parent (
|
||||
type varchar(31) not null,
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
child_name varchar(255),
|
||||
master_id bigint,
|
||||
sort_order integer,
|
||||
constraint pk_order_referenced_parent primary key (id)
|
||||
);
|
||||
|
||||
create table or_order_ship (
|
||||
id integer generated by default as identity not null,
|
||||
order_id integer,
|
||||
@@ -2792,6 +2880,25 @@ create table or_order_ship (
|
||||
constraint pk_or_order_ship primary key (id)
|
||||
);
|
||||
|
||||
create table order_toy (
|
||||
id integer generated by default as identity not null,
|
||||
title varchar(255),
|
||||
child_id bigint,
|
||||
sort_order integer,
|
||||
constraint pk_order_toy primary key (id)
|
||||
);
|
||||
|
||||
create table ordered_parent (
|
||||
dtype varchar(31) not null,
|
||||
id integer generated by default as identity not null,
|
||||
order_master_inheritance_id integer not null,
|
||||
common_name varchar(255),
|
||||
sort_order integer,
|
||||
ordered_aname varchar(255),
|
||||
ordered_bname varchar(255),
|
||||
constraint pk_ordered_parent primary key (id)
|
||||
);
|
||||
|
||||
create table organisation (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -3305,6 +3412,20 @@ create table r_orders (
|
||||
constraint pk_r_orders primary key (company,order_number)
|
||||
);
|
||||
|
||||
create table referenced_defaults_model (
|
||||
id integer generated by default as identity not null,
|
||||
defaults_model_id integer not null,
|
||||
name varchar(255),
|
||||
constraint pk_referenced_defaults_model primary key (id)
|
||||
);
|
||||
|
||||
create table referenced_defaults_model_draft (
|
||||
id integer generated by default as identity not null,
|
||||
defaults_model_id integer not null,
|
||||
name varchar(255),
|
||||
constraint pk_referenced_defaults_model_draft primary key (id)
|
||||
);
|
||||
|
||||
create table referencing_bean (
|
||||
id uuid not null,
|
||||
constraint pk_referencing_bean primary key (id)
|
||||
@@ -3614,7 +3735,7 @@ create table t_detail_with_other_namexxxyy (
|
||||
constraint uq_t_detail_with_other_namexxxyy_some_unique_value unique (some_unique_value),
|
||||
constraint pk_t_detail_with_other_namexxxyy primary key (id)
|
||||
);
|
||||
create sequence t_atable_detail_seq increment by 50;
|
||||
create sequence t_atable_detail_seq increment by 1;
|
||||
|
||||
create table t_atable_thatisrelatively (
|
||||
id integer not null,
|
||||
@@ -3623,7 +3744,7 @@ create table t_atable_thatisrelatively (
|
||||
active boolean default false not null,
|
||||
constraint pk_t_atable_thatisrelatively primary key (id)
|
||||
);
|
||||
create sequence t_atable_master_seq increment by 50;
|
||||
create sequence t_atable_master_seq increment by 1;
|
||||
|
||||
create table ttruck_holder (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -3692,14 +3813,14 @@ create table tire (
|
||||
constraint uq_tire_wheel unique (wheel),
|
||||
constraint pk_tire primary key (id)
|
||||
);
|
||||
create sequence tire_seq increment by 50;
|
||||
create sequence tire_seq increment by 1;
|
||||
|
||||
create table sa_tire (
|
||||
id bigint not null,
|
||||
version integer not null,
|
||||
constraint pk_sa_tire primary key (id)
|
||||
);
|
||||
create sequence sa_tire_seq increment by 50;
|
||||
create sequence sa_tire_seq increment by 1;
|
||||
|
||||
create table tree_entity (
|
||||
id integer generated by default as identity not null,
|
||||
@@ -3900,13 +4021,38 @@ create table vehicle_lease (
|
||||
active_start date,
|
||||
active_end date,
|
||||
version bigint not null,
|
||||
bond decimal(38),
|
||||
bond decimal(16,3),
|
||||
min_duration integer not null,
|
||||
day_rate decimal(38),
|
||||
day_rate decimal(16,3),
|
||||
max_days integer,
|
||||
constraint pk_vehicle_lease primary key (id)
|
||||
);
|
||||
|
||||
create table version_child (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
parent_id integer,
|
||||
version integer not null,
|
||||
position integer,
|
||||
constraint pk_version_child primary key (id)
|
||||
);
|
||||
|
||||
create table version_parent (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
version integer not null,
|
||||
constraint pk_version_parent primary key (id)
|
||||
);
|
||||
|
||||
create table version_toy (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
child_id integer,
|
||||
version integer not null,
|
||||
position integer,
|
||||
constraint pk_version_toy primary key (id)
|
||||
);
|
||||
|
||||
create table warehouses (
|
||||
id integer generated by default as identity not null,
|
||||
officezoneid integer,
|
||||
@@ -3924,7 +4070,7 @@ create table wheel (
|
||||
version integer not null,
|
||||
constraint pk_wheel primary key (id)
|
||||
);
|
||||
create sequence wheel_seq increment by 50;
|
||||
create sequence wheel_seq increment by 1;
|
||||
|
||||
create table sa_wheel (
|
||||
id bigint not null,
|
||||
@@ -3933,7 +4079,7 @@ create table sa_wheel (
|
||||
version integer not null,
|
||||
constraint pk_sa_wheel primary key (id)
|
||||
);
|
||||
create sequence sa_wheel_seq increment by 50;
|
||||
create sequence sa_wheel_seq increment by 1;
|
||||
|
||||
create table sp_car_wheel (
|
||||
id bigint not null,
|
||||
@@ -3941,7 +4087,7 @@ create table sp_car_wheel (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_wheel primary key (id)
|
||||
);
|
||||
create sequence sp_car_wheel_seq increment by 50;
|
||||
create sequence sp_car_wheel_seq increment by 1;
|
||||
|
||||
create table g_who_props_otm (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -3987,7 +4133,11 @@ create index ix_contact_last_name_first_name on contact (last_name,first_name);
|
||||
create index ix_e_basic_name on e_basic (name);
|
||||
create index ix_efile2_no_fk_owner_id on efile2_no_fk (owner_id);
|
||||
create index ix_ecsm_values_host_id on ecsm_values (host_id);
|
||||
create index ix_order_referenced_parent_type on order_referenced_parent (type);
|
||||
create index ix_organization_node_kind on organization_node (kind);
|
||||
create index ano_3 on test_annotation_base_entity (direct);
|
||||
create index ano_1 on test_annotation_base_entity (direct);
|
||||
create index ano_2 on test_annotation_base_entity (direct);
|
||||
create index ix_bar_foo_id on bar (foo_id);
|
||||
alter table bar add constraint fk_bar_foo_id foreign key (foo_id) references foo (foo_id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4053,6 +4203,12 @@ alter table cepproduct_category add constraint fk_cepproduct_category_category_i
|
||||
create index ix_cepproduct_category_product_id on cepproduct_category (product_id);
|
||||
alter table cepproduct_category add constraint fk_cepproduct_category_product_id foreign key (product_id) references cepproduct (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_ciaddress_street_id on ciaddress (street_id);
|
||||
alter table ciaddress add constraint fk_ciaddress_street_id foreign key (street_id) references cistreet_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_cicustomer_parent_address_id on cicustomer_parent (address_id);
|
||||
alter table cicustomer_parent add constraint fk_cicustomer_parent_address_id foreign key (address_id) references ciaddress (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_cinh_ref_ref_id on cinh_ref (ref_id);
|
||||
alter table cinh_ref add constraint fk_cinh_ref_ref_id foreign key (ref_id) references cinh_root (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4160,6 +4316,8 @@ alter table drot_drol add constraint fk_drot_drol_drol foreign key (drol_id) ref
|
||||
create index ix_dc_detail_master_id on dc_detail (master_id);
|
||||
alter table dc_detail add constraint fk_dc_detail_master_id foreign key (master_id) references dc_master (id) on delete restrict on update restrict;
|
||||
|
||||
alter table defaults_model add constraint fk_defaults_model_id foreign key (id) references defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_dfk_cascade_one_id on dfk_cascade (one_id);
|
||||
alter table dfk_cascade add constraint fk_dfk_cascade_one_id foreign key (one_id) references dfk_cascade_one (id) on delete cascade on update cascade;
|
||||
|
||||
@@ -4540,6 +4698,12 @@ alter table om_basic_child add constraint fk_om_basic_child_parent_id foreign ke
|
||||
create index ix_om_ordered_detail_master_id on om_ordered_detail (master_id);
|
||||
alter table om_ordered_detail add constraint fk_om_ordered_detail_master_id foreign key (master_id) references om_ordered_master (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_oml_baz_foo_id on oml_baz (foo_id);
|
||||
alter table oml_baz add constraint fk_oml_baz_foo_id foreign key (foo_id) references oml_foo (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_oml_foo_bar_id on oml_foo (bar_id);
|
||||
alter table oml_foo add constraint fk_oml_foo_bar_id foreign key (bar_id) references oml_bar (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_o_order_kcustomer_id on o_order (kcustomer_id);
|
||||
alter table o_order add constraint fk_o_order_kcustomer_id foreign key (kcustomer_id) references o_customer (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4552,9 +4716,18 @@ alter table o_order_detail add constraint fk_o_order_detail_product_id foreign k
|
||||
create index ix_s_order_items_order_uuid on s_order_items (order_uuid);
|
||||
alter table s_order_items add constraint fk_s_order_items_order_uuid foreign key (order_uuid) references s_orders (uuid) on delete restrict on update restrict;
|
||||
|
||||
create index ix_order_referenced_parent_master_id on order_referenced_parent (master_id);
|
||||
alter table order_referenced_parent add constraint fk_order_referenced_parent_master_id foreign key (master_id) references order_master (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_or_order_ship_order_id on or_order_ship (order_id);
|
||||
alter table or_order_ship add constraint fk_or_order_ship_order_id foreign key (order_id) references o_order (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_order_toy_child_id on order_toy (child_id);
|
||||
alter table order_toy add constraint fk_order_toy_child_id foreign key (child_id) references order_referenced_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_ordered_parent_order_master_inheritance_id on ordered_parent (order_master_inheritance_id);
|
||||
alter table ordered_parent add constraint fk_ordered_parent_order_master_inheritance_id foreign key (order_master_inheritance_id) references order_master_inheritance (id) on delete restrict on update restrict;
|
||||
|
||||
alter table organization_node add constraint fk_organization_node_parent_tree_node_id foreign key (parent_tree_node_id) references organization_tree_node (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_orp_detail_master_id on orp_detail (master_id);
|
||||
@@ -4656,6 +4829,14 @@ alter table question add constraint fk_question_groupobjectid foreign key (group
|
||||
create index ix_r_orders_customer on r_orders (company,customername);
|
||||
alter table r_orders add constraint fk_r_orders_customer foreign key (company,customername) references rcustomer (company,name) on delete restrict on update restrict;
|
||||
|
||||
alter table referenced_defaults_model add constraint fk_referenced_defaults_model_id foreign key (id) references referenced_defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_referenced_defaults_model_defaults_model_id on referenced_defaults_model (defaults_model_id);
|
||||
alter table referenced_defaults_model add constraint fk_referenced_defaults_model_defaults_model_id foreign key (defaults_model_id) references defaults_model (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_referenced_defaults_model_draft_defaults_model_id on referenced_defaults_model_draft (defaults_model_id);
|
||||
alter table referenced_defaults_model_draft add constraint fk_referenced_defaults_model_draft_defaults_model_id foreign key (defaults_model_id) references defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_rel_master_detail_id on rel_master (detail_id);
|
||||
alter table rel_master add constraint fk_rel_master_detail_id foreign key (detail_id) references rel_detail (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4777,6 +4958,12 @@ alter table vehicle_driver add constraint fk_vehicle_driver_vehicle_id foreign k
|
||||
create index ix_vehicle_driver_address_id on vehicle_driver (address_id);
|
||||
alter table vehicle_driver add constraint fk_vehicle_driver_address_id foreign key (address_id) references o_address (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_version_child_parent_id on version_child (parent_id);
|
||||
alter table version_child add constraint fk_version_child_parent_id foreign key (parent_id) references version_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_version_toy_child_id on version_toy (child_id);
|
||||
alter table version_toy add constraint fk_version_toy_child_id foreign key (child_id) references version_child (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_warehouses_officezoneid on warehouses (officezoneid);
|
||||
alter table warehouses add constraint fk_warehouses_officezoneid foreign key (officezoneid) references zones (id) on delete restrict on update restrict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:05:12.077911Z
|
||||
-- Generated by ebean unknown at 2020-08-24T21:11:54.586122Z
|
||||
alter table bar drop constraint if exists fk_bar_foo_id;
|
||||
drop index if exists ix_bar_foo_id;
|
||||
|
||||
@@ -64,6 +64,12 @@ drop index if exists ix_cepproduct_category_category_id;
|
||||
alter table cepproduct_category drop constraint if exists fk_cepproduct_category_product_id;
|
||||
drop index if exists ix_cepproduct_category_product_id;
|
||||
|
||||
alter table ciaddress drop constraint if exists fk_ciaddress_street_id;
|
||||
drop index if exists ix_ciaddress_street_id;
|
||||
|
||||
alter table cicustomer_parent drop constraint if exists fk_cicustomer_parent_address_id;
|
||||
drop index if exists ix_cicustomer_parent_address_id;
|
||||
|
||||
alter table cinh_ref drop constraint if exists fk_cinh_ref_ref_id;
|
||||
drop index if exists ix_cinh_ref_ref_id;
|
||||
|
||||
@@ -171,6 +177,8 @@ drop index if exists ix_drot_drol_drol;
|
||||
alter table dc_detail drop constraint if exists fk_dc_detail_master_id;
|
||||
drop index if exists ix_dc_detail_master_id;
|
||||
|
||||
alter table defaults_model drop constraint if exists fk_defaults_model_id;
|
||||
|
||||
alter table dfk_cascade drop constraint if exists fk_dfk_cascade_one_id;
|
||||
drop index if exists ix_dfk_cascade_one_id;
|
||||
|
||||
@@ -551,6 +559,12 @@ drop index if exists ix_om_basic_child_parent_id;
|
||||
alter table om_ordered_detail drop constraint if exists fk_om_ordered_detail_master_id;
|
||||
drop index if exists ix_om_ordered_detail_master_id;
|
||||
|
||||
alter table oml_baz drop constraint if exists fk_oml_baz_foo_id;
|
||||
drop index if exists ix_oml_baz_foo_id;
|
||||
|
||||
alter table oml_foo drop constraint if exists fk_oml_foo_bar_id;
|
||||
drop index if exists ix_oml_foo_bar_id;
|
||||
|
||||
alter table o_order drop constraint if exists fk_o_order_kcustomer_id;
|
||||
drop index if exists ix_o_order_kcustomer_id;
|
||||
|
||||
@@ -563,9 +577,18 @@ drop index if exists ix_o_order_detail_product_id;
|
||||
alter table s_order_items drop constraint if exists fk_s_order_items_order_uuid;
|
||||
drop index if exists ix_s_order_items_order_uuid;
|
||||
|
||||
alter table order_referenced_parent drop constraint if exists fk_order_referenced_parent_master_id;
|
||||
drop index if exists ix_order_referenced_parent_master_id;
|
||||
|
||||
alter table or_order_ship drop constraint if exists fk_or_order_ship_order_id;
|
||||
drop index if exists ix_or_order_ship_order_id;
|
||||
|
||||
alter table order_toy drop constraint if exists fk_order_toy_child_id;
|
||||
drop index if exists ix_order_toy_child_id;
|
||||
|
||||
alter table ordered_parent drop constraint if exists fk_ordered_parent_order_master_inheritance_id;
|
||||
drop index if exists ix_ordered_parent_order_master_inheritance_id;
|
||||
|
||||
alter table organization_node drop constraint if exists fk_organization_node_parent_tree_node_id;
|
||||
|
||||
alter table orp_detail drop constraint if exists fk_orp_detail_master_id;
|
||||
@@ -667,6 +690,14 @@ drop index if exists ix_question_groupobjectid;
|
||||
alter table r_orders drop constraint if exists fk_r_orders_customer;
|
||||
drop index if exists ix_r_orders_customer;
|
||||
|
||||
alter table referenced_defaults_model drop constraint if exists fk_referenced_defaults_model_id;
|
||||
|
||||
alter table referenced_defaults_model drop constraint if exists fk_referenced_defaults_model_defaults_model_id;
|
||||
drop index if exists ix_referenced_defaults_model_defaults_model_id;
|
||||
|
||||
alter table referenced_defaults_model_draft drop constraint if exists fk_referenced_defaults_model_draft_defaults_model_id;
|
||||
drop index if exists ix_referenced_defaults_model_draft_defaults_model_id;
|
||||
|
||||
alter table rel_master drop constraint if exists fk_rel_master_detail_id;
|
||||
drop index if exists ix_rel_master_detail_id;
|
||||
|
||||
@@ -788,6 +819,12 @@ drop index if exists ix_vehicle_driver_vehicle_id;
|
||||
alter table vehicle_driver drop constraint if exists fk_vehicle_driver_address_id;
|
||||
drop index if exists ix_vehicle_driver_address_id;
|
||||
|
||||
alter table version_child drop constraint if exists fk_version_child_parent_id;
|
||||
drop index if exists ix_version_child_parent_id;
|
||||
|
||||
alter table version_toy drop constraint if exists fk_version_toy_child_id;
|
||||
drop index if exists ix_version_toy_child_id;
|
||||
|
||||
alter table warehouses drop constraint if exists fk_warehouses_officezoneid;
|
||||
drop index if exists ix_warehouses_officezoneid;
|
||||
|
||||
@@ -887,6 +924,12 @@ drop table if exists cepproduct;
|
||||
|
||||
drop table if exists cepproduct_category;
|
||||
|
||||
drop table if exists ciaddress;
|
||||
|
||||
drop table if exists cicustomer_parent;
|
||||
|
||||
drop table if exists cistreet_parent;
|
||||
|
||||
drop table if exists cinh_ref;
|
||||
|
||||
drop table if exists cinh_root;
|
||||
@@ -991,6 +1034,10 @@ drop table if exists dc_detail;
|
||||
|
||||
drop table if exists dc_master;
|
||||
|
||||
drop table if exists defaults_model;
|
||||
|
||||
drop table if exists defaults_model_draft;
|
||||
|
||||
drop table if exists dfk_cascade;
|
||||
|
||||
drop table if exists dfk_cascade_one;
|
||||
@@ -1142,6 +1189,8 @@ drop table if exists eper_addr;
|
||||
|
||||
drop table if exists eperson;
|
||||
|
||||
drop table if exists eperson2;
|
||||
|
||||
drop table if exists e_person_online;
|
||||
|
||||
drop table if exists esimple;
|
||||
@@ -1253,9 +1302,7 @@ drop table if exists foo;
|
||||
drop table if exists gen_key_identity;
|
||||
|
||||
drop table if exists gen_key_sequence;
|
||||
drop sequence if exists SEQ;
|
||||
|
||||
drop table if exists gen_key_table;
|
||||
drop sequence if exists SEQ_NAME;
|
||||
|
||||
drop table if exists grand_parent_person;
|
||||
|
||||
@@ -1548,6 +1595,12 @@ drop table if exists om_ordered_detail;
|
||||
|
||||
drop table if exists om_ordered_master;
|
||||
|
||||
drop table if exists oml_bar;
|
||||
|
||||
drop table if exists oml_baz;
|
||||
|
||||
drop table if exists oml_foo;
|
||||
|
||||
drop table if exists only_id_entity;
|
||||
|
||||
drop table if exists o_order;
|
||||
@@ -1558,8 +1611,18 @@ drop table if exists s_orders;
|
||||
|
||||
drop table if exists s_order_items;
|
||||
|
||||
drop table if exists order_master;
|
||||
|
||||
drop table if exists order_master_inheritance;
|
||||
|
||||
drop table if exists order_referenced_parent;
|
||||
|
||||
drop table if exists or_order_ship;
|
||||
|
||||
drop table if exists order_toy;
|
||||
|
||||
drop table if exists ordered_parent;
|
||||
|
||||
drop table if exists organisation;
|
||||
|
||||
drop table if exists organization_node;
|
||||
@@ -1688,6 +1751,10 @@ drop table if exists rcustomer;
|
||||
|
||||
drop table if exists r_orders;
|
||||
|
||||
drop table if exists referenced_defaults_model;
|
||||
|
||||
drop table if exists referenced_defaults_model_draft;
|
||||
|
||||
drop table if exists referencing_bean;
|
||||
|
||||
drop table if exists region;
|
||||
@@ -1840,6 +1907,12 @@ drop table if exists vehicle_driver;
|
||||
|
||||
drop table if exists vehicle_lease;
|
||||
|
||||
drop table if exists version_child;
|
||||
|
||||
drop table if exists version_parent;
|
||||
|
||||
drop table if exists version_toy;
|
||||
|
||||
drop table if exists warehouses;
|
||||
|
||||
drop table if exists warehousesshippingzones;
|
||||
@@ -1867,4 +1940,8 @@ drop index if exists ix_contact_last_name_first_name;
|
||||
drop index if exists ix_e_basic_name;
|
||||
drop index if exists ix_efile2_no_fk_owner_id;
|
||||
drop index if exists ix_ecsm_values_host_id;
|
||||
drop index if exists ix_order_referenced_parent_type;
|
||||
drop index if exists ix_organization_node_kind;
|
||||
drop index if exists ano_3;
|
||||
drop index if exists ano_1;
|
||||
drop index if exists ano_2;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:18:31.280668Z
|
||||
-- Generated by ebean unknown at 2020-08-24T21:02:32.420817Z
|
||||
create table asimple_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -307,6 +307,28 @@ create table cepproduct_category (
|
||||
priority integer
|
||||
);
|
||||
|
||||
create table ciaddress (
|
||||
id bigint generated by default as identity not null,
|
||||
street_id bigint,
|
||||
constraint pk_ciaddress primary key (id)
|
||||
);
|
||||
|
||||
create table cicustomer_parent (
|
||||
dtype integer not null,
|
||||
id bigint generated by default as identity not null,
|
||||
address_id bigint,
|
||||
notes varchar(255),
|
||||
constraint pk_cicustomer_parent primary key (id)
|
||||
);
|
||||
|
||||
create table cistreet_parent (
|
||||
dtype integer not null,
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
num varchar(255),
|
||||
constraint pk_cistreet_parent primary key (id)
|
||||
);
|
||||
|
||||
create table cinh_ref (
|
||||
id integer generated by default as identity not null,
|
||||
ref_id integer,
|
||||
@@ -641,7 +663,7 @@ create table d_machine_aux_use (
|
||||
name varchar(255),
|
||||
edate date,
|
||||
use_secs bigint not null,
|
||||
fuel decimal(38),
|
||||
fuel decimal(16,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_aux_use primary key (id)
|
||||
);
|
||||
@@ -652,8 +674,8 @@ create table d_machine_stats (
|
||||
edate date,
|
||||
total_kms bigint not null,
|
||||
hours bigint not null,
|
||||
rate decimal(38),
|
||||
cost decimal(38),
|
||||
rate decimal(16,3),
|
||||
cost decimal(16,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_stats primary key (id)
|
||||
);
|
||||
@@ -664,7 +686,7 @@ create table d_machine_use (
|
||||
edate date,
|
||||
distance_kms bigint not null,
|
||||
time_secs bigint not null,
|
||||
fuel decimal(38),
|
||||
fuel decimal(9,3),
|
||||
version bigint not null,
|
||||
constraint pk_d_machine_use primary key (id)
|
||||
);
|
||||
@@ -680,7 +702,7 @@ create table dperson (
|
||||
id bigint generated by default as identity not null,
|
||||
first_name varchar(255),
|
||||
last_name varchar(255),
|
||||
salary decimal(38),
|
||||
salary decimal(16,3),
|
||||
constraint pk_dperson primary key (id)
|
||||
);
|
||||
|
||||
@@ -729,6 +751,16 @@ create table dc_master (
|
||||
constraint pk_dc_master primary key (id)
|
||||
);
|
||||
|
||||
create table defaults_model (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_defaults_model primary key (id)
|
||||
);
|
||||
|
||||
create table defaults_model_draft (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_defaults_model_draft primary key (id)
|
||||
);
|
||||
|
||||
create table dfk_cascade (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -1511,7 +1543,7 @@ create table esoft_del_user_esoft_del_role (
|
||||
create table esome_convert_type (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
money decimal(38),
|
||||
money decimal(16,3),
|
||||
constraint pk_esome_convert_type primary key (id)
|
||||
);
|
||||
|
||||
@@ -1801,13 +1833,7 @@ create table gen_key_sequence (
|
||||
description varchar(255),
|
||||
constraint pk_gen_key_sequence primary key (id)
|
||||
);
|
||||
create sequence SEQ start with 1 increment by 1;
|
||||
|
||||
create table gen_key_table (
|
||||
id bigint generated by default as identity not null,
|
||||
description varchar(255),
|
||||
constraint pk_gen_key_table primary key (id)
|
||||
);
|
||||
create sequence SEQ_NAME increment by 1;
|
||||
|
||||
create table grand_parent_person (
|
||||
identifier integer generated by default as identity not null,
|
||||
@@ -2739,6 +2765,23 @@ create table om_ordered_master (
|
||||
constraint pk_om_ordered_master primary key (id)
|
||||
);
|
||||
|
||||
create table oml_bar (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_oml_bar primary key (id)
|
||||
);
|
||||
|
||||
create table oml_baz (
|
||||
id bigint generated by default as identity not null,
|
||||
foo_id bigint not null,
|
||||
constraint pk_oml_baz primary key (id)
|
||||
);
|
||||
|
||||
create table oml_foo (
|
||||
id bigint generated by default as identity not null,
|
||||
bar_id bigint not null,
|
||||
constraint pk_oml_foo primary key (id)
|
||||
);
|
||||
|
||||
create table only_id_entity (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_only_id_entity primary key (id)
|
||||
@@ -2778,10 +2821,30 @@ create table s_order_items (
|
||||
product_variant_uuid varchar(255),
|
||||
order_uuid varchar(40),
|
||||
quantity integer not null,
|
||||
amount decimal(38),
|
||||
amount decimal(16,3),
|
||||
constraint pk_s_order_items primary key (uuid)
|
||||
);
|
||||
|
||||
create table order_master (
|
||||
id bigint generated by default as identity not null,
|
||||
constraint pk_order_master primary key (id)
|
||||
);
|
||||
|
||||
create table order_master_inheritance (
|
||||
id integer generated by default as identity not null,
|
||||
constraint pk_order_master_inheritance primary key (id)
|
||||
);
|
||||
|
||||
create table order_referenced_parent (
|
||||
type varchar(31) not null,
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
child_name varchar(255),
|
||||
master_id bigint,
|
||||
sort_order integer,
|
||||
constraint pk_order_referenced_parent primary key (id)
|
||||
);
|
||||
|
||||
create table or_order_ship (
|
||||
id integer generated by default as identity not null,
|
||||
order_id integer,
|
||||
@@ -2792,6 +2855,25 @@ create table or_order_ship (
|
||||
constraint pk_or_order_ship primary key (id)
|
||||
);
|
||||
|
||||
create table order_toy (
|
||||
id integer generated by default as identity not null,
|
||||
title varchar(255),
|
||||
child_id bigint,
|
||||
sort_order integer,
|
||||
constraint pk_order_toy primary key (id)
|
||||
);
|
||||
|
||||
create table ordered_parent (
|
||||
dtype varchar(31) not null,
|
||||
id integer generated by default as identity not null,
|
||||
order_master_inheritance_id integer not null,
|
||||
common_name varchar(255),
|
||||
sort_order integer,
|
||||
ordered_aname varchar(255),
|
||||
ordered_bname varchar(255),
|
||||
constraint pk_ordered_parent primary key (id)
|
||||
);
|
||||
|
||||
create table organisation (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -3305,6 +3387,20 @@ create table r_orders (
|
||||
constraint pk_r_orders primary key (company,order_number)
|
||||
);
|
||||
|
||||
create table referenced_defaults_model (
|
||||
id integer generated by default as identity not null,
|
||||
defaults_model_id integer not null,
|
||||
name varchar(255),
|
||||
constraint pk_referenced_defaults_model primary key (id)
|
||||
);
|
||||
|
||||
create table referenced_defaults_model_draft (
|
||||
id integer generated by default as identity not null,
|
||||
defaults_model_id integer not null,
|
||||
name varchar(255),
|
||||
constraint pk_referenced_defaults_model_draft primary key (id)
|
||||
);
|
||||
|
||||
create table referencing_bean (
|
||||
id uuid not null,
|
||||
constraint pk_referencing_bean primary key (id)
|
||||
@@ -3900,13 +3996,38 @@ create table vehicle_lease (
|
||||
active_start date,
|
||||
active_end date,
|
||||
version bigint not null,
|
||||
bond decimal(38),
|
||||
bond decimal(16,3),
|
||||
min_duration integer not null,
|
||||
day_rate decimal(38),
|
||||
day_rate decimal(16,3),
|
||||
max_days integer,
|
||||
constraint pk_vehicle_lease primary key (id)
|
||||
);
|
||||
|
||||
create table version_child (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
parent_id integer,
|
||||
version integer not null,
|
||||
position integer,
|
||||
constraint pk_version_child primary key (id)
|
||||
);
|
||||
|
||||
create table version_parent (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
version integer not null,
|
||||
constraint pk_version_parent primary key (id)
|
||||
);
|
||||
|
||||
create table version_toy (
|
||||
id integer generated by default as identity not null,
|
||||
name varchar(255),
|
||||
child_id integer,
|
||||
version integer not null,
|
||||
position integer,
|
||||
constraint pk_version_toy primary key (id)
|
||||
);
|
||||
|
||||
create table warehouses (
|
||||
id integer generated by default as identity not null,
|
||||
officezoneid integer,
|
||||
@@ -3987,9 +4108,13 @@ create index ix_contact_last_name_first_name on contact (last_name,first_name);
|
||||
create index ix_e_basic_name on e_basic (name);
|
||||
create index ix_efile2_no_fk_owner_id on efile2_no_fk (owner_id);
|
||||
create index ix_ecsm_values_host_id on ecsm_values (host_id);
|
||||
create index ix_order_referenced_parent_type on order_referenced_parent (type);
|
||||
create index ix_organization_node_kind on organization_node (kind);
|
||||
create unique index concurrently ix_t_detail_with_other_namexxxyy_lowername on t_detail_with_other_namexxxyy (lower(name));
|
||||
create index ix_t_detail_with_other_namexxxyy_defn on t_detail_with_other_namexxxyy using hash (lower(name)) where lower(name) like 'r%';
|
||||
create index ano_3 on test_annotation_base_entity (direct);
|
||||
create index ano_1 on test_annotation_base_entity (direct);
|
||||
create index ano_2 on test_annotation_base_entity (direct);
|
||||
create index ix_bar_foo_id on bar (foo_id);
|
||||
alter table bar add constraint fk_bar_foo_id foreign key (foo_id) references foo (foo_id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4055,6 +4180,12 @@ alter table cepproduct_category add constraint fk_cepproduct_category_category_i
|
||||
create index ix_cepproduct_category_product_id on cepproduct_category (product_id);
|
||||
alter table cepproduct_category add constraint fk_cepproduct_category_product_id foreign key (product_id) references cepproduct (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_ciaddress_street_id on ciaddress (street_id);
|
||||
alter table ciaddress add constraint fk_ciaddress_street_id foreign key (street_id) references cistreet_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_cicustomer_parent_address_id on cicustomer_parent (address_id);
|
||||
alter table cicustomer_parent add constraint fk_cicustomer_parent_address_id foreign key (address_id) references ciaddress (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_cinh_ref_ref_id on cinh_ref (ref_id);
|
||||
alter table cinh_ref add constraint fk_cinh_ref_ref_id foreign key (ref_id) references cinh_root (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4162,6 +4293,8 @@ alter table drot_drol add constraint fk_drot_drol_drol foreign key (drol_id) ref
|
||||
create index ix_dc_detail_master_id on dc_detail (master_id);
|
||||
alter table dc_detail add constraint fk_dc_detail_master_id foreign key (master_id) references dc_master (id) on delete restrict on update restrict;
|
||||
|
||||
alter table defaults_model add constraint fk_defaults_model_id foreign key (id) references defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_dfk_cascade_one_id on dfk_cascade (one_id);
|
||||
alter table dfk_cascade add constraint fk_dfk_cascade_one_id foreign key (one_id) references dfk_cascade_one (id) on delete cascade on update cascade;
|
||||
|
||||
@@ -4542,6 +4675,12 @@ alter table om_basic_child add constraint fk_om_basic_child_parent_id foreign ke
|
||||
create index ix_om_ordered_detail_master_id on om_ordered_detail (master_id);
|
||||
alter table om_ordered_detail add constraint fk_om_ordered_detail_master_id foreign key (master_id) references om_ordered_master (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_oml_baz_foo_id on oml_baz (foo_id);
|
||||
alter table oml_baz add constraint fk_oml_baz_foo_id foreign key (foo_id) references oml_foo (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_oml_foo_bar_id on oml_foo (bar_id);
|
||||
alter table oml_foo add constraint fk_oml_foo_bar_id foreign key (bar_id) references oml_bar (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_o_order_kcustomer_id on o_order (kcustomer_id);
|
||||
alter table o_order add constraint fk_o_order_kcustomer_id foreign key (kcustomer_id) references o_customer (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4554,9 +4693,18 @@ alter table o_order_detail add constraint fk_o_order_detail_product_id foreign k
|
||||
create index ix_s_order_items_order_uuid on s_order_items (order_uuid);
|
||||
alter table s_order_items add constraint fk_s_order_items_order_uuid foreign key (order_uuid) references s_orders (uuid) on delete restrict on update restrict;
|
||||
|
||||
create index ix_order_referenced_parent_master_id on order_referenced_parent (master_id);
|
||||
alter table order_referenced_parent add constraint fk_order_referenced_parent_master_id foreign key (master_id) references order_master (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_or_order_ship_order_id on or_order_ship (order_id);
|
||||
alter table or_order_ship add constraint fk_or_order_ship_order_id foreign key (order_id) references o_order (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_order_toy_child_id on order_toy (child_id);
|
||||
alter table order_toy add constraint fk_order_toy_child_id foreign key (child_id) references order_referenced_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_ordered_parent_order_master_inheritance_id on ordered_parent (order_master_inheritance_id);
|
||||
alter table ordered_parent add constraint fk_ordered_parent_order_master_inheritance_id foreign key (order_master_inheritance_id) references order_master_inheritance (id) on delete restrict on update restrict;
|
||||
|
||||
alter table organization_node add constraint fk_organization_node_parent_tree_node_id foreign key (parent_tree_node_id) references organization_tree_node (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_orp_detail_master_id on orp_detail (master_id);
|
||||
@@ -4658,6 +4806,14 @@ alter table question add constraint fk_question_groupobjectid foreign key (group
|
||||
create index ix_r_orders_customer on r_orders (company,customername);
|
||||
alter table r_orders add constraint fk_r_orders_customer foreign key (company,customername) references rcustomer (company,name) on delete restrict on update restrict;
|
||||
|
||||
alter table referenced_defaults_model add constraint fk_referenced_defaults_model_id foreign key (id) references referenced_defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_referenced_defaults_model_defaults_model_id on referenced_defaults_model (defaults_model_id);
|
||||
alter table referenced_defaults_model add constraint fk_referenced_defaults_model_defaults_model_id foreign key (defaults_model_id) references defaults_model (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_referenced_defaults_model_draft_defaults_model_id on referenced_defaults_model_draft (defaults_model_id);
|
||||
alter table referenced_defaults_model_draft add constraint fk_referenced_defaults_model_draft_defaults_model_id foreign key (defaults_model_id) references defaults_model_draft (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_rel_master_detail_id on rel_master (detail_id);
|
||||
alter table rel_master add constraint fk_rel_master_detail_id foreign key (detail_id) references rel_detail (id) on delete restrict on update restrict;
|
||||
|
||||
@@ -4779,6 +4935,12 @@ alter table vehicle_driver add constraint fk_vehicle_driver_vehicle_id foreign k
|
||||
create index ix_vehicle_driver_address_id on vehicle_driver (address_id);
|
||||
alter table vehicle_driver add constraint fk_vehicle_driver_address_id foreign key (address_id) references o_address (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_version_child_parent_id on version_child (parent_id);
|
||||
alter table version_child add constraint fk_version_child_parent_id foreign key (parent_id) references version_parent (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_version_toy_child_id on version_toy (child_id);
|
||||
alter table version_toy add constraint fk_version_toy_child_id foreign key (child_id) references version_child (id) on delete restrict on update restrict;
|
||||
|
||||
create index ix_warehouses_officezoneid on warehouses (officezoneid);
|
||||
alter table warehouses add constraint fk_warehouses_officezoneid foreign key (officezoneid) references zones (id) on delete restrict on update restrict;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:18:31.280668Z
|
||||
-- Generated by ebean unknown at 2020-08-24T21:02:32.420817Z
|
||||
alter table if exists bar drop constraint if exists fk_bar_foo_id;
|
||||
drop index if exists ix_bar_foo_id;
|
||||
|
||||
@@ -64,6 +64,12 @@ drop index if exists ix_cepproduct_category_category_id;
|
||||
alter table if exists cepproduct_category drop constraint if exists fk_cepproduct_category_product_id;
|
||||
drop index if exists ix_cepproduct_category_product_id;
|
||||
|
||||
alter table if exists ciaddress drop constraint if exists fk_ciaddress_street_id;
|
||||
drop index if exists ix_ciaddress_street_id;
|
||||
|
||||
alter table if exists cicustomer_parent drop constraint if exists fk_cicustomer_parent_address_id;
|
||||
drop index if exists ix_cicustomer_parent_address_id;
|
||||
|
||||
alter table if exists cinh_ref drop constraint if exists fk_cinh_ref_ref_id;
|
||||
drop index if exists ix_cinh_ref_ref_id;
|
||||
|
||||
@@ -171,6 +177,8 @@ drop index if exists ix_drot_drol_drol;
|
||||
alter table if exists dc_detail drop constraint if exists fk_dc_detail_master_id;
|
||||
drop index if exists ix_dc_detail_master_id;
|
||||
|
||||
alter table if exists defaults_model drop constraint if exists fk_defaults_model_id;
|
||||
|
||||
alter table if exists dfk_cascade drop constraint if exists fk_dfk_cascade_one_id;
|
||||
drop index if exists ix_dfk_cascade_one_id;
|
||||
|
||||
@@ -551,6 +559,12 @@ drop index if exists ix_om_basic_child_parent_id;
|
||||
alter table if exists om_ordered_detail drop constraint if exists fk_om_ordered_detail_master_id;
|
||||
drop index if exists ix_om_ordered_detail_master_id;
|
||||
|
||||
alter table if exists oml_baz drop constraint if exists fk_oml_baz_foo_id;
|
||||
drop index if exists ix_oml_baz_foo_id;
|
||||
|
||||
alter table if exists oml_foo drop constraint if exists fk_oml_foo_bar_id;
|
||||
drop index if exists ix_oml_foo_bar_id;
|
||||
|
||||
alter table if exists o_order drop constraint if exists fk_o_order_kcustomer_id;
|
||||
drop index if exists ix_o_order_kcustomer_id;
|
||||
|
||||
@@ -563,9 +577,18 @@ drop index if exists ix_o_order_detail_product_id;
|
||||
alter table if exists s_order_items drop constraint if exists fk_s_order_items_order_uuid;
|
||||
drop index if exists ix_s_order_items_order_uuid;
|
||||
|
||||
alter table if exists order_referenced_parent drop constraint if exists fk_order_referenced_parent_master_id;
|
||||
drop index if exists ix_order_referenced_parent_master_id;
|
||||
|
||||
alter table if exists or_order_ship drop constraint if exists fk_or_order_ship_order_id;
|
||||
drop index if exists ix_or_order_ship_order_id;
|
||||
|
||||
alter table if exists order_toy drop constraint if exists fk_order_toy_child_id;
|
||||
drop index if exists ix_order_toy_child_id;
|
||||
|
||||
alter table if exists ordered_parent drop constraint if exists fk_ordered_parent_order_master_inheritance_id;
|
||||
drop index if exists ix_ordered_parent_order_master_inheritance_id;
|
||||
|
||||
alter table if exists organization_node drop constraint if exists fk_organization_node_parent_tree_node_id;
|
||||
|
||||
alter table if exists orp_detail drop constraint if exists fk_orp_detail_master_id;
|
||||
@@ -667,6 +690,14 @@ drop index if exists ix_question_groupobjectid;
|
||||
alter table if exists r_orders drop constraint if exists fk_r_orders_customer;
|
||||
drop index if exists ix_r_orders_customer;
|
||||
|
||||
alter table if exists referenced_defaults_model drop constraint if exists fk_referenced_defaults_model_id;
|
||||
|
||||
alter table if exists referenced_defaults_model drop constraint if exists fk_referenced_defaults_model_defaults_model_id;
|
||||
drop index if exists ix_referenced_defaults_model_defaults_model_id;
|
||||
|
||||
alter table if exists referenced_defaults_model_draft drop constraint if exists fk_referenced_defaults_model_draft_defaults_model_id;
|
||||
drop index if exists ix_referenced_defaults_model_draft_defaults_model_id;
|
||||
|
||||
alter table if exists rel_master drop constraint if exists fk_rel_master_detail_id;
|
||||
drop index if exists ix_rel_master_detail_id;
|
||||
|
||||
@@ -788,6 +819,12 @@ drop index if exists ix_vehicle_driver_vehicle_id;
|
||||
alter table if exists vehicle_driver drop constraint if exists fk_vehicle_driver_address_id;
|
||||
drop index if exists ix_vehicle_driver_address_id;
|
||||
|
||||
alter table if exists version_child drop constraint if exists fk_version_child_parent_id;
|
||||
drop index if exists ix_version_child_parent_id;
|
||||
|
||||
alter table if exists version_toy drop constraint if exists fk_version_toy_child_id;
|
||||
drop index if exists ix_version_toy_child_id;
|
||||
|
||||
alter table if exists warehouses drop constraint if exists fk_warehouses_officezoneid;
|
||||
drop index if exists ix_warehouses_officezoneid;
|
||||
|
||||
@@ -887,6 +924,12 @@ drop table if exists cepproduct cascade;
|
||||
|
||||
drop table if exists cepproduct_category cascade;
|
||||
|
||||
drop table if exists ciaddress cascade;
|
||||
|
||||
drop table if exists cicustomer_parent cascade;
|
||||
|
||||
drop table if exists cistreet_parent cascade;
|
||||
|
||||
drop table if exists cinh_ref cascade;
|
||||
|
||||
drop table if exists cinh_root cascade;
|
||||
@@ -991,6 +1034,10 @@ drop table if exists dc_detail cascade;
|
||||
|
||||
drop table if exists dc_master cascade;
|
||||
|
||||
drop table if exists defaults_model cascade;
|
||||
|
||||
drop table if exists defaults_model_draft cascade;
|
||||
|
||||
drop table if exists dfk_cascade cascade;
|
||||
|
||||
drop table if exists dfk_cascade_one cascade;
|
||||
@@ -1253,9 +1300,7 @@ drop table if exists foo cascade;
|
||||
drop table if exists gen_key_identity cascade;
|
||||
|
||||
drop table if exists gen_key_sequence cascade;
|
||||
drop sequence if exists SEQ;
|
||||
|
||||
drop table if exists gen_key_table cascade;
|
||||
drop sequence if exists SEQ_NAME;
|
||||
|
||||
drop table if exists grand_parent_person cascade;
|
||||
|
||||
@@ -1557,6 +1602,12 @@ drop table if exists om_ordered_detail cascade;
|
||||
|
||||
drop table if exists om_ordered_master cascade;
|
||||
|
||||
drop table if exists oml_bar cascade;
|
||||
|
||||
drop table if exists oml_baz cascade;
|
||||
|
||||
drop table if exists oml_foo cascade;
|
||||
|
||||
drop table if exists only_id_entity cascade;
|
||||
|
||||
drop table if exists o_order cascade;
|
||||
@@ -1567,8 +1618,18 @@ drop table if exists s_orders cascade;
|
||||
|
||||
drop table if exists s_order_items cascade;
|
||||
|
||||
drop table if exists order_master cascade;
|
||||
|
||||
drop table if exists order_master_inheritance cascade;
|
||||
|
||||
drop table if exists order_referenced_parent cascade;
|
||||
|
||||
drop table if exists or_order_ship cascade;
|
||||
|
||||
drop table if exists order_toy cascade;
|
||||
|
||||
drop table if exists ordered_parent cascade;
|
||||
|
||||
drop table if exists organisation cascade;
|
||||
|
||||
drop table if exists organization_node cascade;
|
||||
@@ -1697,6 +1758,10 @@ drop table if exists rcustomer cascade;
|
||||
|
||||
drop table if exists r_orders cascade;
|
||||
|
||||
drop table if exists referenced_defaults_model cascade;
|
||||
|
||||
drop table if exists referenced_defaults_model_draft cascade;
|
||||
|
||||
drop table if exists referencing_bean cascade;
|
||||
|
||||
drop table if exists region cascade;
|
||||
@@ -1850,6 +1915,12 @@ drop table if exists vehicle_driver cascade;
|
||||
|
||||
drop table if exists vehicle_lease cascade;
|
||||
|
||||
drop table if exists version_child cascade;
|
||||
|
||||
drop table if exists version_parent cascade;
|
||||
|
||||
drop table if exists version_toy cascade;
|
||||
|
||||
drop table if exists warehouses cascade;
|
||||
|
||||
drop table if exists warehousesshippingzones cascade;
|
||||
@@ -1877,6 +1948,10 @@ drop index if exists ix_contact_last_name_first_name;
|
||||
drop index if exists ix_e_basic_name;
|
||||
drop index if exists ix_efile2_no_fk_owner_id;
|
||||
drop index if exists ix_ecsm_values_host_id;
|
||||
drop index if exists ix_order_referenced_parent_type;
|
||||
drop index if exists ix_organization_node_kind;
|
||||
drop index concurrently if exists ix_t_detail_with_other_namexxxyy_lowername;
|
||||
drop index if exists ix_t_detail_with_other_namexxxyy_defn;
|
||||
drop index if exists ano_3;
|
||||
drop index if exists ano_1;
|
||||
drop index if exists ano_2;
|
||||
|
||||
@@ -158,10 +158,10 @@ public abstract class BaseTestCase {
|
||||
*/
|
||||
protected String trimSql(String sql, int columns) {
|
||||
for (int i = 0; i <= columns; i++) {
|
||||
sql = StringHelper.replaceString(sql, " c" + i + ",", ",");
|
||||
sql = StringHelper.replace(sql, " c" + i + ",", ",");
|
||||
}
|
||||
for (int i = 0; i <= columns; i++) {
|
||||
sql = StringHelper.replaceString(sql, " c" + i + " ", " ");
|
||||
sql = StringHelper.replace(sql, " c" + i + " ", " ");
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ConditionalTestRunner extends BlockJUnit4ClassRunner {
|
||||
|
||||
}
|
||||
private boolean platformMath(Platform[] platforms) {
|
||||
Platform basePlatform = DB.getDefault().getPluginApi().getDatabasePlatform().getPlatform().base();
|
||||
Platform basePlatform = DB.getDefault().getPlatform().base();
|
||||
for (Platform platform : platforms) {
|
||||
if (platform.equals(basePlatform)) {
|
||||
return true;
|
||||
|
||||
+7
-7
@@ -10,29 +10,29 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PrimaryServerTest extends BaseTestCase {
|
||||
public class DbPrimaryTest extends BaseTestCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsSkipPrimaryServer() {
|
||||
PrimaryServer.setSkip(true);
|
||||
assertTrue(PrimaryServer.isSkip());
|
||||
PrimaryServer.setSkip(false);
|
||||
assertFalse(PrimaryServer.isSkip());
|
||||
DbPrimary.setSkip(true);
|
||||
assertTrue(DbPrimary.isSkip());
|
||||
DbPrimary.setSkip(false);
|
||||
assertFalse(DbPrimary.isSkip());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.H2)
|
||||
public void testGetPrimaryServerName() {
|
||||
|
||||
String primaryServerName = PrimaryServer.getDefaultServerName();
|
||||
String primaryServerName = DbPrimary.getDefaultServerName();
|
||||
assertEquals("h2", primaryServerName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadProperties() {
|
||||
|
||||
Properties properties = PrimaryServer.getProperties();
|
||||
Properties properties = DbPrimary.getProperties();
|
||||
assertTrue(!properties.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,33 @@
|
||||
package io.ebean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import io.ebean.util.StringHelper;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import io.ebean.util.StringHelper;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class StringHelperTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void isNull() {
|
||||
assertTrue(StringHelper.isNull(null));
|
||||
assertTrue(StringHelper.isNull(""));
|
||||
assertTrue(StringHelper.isNull(" "));
|
||||
assertFalse(StringHelper.isNull("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceString() {
|
||||
assertEquals("sJmethJng", StringHelper.replace("somethong", "o","J"));
|
||||
assertEquals("somethong", StringHelper.replace("somethong", "o", null));
|
||||
assertNull(StringHelper.replace(null, "o","J"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSplitNames() {
|
||||
assertThat(StringHelper.splitNames("")).hasSize(0);
|
||||
@@ -22,56 +39,71 @@ public class StringHelperTest {
|
||||
assertThat(StringHelper.splitNames("foo, bar baz")).containsExactly("foo", "bar", "baz");
|
||||
assertThat(StringHelper.splitNames("foo, bar\nbaz")).containsExactly("foo", "bar", "baz");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testReplaceStringMulti() {
|
||||
public void removeNewLines() {
|
||||
String content = "This is\na\rmultiline\r\ntext\n\r";
|
||||
String[] multi = { "\r\n", "\r", "\n" };
|
||||
content = StringHelper.replaceStringMulti(content, multi, "<br/>");
|
||||
assertThat(content).isEqualTo("This is<br/>a<br/>multiline<br/>text<br/><br/>");
|
||||
content = StringHelper.removeNewLines(content);
|
||||
assertThat(content).isEqualTo("This is a multiline text ");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseNameQuotedValue() {
|
||||
String content = "name1='value1' name2='value2'";
|
||||
Map<String, String> map = StringHelper.parseNameQuotedValue(content);
|
||||
assertThat(map).containsEntry("name1", "value1").containsEntry("name2", "value2");
|
||||
|
||||
// now check with double quotes
|
||||
content = "name1=\"value1\" name2=\"value2\"";
|
||||
map = StringHelper.parseNameQuotedValue(content);
|
||||
assertThat(map).containsEntry("name1", "value1").containsEntry("name2", "value2");
|
||||
|
||||
// now check mix
|
||||
content = "name1=\"value'1\" name2='value\"2'";
|
||||
map = StringHelper.parseNameQuotedValue(content);
|
||||
assertThat(map).containsEntry("name1", "value'1").containsEntry("name2", "value\"2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCountOccurances() {
|
||||
String content = "blablabla, bla bla blubb, blubblubb blablub blubblabla ";
|
||||
assertThat(StringHelper.countOccurances(content , "bla")).isEqualTo(8);
|
||||
assertThat(StringHelper.countOccurances(content , "blubb")).isEqualTo(3);
|
||||
assertThat(StringHelper.countOccurances(content , "blah")).isEqualTo(0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap() {
|
||||
String content = "name1=blah; name2 = blubb ;name3\n=foo";
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content , ";", "=");
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content, ";", "=");
|
||||
assertThat(map)
|
||||
.containsEntry("name1", "blah")
|
||||
.containsEntry("name2", " blubb ") // white space is not trimmed
|
||||
.containsEntry("name3", "foo");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDelimitedToArray() {
|
||||
String content = "foo, bar, bla,blubb,,bla, ,bla";
|
||||
String[] arr = StringHelper.delimitedToArray(content, ",", true);
|
||||
assertThat(arr).containsExactly("foo"," bar"," bla","blubb","","bla"," ","bla");
|
||||
arr = StringHelper.delimitedToArray(content, ",", false);
|
||||
assertThat(arr).containsExactly("foo"," bar"," bla","blubb","bla"," ","bla");
|
||||
public void testDelimitedToMap_expect_trimLeading() {
|
||||
String content = ";name1=foo;name2=bar;";
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content, ";", "=");
|
||||
assertThat(map).hasSize(2)
|
||||
.containsEntry("name1", "foo")
|
||||
.containsEntry("name2", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap_when_emptyEntry() {
|
||||
String content = ";name1=foo;=;name2=bar;";
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content, ";", "=");
|
||||
assertThat(map).hasSize(2)
|
||||
.containsEntry("name1", "foo")
|
||||
.containsEntry("name2", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap_when_missingValue() {
|
||||
String content = ";name1=foo;nameX;name2=bar;";
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content, ";", "=");
|
||||
assertThat(map).hasSize(3)
|
||||
.containsEntry("nameX", null)
|
||||
.containsEntry("name1", "foo")
|
||||
.containsEntry("name2", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap_when_missingValueAtEnd() {
|
||||
String content = ";name1=foo;nameX;name2=bar;nameX2";
|
||||
Map<String, String> map = StringHelper.delimitedToMap(content, ";", "=");
|
||||
assertThat(map).hasSize(3)
|
||||
.containsEntry("nameX", null)
|
||||
.containsEntry("name1", "foo")
|
||||
.containsEntry("name2", "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap_when_null() {
|
||||
Map<String, String> map = StringHelper.delimitedToMap(null, ";", "=");
|
||||
assertThat(map).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelimitedToMap_when_empty() {
|
||||
Map<String, String> map = StringHelper.delimitedToMap("", ";", "=");
|
||||
assertThat(map).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import org.tests.compositekeys.db.AuditInfo;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasic;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -19,12 +20,11 @@ import static org.junit.Assert.assertTrue;
|
||||
public class EntityBeanInterceptTest extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testHasDirtyProperty() throws Exception {
|
||||
|
||||
public void testHasDirtyProperty() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<Customer> list = Ebean.find(Customer.class).findList();
|
||||
List<Customer> list = DB.find(Customer.class).findList();
|
||||
|
||||
Set<String> propertyNames = new HashSet<>();
|
||||
propertyNames.add("name");
|
||||
@@ -32,7 +32,7 @@ public class EntityBeanInterceptTest extends BaseTestCase {
|
||||
|
||||
|
||||
Customer customer = list.get(0);
|
||||
EntityBeanIntercept ebi = ((EntityBean) customer)._ebean_getIntercept();
|
||||
EntityBeanIntercept ebi = ebi(customer);
|
||||
|
||||
assertFalse(ebi.hasDirtyProperty(propertyNames));
|
||||
|
||||
@@ -48,7 +48,7 @@ public class EntityBeanInterceptTest extends BaseTestCase {
|
||||
public void isPartial_when_new() {
|
||||
|
||||
EBasic basic = new EBasic();
|
||||
EntityBeanIntercept ebi = ((EntityBean) basic)._ebean_getIntercept();
|
||||
EntityBeanIntercept ebi = ebi(basic);
|
||||
assertThat(ebi.isPartial()).isTrue();
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class EntityBeanInterceptTest extends BaseTestCase {
|
||||
EBasic basic = new EBasic();
|
||||
basic.setId(42);
|
||||
basic.setName("some");
|
||||
EntityBeanIntercept ebi = ((EntityBean) basic)._ebean_getIntercept();
|
||||
EntityBeanIntercept ebi = ebi(basic);
|
||||
assertThat(ebi.isPartial()).isTrue();
|
||||
}
|
||||
|
||||
@@ -72,8 +72,64 @@ public class EntityBeanInterceptTest extends BaseTestCase {
|
||||
basic.setSomeDate(null);
|
||||
basic.setStatus(EBasic.Status.ACTIVE);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) basic)._ebean_getIntercept();
|
||||
EntityBeanIntercept ebi = ebi(basic);
|
||||
assertThat(ebi.isPartial()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isEmbeddedNewOrDirty() {
|
||||
|
||||
AuditInfo auditInfo = new AuditInfo();
|
||||
EntityBeanIntercept ebi = ebi(auditInfo);
|
||||
assertTrue(ebi.isNew());
|
||||
assertTrue(ebi.isEmbeddedNewOrDirty(auditInfo));
|
||||
|
||||
auditInfo.setUpdatedBy("initial");
|
||||
ebi.setLoaded();
|
||||
assertTrue(ebi.isLoaded());
|
||||
assertFalse(ebi.isEmbeddedNewOrDirty(auditInfo));
|
||||
|
||||
auditInfo.setUpdatedBy("nowDirty");
|
||||
assertTrue(ebi.isDirty());
|
||||
assertTrue(ebi.isEmbeddedNewOrDirty(auditInfo));
|
||||
assertFalse(ebi.isEmbeddedNewOrDirty(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setEmbeddedLoaded() {
|
||||
AuditInfo auditInfo = new AuditInfo();
|
||||
EntityBeanIntercept ebi = ebi(auditInfo);
|
||||
assertFalse(ebi.isLoaded());
|
||||
|
||||
ebi.setEmbeddedLoaded(auditInfo);
|
||||
assertTrue(ebi.isLoaded());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void initialisedMany() {
|
||||
Customer customer = new Customer();
|
||||
EntityBeanIntercept ebi = ebi(customer);
|
||||
final int contactsPos = findProperty("contacts", ebi);
|
||||
assertFalse(ebi.isLoadedProperty(contactsPos));
|
||||
|
||||
ebi.initialisedMany(contactsPos);
|
||||
assertTrue(ebi.isLoadedProperty(contactsPos));
|
||||
}
|
||||
|
||||
private int findProperty(String name, EntityBeanIntercept eb) {
|
||||
final String[] names = eb.getOwner()._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("property not found");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private EntityBeanIntercept ebi(Object bean) {
|
||||
return ((EntityBean)bean)._ebean_getIntercept();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,9 +54,7 @@ public class MatchingNamingConventionTest {
|
||||
@Test
|
||||
public void getSequenceName() {
|
||||
MatchingNamingConvention nc = createMatchingNamingConventionAllQuoted();
|
||||
|
||||
final String sequenceName = nc.getSequenceName("[Customer]", null);
|
||||
assertEquals("Customer_seq", sequenceName);
|
||||
assertEquals("Customer_seq", nc.getSequenceName("[Customer]", null));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.MatchingNamingConvention;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
@@ -9,9 +12,45 @@ import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DatabasePlatformTest {
|
||||
public class DatabasePlatformTest extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.H2)
|
||||
public void h2_platform() {
|
||||
final Platform platform = DB.getDefault().getPlatform();
|
||||
assertThat(platform).isSameAs(Platform.H2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.POSTGRES)
|
||||
public void postgres_platform() {
|
||||
final Platform platform = DB.getDefault().getPlatform().base();
|
||||
assertThat(platform).isSameAs(Platform.POSTGRES);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.MYSQL)
|
||||
public void mysql_platform() {
|
||||
final Platform platform = DB.getDefault().getPlatform().base();
|
||||
assertThat(platform).isSameAs(Platform.MYSQL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.MARIADB)
|
||||
public void mariadb_platform() {
|
||||
final Platform platform = DB.getDefault().getPlatform().base();
|
||||
assertThat(platform).isSameAs(Platform.MARIADB);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.SQLSERVER)
|
||||
public void sqlserver_platform() {
|
||||
final Platform platform = DB.getDefault().getPlatform().base();
|
||||
assertThat(platform).isSameAs(Platform.SQLSERVER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertQuotedIdentifiers_when_allQuotedIdentifier_sqlServer() {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class DbIdentityTest {
|
||||
|
||||
@Test
|
||||
public void getSelectLastInsertedId() {
|
||||
|
||||
DbIdentity identity = new DbIdentity();
|
||||
identity.setSelectLastInsertedIdTemplate("lastid for {table}");
|
||||
|
||||
assertEquals("lastid for customer",identity.getSelectLastInsertedId("customer"));
|
||||
assertEquals("lastid for contact",identity.getSelectLastInsertedId("contact"));
|
||||
|
||||
identity.setSelectLastInsertedIdTemplate("A{table}B{table}C");
|
||||
assertEquals("AoneBoneC",identity.getSelectLastInsertedId("one"));
|
||||
|
||||
identity.setSelectLastInsertedIdTemplate("{table}A{table}");
|
||||
assertEquals("oneAone",identity.getSelectLastInsertedId("one"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSelectLastInsertedId_when_null() {
|
||||
|
||||
DbIdentity identity = new DbIdentity();
|
||||
|
||||
assertNull(identity.getSelectLastInsertedId("customer"));
|
||||
assertNull(identity.getSelectLastInsertedId("contact"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSelectLastInsertedId_when_noPlaceHolder() {
|
||||
|
||||
DbIdentity identity = new DbIdentity();
|
||||
identity.setSelectLastInsertedIdTemplate("lastid");
|
||||
|
||||
assertEquals("lastid",identity.getSelectLastInsertedId("customer"));
|
||||
assertEquals("lastid",identity.getSelectLastInsertedId("contact"));
|
||||
}
|
||||
}
|
||||
@@ -30,10 +30,10 @@ import io.ebean.Update;
|
||||
import io.ebean.UpdateQuery;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -96,6 +96,11 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
public void setClock(Clock clock) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableL2Cache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiLogManager log() {
|
||||
return null;
|
||||
@@ -137,6 +142,11 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Platform getPlatform() {
|
||||
return Platform.GENERIC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiServer getPluginApi() {
|
||||
return null;
|
||||
|
||||
+9
-7
@@ -20,12 +20,12 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PlatformDdl_AlterColumnTest {
|
||||
|
||||
private PlatformDdl h2Ddl = PlatformDdlBuilder.create(new H2Platform());
|
||||
private PlatformDdl pgDdl = PlatformDdlBuilder.create(new PostgresPlatform());
|
||||
private PlatformDdl mysqlDdl = PlatformDdlBuilder.create(new MySqlPlatform());
|
||||
private PlatformDdl oraDdl = PlatformDdlBuilder.create(new OraclePlatform());
|
||||
private PlatformDdl sqlServerDdl = PlatformDdlBuilder.create(new SqlServer17Platform());
|
||||
private PlatformDdl hanaDdl = PlatformDdlBuilder.create(new HanaPlatform());
|
||||
private final PlatformDdl h2Ddl = PlatformDdlBuilder.create(new H2Platform());
|
||||
private final PlatformDdl pgDdl = PlatformDdlBuilder.create(new PostgresPlatform());
|
||||
private final PlatformDdl mysqlDdl = PlatformDdlBuilder.create(new MySqlPlatform());
|
||||
private final PlatformDdl oraDdl = PlatformDdlBuilder.create(new OraclePlatform());
|
||||
private final PlatformDdl sqlServerDdl = PlatformDdlBuilder.create(new SqlServer17Platform());
|
||||
private final PlatformDdl hanaDdl = PlatformDdlBuilder.create(new HanaPlatform());
|
||||
|
||||
{
|
||||
ServerConfig serverConfig = Ebean.getDefaultServer().getPluginApi().getServerConfig();
|
||||
@@ -122,7 +122,9 @@ public class PlatformDdl_AlterColumnTest {
|
||||
assertEquals("alter table mytab alter column acol varchar(20)", sql);
|
||||
|
||||
sql = pgDdl.alterColumnType("mytab", "acol", "varchar(20)");
|
||||
assertEquals("alter table mytab alter column acol type varchar(20)", sql);
|
||||
assertEquals("alter table mytab alter column acol type varchar(20) using acol::varchar(20)", sql);
|
||||
sql = pgDdl.alterColumnType("mytab", "acol", "bigint");
|
||||
assertEquals("alter table mytab alter column acol type bigint using acol::bigint", sql);
|
||||
|
||||
sql = oraDdl.alterColumnType("mytab", "acol", "varchar(20)");
|
||||
assertEquals("alter table mytab modify acol varchar2(20)", sql);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.event.AbstractBeanPersistListener;
|
||||
import io.ebean.event.BeanPersistAdapter;
|
||||
import io.ebean.event.BeanPersistListener;
|
||||
@@ -14,9 +14,9 @@ import static org.junit.Assert.*;
|
||||
public class BeanDescriptor_registerTest {
|
||||
|
||||
@Test
|
||||
public void testRegisterDeregister() throws Exception {
|
||||
public void testRegisterDeregister() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
|
||||
config.setName("h2other");
|
||||
config.loadFromProperties();
|
||||
@@ -25,7 +25,7 @@ public class BeanDescriptor_registerTest {
|
||||
config.setDefaultServer(false);
|
||||
config.getClasses().add(EBasic.class);
|
||||
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer)DatabaseFactory.create(config);
|
||||
BeanDescriptor<EBasic> desc = ebeanServer.getBeanDescriptor(EBasic.class);
|
||||
|
||||
persistListenerRegistrationTests(desc);
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
package io.ebeaninternal.server.dto;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DtoMetaBuilderTest {
|
||||
|
||||
@Test
|
||||
public void includeMethod() {
|
||||
Map<String, Method> methods = getIncludedMethodsFor(D0.class);
|
||||
|
||||
assertThat(methods).hasSize(2);
|
||||
assertThat(methods.get("setName")).isNotNull();
|
||||
assertThat(methods.get("setId")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void includeMethod_when_notStrictlySetters() {
|
||||
Map<String, Method> methods = getIncludedMethodsFor(D1.class);
|
||||
|
||||
assertThat(methods).hasSize(3);
|
||||
assertThat(methods.get("setNameThen")).isNotNull();
|
||||
assertThat(methods.get("setIdFor")).isNotNull();
|
||||
assertThat(methods.get("setI")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyType() {
|
||||
Map<String, Method> methods = getIncludedMethodsFor(D0.class);
|
||||
|
||||
assertThat(methods).hasSize(2);
|
||||
assertThat(DtoMetaBuilder.propertyType(methods.get("setName"))).isEqualTo(String.class);
|
||||
assertThat(DtoMetaBuilder.propertyType(methods.get("setId"))).isEqualTo(long.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void propertyName() {
|
||||
|
||||
assertThat(DtoMetaBuilder.propertyName("setName")).isEqualTo("name");
|
||||
assertThat(DtoMetaBuilder.propertyName("setId")).isEqualTo("id");
|
||||
assertThat(DtoMetaBuilder.propertyName("setI")).isEqualTo("i");
|
||||
assertThat(DtoMetaBuilder.propertyName("setfoo")).isEqualTo("foo");
|
||||
}
|
||||
|
||||
|
||||
private Map<String, Method> getIncludedMethodsFor(Class<?> cls) {
|
||||
Map<String,Method> included = new HashMap<>();
|
||||
for (Method method : cls.getMethods()) {
|
||||
if (DtoMetaBuilder.includeMethod(method)) {
|
||||
included.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
return included;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class D0 {
|
||||
private String name;
|
||||
private long id;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setNamePlus(String name, long id) {
|
||||
this.name = name;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static void setFoo(String foo) {
|
||||
}
|
||||
|
||||
protected void setProtected(String foo) {
|
||||
}
|
||||
|
||||
private void setPrivate(String foo) {
|
||||
}
|
||||
|
||||
private void setPackage(String foo) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
static class D1 {
|
||||
|
||||
public void setNameThen(String name) {
|
||||
|
||||
}
|
||||
|
||||
public void setIdFor(long id) {
|
||||
|
||||
}
|
||||
|
||||
public void setI(long val) {
|
||||
|
||||
}
|
||||
|
||||
public void set(long val) {
|
||||
|
||||
}
|
||||
|
||||
public D1 setA(long val) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import io.ebean.FetchConfig;
|
||||
import io.ebean.Query;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequestTestHelper;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -94,13 +95,14 @@ public class DLoadContextTest extends BaseTestCase {
|
||||
@Test
|
||||
public void construct_when_fetch_expect_100_100_batchSize() {
|
||||
|
||||
BeanPropertyAssocMany<?> many = (BeanPropertyAssocMany<?>)getBeanDescriptor(Order.class).getBeanProperty("details");
|
||||
// the fetch is converted to a query join due to the maxRows
|
||||
OrmQueryRequest<Order> queryRequest = queryRequest(query().fetch("details").setMaxRows(100));
|
||||
queryRequest.initTransIfRequired();
|
||||
queryRequest.endTransIfRequired();
|
||||
|
||||
DLoadContext graphContext = (DLoadContext) queryRequest.getGraphContext();
|
||||
DLoadManyContext details = graphContext.getManyContext("details");
|
||||
DLoadManyContext details = graphContext.getManyContext("details", many);
|
||||
|
||||
assertThat(details.firstBatchSize).isEqualTo(100);
|
||||
assertThat(details.secondaryBatchSize).isEqualTo(100);
|
||||
|
||||
@@ -7,10 +7,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class TrimLogSqlTest {
|
||||
|
||||
@Test
|
||||
public void trim() throws Exception {
|
||||
|
||||
public void trim() {
|
||||
assertThat(TrimLogSql.trim("hello")).isEqualTo("hello");
|
||||
assertThat(TrimLogSql.trim("hello\nthere")).isEqualTo("hello\\n there");
|
||||
assertThat(TrimLogSql.trim("a\nb\nc\nd")).isEqualTo("a\\n b\\n c\\n d");
|
||||
assertThat(TrimLogSql.trim("a\n\nb")).isEqualTo("a\\n \\n b");
|
||||
assertThat(TrimLogSql.trim("\n\n\n")).isEqualTo("\\n \\n \\n ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class SqlTreeAliasTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void parseRootAlias_when_rootAliasIsNull() {
|
||||
|
||||
SqlTreeAlias treeAlias = new SqlTreeAlias(null, SpiQuery.TemporalMode.CURRENT);
|
||||
|
||||
assertEquals("A B", treeAlias.parseRootAlias("${}A ${}B"));
|
||||
assertEquals("ABC", treeAlias.parseRootAlias("A${}B${}C"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseRootAlias_when_rootAliasHasValue() {
|
||||
|
||||
SqlTreeAlias treeAlias = new SqlTreeAlias("t0", SpiQuery.TemporalMode.CURRENT);
|
||||
|
||||
assertEquals("t0.A t0.B", treeAlias.parseRootAlias("${}A ${}B"));
|
||||
assertEquals("At0.Bt0.C", treeAlias.parseRootAlias("A${}B${}C"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.server.querydefn;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class OrmUpdatePropertiesTest {
|
||||
|
||||
@Test
|
||||
public void trim() {
|
||||
assertEquals("ship_id", OrmUpdateProperties.trim("${}ship_id"));
|
||||
assertEquals("(ship_id)", OrmUpdateProperties.trim("(${}ship_id)"));
|
||||
}
|
||||
}
|
||||
+11
-4
@@ -15,14 +15,13 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class DefaultPersistenceContextTest {
|
||||
|
||||
Customer customer42;
|
||||
private final Customer customer42;
|
||||
|
||||
Car car1;
|
||||
private final Car car1;
|
||||
|
||||
public DefaultPersistenceContextTest() {
|
||||
customer42 = new Customer();
|
||||
customer42.setId(42);
|
||||
|
||||
car1 = new Car();
|
||||
car1.setId(1);
|
||||
}
|
||||
@@ -167,10 +166,18 @@ public class DefaultPersistenceContextTest {
|
||||
@Test
|
||||
public void forIterate() {
|
||||
final DefaultPersistenceContext pc = pcWith42();
|
||||
final Object origCustomer42 = pc.get(Customer.class, 42);
|
||||
|
||||
// act
|
||||
final PersistenceContext pcIterate = pc.forIterate();
|
||||
assertThat(pc).isNotSameAs(pcIterate);
|
||||
assertThat(pcIterate.size(Customer.class)).isEqualTo(1);
|
||||
|
||||
// assert same instance (bean effectively transferred to iterator persistence context
|
||||
final Object customer42 = pcIterate.get(Customer.class, 42);
|
||||
assertThat(customer42).isSameAs(origCustomer42);
|
||||
final PersistenceContext.WithOption option = pcIterate.getWithOption(Customer.class, 42);
|
||||
assertThat(option.getBean()).isSameAs(origCustomer42);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -217,7 +224,7 @@ public class DefaultPersistenceContextTest {
|
||||
// ACT - obtain new PC forIterateReset
|
||||
PersistenceContext pcReset = pcIterate.forIterateReset();
|
||||
|
||||
// keeps original customer beans as new added beans there
|
||||
// keeps original customer beans as no new added beans there
|
||||
assertThat(pcReset.size(Customer.class)).isEqualTo(100); // customers didn't change
|
||||
// added beans to contacts and products so those where reset
|
||||
assertThat(pcReset.size(Contact.class)).isEqualTo(0);
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.TransactionCallbackAdapter;
|
||||
import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import org.junit.Test;
|
||||
@@ -9,6 +10,8 @@ import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasic;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class JdbcTransactionTest {
|
||||
@@ -66,4 +69,40 @@ public class JdbcTransactionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void postNestedCallback() {
|
||||
// test both pre-commit and post-commit to ensure callbacks don't disappear and new ones can be added
|
||||
AtomicInteger preCommitCallCount = new AtomicInteger();
|
||||
AtomicInteger postCommitCallCount = new AtomicInteger();
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
DB.currentTransaction().register(
|
||||
new TransactionCallbackAdapter() {
|
||||
@Override
|
||||
public void postCommit() {
|
||||
postCommitCallCount.incrementAndGet();
|
||||
DB.currentTransaction().register(
|
||||
new TransactionCallbackAdapter() {
|
||||
@Override
|
||||
public void postCommit() {
|
||||
postCommitCallCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preCommit() {
|
||||
preCommitCallCount.incrementAndGet();
|
||||
}
|
||||
}
|
||||
);
|
||||
EBasic basic = new EBasic("b1");
|
||||
DB.save(basic);
|
||||
transaction.commit(); // transaction will fail if recursive post-commit is failing
|
||||
|
||||
assertThat(preCommitCallCount.get()).isEqualTo(1); // precommit executed once
|
||||
assertThat(postCommitCallCount.get()).isEqualTo(2); // postcommit executed twice
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
package org.tests.embedded;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.embedded.EAddress;
|
||||
import org.tests.model.embedded.EAddressStatus;
|
||||
import org.tests.model.embedded.EPerson;
|
||||
import org.tests.model.embedded.EPerson3;
|
||||
|
||||
public class TestEmbeddedEmpty {
|
||||
|
||||
@Test
|
||||
public void insertEmptyEmbedded() {
|
||||
|
||||
EPerson person = new EPerson();
|
||||
EPerson3 person = new EPerson3();
|
||||
person.setName("with empty embedded");
|
||||
|
||||
// set empty embedded bean
|
||||
person.setAddress(new EAddress());
|
||||
|
||||
Ebean.save(person);
|
||||
DB.save(person);
|
||||
|
||||
// treat all embedded properties as loaded
|
||||
person.getAddress().getCity();
|
||||
@@ -28,7 +26,7 @@ public class TestEmbeddedEmpty {
|
||||
|
||||
EAddressStatus.TWO.doIt();
|
||||
|
||||
Ebean.find(EPerson.class)
|
||||
DB.find(EPerson3.class)
|
||||
.where().eq("address.status", EAddressStatus.TWO)
|
||||
.findList();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user