mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
99
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a80ab94479 | ||
|
|
e6f0ab90dc | ||
|
|
53f4739c8f | ||
|
|
c6e33ba3ac | ||
|
|
0e2528e542 | ||
|
|
6ecc10a35c | ||
|
|
59bd2bb251 | ||
|
|
9fa83cdd5a | ||
|
|
f383f3f759 | ||
|
|
0abcc9e06e | ||
|
|
4a594b32ef | ||
|
|
8b9f760cb2 | ||
|
|
1d1cf76b5e | ||
|
|
194c14b99a | ||
|
|
fa8c6839dd | ||
|
|
f8e4ce6b4c | ||
|
|
cce496016d | ||
|
|
2c4d5dc304 | ||
|
|
1c981130b6 | ||
|
|
c18d1fa288 | ||
|
|
5287d93a58 | ||
|
|
6e6055fb84 | ||
|
|
c2ea8b3d56 | ||
|
|
5885d724c4 | ||
|
|
90d028640d | ||
|
|
b8d92f1846 | ||
|
|
e41d2eed7f | ||
|
|
8c7a84be9c | ||
|
|
63116f25ec | ||
|
|
eac05571c8 | ||
|
|
a6ad043142 | ||
|
|
bcc8040afe | ||
|
|
ee73fd47d5 | ||
|
|
064b3ceaa4 | ||
|
|
54ada6e07b | ||
|
|
14181932ec | ||
|
|
0faa6a8efd | ||
|
|
f94eb9b75e | ||
|
|
817436b00d | ||
|
|
a089a36f9d | ||
|
|
1f1868fdd3 | ||
|
|
8ac49e537d | ||
|
|
1e44b81e87 | ||
|
|
133cf95c6d | ||
|
|
2caf4bcccd | ||
|
|
e8f0e2f4bf | ||
|
|
8bde42fb16 | ||
|
|
2bb1e40c44 | ||
|
|
1ac1e19db0 | ||
|
|
85a0eb0afb | ||
|
|
a6470b48ff | ||
|
|
ebde00a137 | ||
|
|
bb6425a0c1 | ||
|
|
abff32c418 | ||
|
|
75f26b1f62 | ||
|
|
fc4ee15a2a | ||
|
|
6cb21f3e73 | ||
|
|
18663c8983 | ||
|
|
0d9094984a | ||
|
|
bd05f2c2ba | ||
|
|
1cc167341b | ||
|
|
4a313245b5 | ||
|
|
8744435eb6 | ||
|
|
dfdcdcf321 | ||
|
|
e203d4d191 | ||
|
|
d4c345b989 | ||
|
|
85b21a02e8 | ||
|
|
541271efb7 | ||
|
|
4313fb6f58 | ||
|
|
489781f89d | ||
|
|
ee19fd17fa | ||
|
|
a7c6f9835a | ||
|
|
06b1babed9 | ||
|
|
73ea91d4c9 | ||
|
|
14839f0c0f | ||
|
|
db8f4e141d | ||
|
|
09fa406f84 | ||
|
|
50d22ba357 | ||
|
|
c6f9d193be | ||
|
|
5e1aa47c05 | ||
|
|
21dd8cee37 | ||
|
|
ece82996c2 | ||
|
|
fa520c95ea | ||
|
|
a6685141a4 | ||
|
|
78ab0ad923 | ||
|
|
4fb67a4c8c | ||
|
|
dd94e60d16 | ||
|
|
aa70e17657 | ||
|
|
016cd3fb71 | ||
|
|
17f28ba0aa | ||
|
|
ab88a879e9 | ||
|
|
5b85f3c8dd | ||
|
|
16a5100f35 | ||
|
|
86b2c5d5b5 | ||
|
|
e0c3198ee6 | ||
|
|
12bdd847b5 | ||
|
|
9860816ab7 | ||
|
|
e17283726a | ||
|
|
eff61ae5fc |
+9
-6
@@ -1,17 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>ebean api</name>
|
||||
<description>ebean api</description>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
|
||||
<properties>
|
||||
<jackson-core.version>2.10.0</jackson-core.version>
|
||||
<jackson-databind.version>2.10.0</jackson-databind.version>
|
||||
<jackson-core.version>2.11.3</jackson-core.version>
|
||||
<jackson-databind.version>2.11.3</jackson-databind.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -30,7 +32,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -65,7 +67,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>5.1</version>
|
||||
<version>6.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -79,6 +81,7 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson-core.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for JsonNode support -->
|
||||
|
||||
@@ -70,6 +70,13 @@ public final class DB {
|
||||
private DB() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Backdoor for registering a mock implementation of Database as the default database.
|
||||
*/
|
||||
protected static Database mock(String name, Database server, boolean defaultServer) {
|
||||
return context.mock(name, server, defaultServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default database.
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -121,6 +122,16 @@ public interface Database {
|
||||
*/
|
||||
AutoTune getAutoTune();
|
||||
|
||||
/**
|
||||
* Return the associated DataSource for this Database instance.
|
||||
*/
|
||||
DataSource getDataSource();
|
||||
|
||||
/**
|
||||
* Return the associated read only DataSource for this Database instance (can be null).
|
||||
*/
|
||||
DataSource getReadOnlyDataSource();
|
||||
|
||||
/**
|
||||
* Return the name. This is used with {@link DB#byName(String)} to get a
|
||||
* Database that was registered with the DB singleton.
|
||||
|
||||
@@ -9,6 +9,7 @@ import javax.persistence.PersistenceException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Creates Database instances.
|
||||
@@ -30,6 +31,7 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
public class DatabaseFactory {
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock(false);
|
||||
private static SpiContainer container;
|
||||
|
||||
static {
|
||||
@@ -42,44 +44,63 @@ public class DatabaseFactory {
|
||||
* Call this prior to creating any Database instances or alternatively set the
|
||||
* ContainerConfig on the DatabaseConfig when creating the first Database instance.
|
||||
*/
|
||||
public static synchronized void initialiseContainer(ContainerConfig containerConfig) {
|
||||
getContainer(containerConfig);
|
||||
public static void initialiseContainer(ContainerConfig containerConfig) {
|
||||
lock.lock();
|
||||
try {
|
||||
getContainer(containerConfig);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using properties to configure the database.
|
||||
*/
|
||||
public static synchronized Database create(String name) {
|
||||
// construct based on loading properties files
|
||||
return getContainer(null).createServer(name);
|
||||
public static Database create(String name) {
|
||||
lock.lock();
|
||||
try {
|
||||
return getContainer(null).createServer(name);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the DatabaseConfig object to configure the database.
|
||||
*/
|
||||
public static synchronized Database create(DatabaseConfig config) {
|
||||
if (config.getName() == null) {
|
||||
throw new PersistenceException("The name is null (it is required)");
|
||||
public static Database create(DatabaseConfig config) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (config.getName() == null) {
|
||||
throw new PersistenceException("The name is null (it is required)");
|
||||
}
|
||||
Database server = createInternal(config);
|
||||
if (config.isRegister()) {
|
||||
DbPrimary.setSkip(true);
|
||||
DbContext.getInstance().register(server, config.isDefaultServer());
|
||||
}
|
||||
return server;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
Database server = createInternal(config);
|
||||
if (config.isRegister()) {
|
||||
DbPrimary.setSkip(true);
|
||||
DbContext.getInstance().register(server, config.isDefaultServer());
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the DatabaseConfig additionally specifying a classLoader to use as the context class loader.
|
||||
*/
|
||||
public static synchronized Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
|
||||
ClassLoader currentContextLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
public static Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
|
||||
lock.lock();
|
||||
try {
|
||||
return DatabaseFactory.create(config);
|
||||
ClassLoader currentContextLoader = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
try {
|
||||
return DatabaseFactory.create(config);
|
||||
} finally {
|
||||
// set the currentContextLoader back
|
||||
Thread.currentThread().setContextClassLoader(currentContextLoader);
|
||||
}
|
||||
} finally {
|
||||
// set the currentContextLoader back
|
||||
Thread.currentThread().setContextClassLoader(currentContextLoader);
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,8 +110,13 @@ public class DatabaseFactory {
|
||||
* This is typically invoked via JVM shutdown hook and not explicitly called.
|
||||
* </p>
|
||||
*/
|
||||
public static synchronized void shutdown() {
|
||||
container.shutdown();
|
||||
public static void shutdown() {
|
||||
lock.lock();
|
||||
try {
|
||||
container.shutdown();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private static Database createInternal(DatabaseConfig config) {
|
||||
@@ -103,8 +129,7 @@ public class DatabaseFactory {
|
||||
* @param containerConfig the configuration controlling clustering communication
|
||||
*/
|
||||
private static SpiContainer getContainer(ContainerConfig containerConfig) {
|
||||
|
||||
// thread safe in that all calling methods are synchronized
|
||||
// thread safe in that all calling methods hold lock
|
||||
if (container != null) {
|
||||
return container;
|
||||
}
|
||||
@@ -123,7 +148,6 @@ public class DatabaseFactory {
|
||||
* Create the container instance using the configuration.
|
||||
*/
|
||||
protected static SpiContainer createContainer(ContainerConfig containerConfig) {
|
||||
|
||||
Iterator<SpiContainerFactory> factories = ServiceLoader.load(SpiContainerFactory.class).iterator();
|
||||
if (factories.hasNext()) {
|
||||
return factories.next().create(containerConfig);
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Holds Database instances.
|
||||
@@ -22,17 +23,11 @@ final class DbContext {
|
||||
|
||||
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();
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* The 'default' Database.
|
||||
@@ -91,27 +86,28 @@ final class DbContext {
|
||||
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.
|
||||
* Read, create and put of Databases.
|
||||
*/
|
||||
private Database getWithCreate(String name) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
Database server = syncMap.get(name);
|
||||
if (server == null) {
|
||||
// register when creating server this way
|
||||
server = EbeanServerFactory.create(name);
|
||||
server = DatabaseFactory.create(name);
|
||||
register(server, false);
|
||||
}
|
||||
return server;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,12 +119,15 @@ final class DbContext {
|
||||
}
|
||||
|
||||
private void registerWithName(String name, Database server, boolean isDefault) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
concMap.put(name, server);
|
||||
syncMap.put(name, server);
|
||||
if (isDefault) {
|
||||
defaultDatabase = server;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebean;
|
||||
import io.avaje.config.Config;
|
||||
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Provides singleton state for the default database.
|
||||
@@ -11,47 +12,66 @@ import java.util.Properties;
|
||||
*/
|
||||
class DbPrimary {
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock(false);
|
||||
private static String defaultServerName;
|
||||
|
||||
private static boolean skip;
|
||||
|
||||
/**
|
||||
* Set whether to skip automatically creating the primary database.
|
||||
*/
|
||||
static synchronized void setSkip(boolean skip) {
|
||||
DbPrimary.skip = skip;
|
||||
static void setSkip(boolean skip) {
|
||||
lock.lock();
|
||||
try {
|
||||
DbPrimary.skip = skip;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true to skip automatically creating the primary database.
|
||||
*/
|
||||
static synchronized boolean isSkip() {
|
||||
return skip;
|
||||
static boolean isSkip() {
|
||||
lock.lock();
|
||||
try {
|
||||
return skip;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default database name.
|
||||
*/
|
||||
static synchronized String getDefaultServerName() {
|
||||
getProperties();
|
||||
return defaultServerName;
|
||||
static String getDefaultServerName() {
|
||||
lock.lock();
|
||||
try {
|
||||
getProperties();
|
||||
return defaultServerName;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default configuration Properties.
|
||||
*/
|
||||
static synchronized Properties getProperties() {
|
||||
if (defaultServerName == null) {
|
||||
defaultServerName = determineDefaultServerName();
|
||||
static Properties getProperties() {
|
||||
lock.lock();
|
||||
try {
|
||||
if (defaultServerName == null) {
|
||||
defaultServerName = determineDefaultServerName();
|
||||
}
|
||||
return Config.asProperties();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
return Config.asProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine and return the default server name checking system environment variables and then global properties.
|
||||
*/
|
||||
private static String determineDefaultServerName() {
|
||||
|
||||
String defaultServerName = System.getenv("EBEAN_DB");
|
||||
defaultServerName = System.getProperty("db", defaultServerName);
|
||||
defaultServerName = System.getProperty("ebean_db", defaultServerName);
|
||||
|
||||
@@ -39,28 +39,28 @@ public class EbeanServerFactory {
|
||||
* Call this prior to creating any EbeanServer instances or alternatively set the
|
||||
* ContainerConfig on the ServerConfig when creating the first EbeanServer instance.
|
||||
*/
|
||||
public static synchronized void initialiseContainer(ContainerConfig containerConfig) {
|
||||
public static void initialiseContainer(ContainerConfig containerConfig) {
|
||||
DatabaseFactory.initialiseContainer(containerConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using ebean.properties to configure the database.
|
||||
*/
|
||||
public static synchronized EbeanServer create(String name) {
|
||||
public static EbeanServer create(String name) {
|
||||
return (EbeanServer)DatabaseFactory.create(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the ServerConfig object to configure the database.
|
||||
*/
|
||||
public static synchronized EbeanServer create(ServerConfig config) {
|
||||
public static EbeanServer create(ServerConfig config) {
|
||||
return (EbeanServer)DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
|
||||
*/
|
||||
public static synchronized EbeanServer createWithContextClassLoader(ServerConfig config, ClassLoader classLoader) {
|
||||
public static EbeanServer createWithContextClassLoader(ServerConfig config, ClassLoader classLoader) {
|
||||
return (EbeanServer)DatabaseFactory.createWithContextClassLoader(config, classLoader);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class EbeanServerFactory {
|
||||
* This is typically invoked via JVM shutdown hook and not explicitly called.
|
||||
* </p>
|
||||
*/
|
||||
public static synchronized void shutdown() {
|
||||
public static void shutdown() {
|
||||
DatabaseFactory.shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* Loads a entity bean.
|
||||
* <p>
|
||||
@@ -18,4 +20,9 @@ public interface BeanLoader {
|
||||
*/
|
||||
void loadBean(EntityBeanIntercept ebi);
|
||||
|
||||
/**
|
||||
* Obtain a lock on the loader.
|
||||
*/
|
||||
Lock lock();
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* This is the object added to every entity bean using byte code enhancement.
|
||||
@@ -30,6 +32,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
private static final int STATE_REFERENCE = 1;
|
||||
private static final int STATE_LOADED = 2;
|
||||
|
||||
private transient final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private transient NodeUsageCollector nodeUsageCollector;
|
||||
|
||||
private transient PersistenceContext persistenceContext;
|
||||
@@ -803,7 +807,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Load the bean when it is a reference.
|
||||
*/
|
||||
protected void loadBean(int loadProperty) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (beanLoader == null) {
|
||||
final Database database = DB.byName(ebeanServerName);
|
||||
if (database == null) {
|
||||
@@ -811,14 +816,19 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
loadBeanInternal(loadProperty, database.getPluginApi());
|
||||
loadBeanInternal(loadProperty, database.getPluginApi().beanLoader());
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
synchronized (beanLoader) {
|
||||
final Lock lock = beanLoader.lock();
|
||||
try {
|
||||
// Lazy loading using LoadBeanContext which supports batch loading
|
||||
// Synchronise on the beanLoader (a 'node' of the LoadBeanContext 'tree')
|
||||
loadBeanInternal(loadProperty, beanLoader);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,11 +2,16 @@ package io.ebean.bean;
|
||||
|
||||
import io.ebean.Database;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* BeanLoader used when single beans are loaded (which is usually not ideal / N+1).
|
||||
*/
|
||||
public abstract class SingleBeanLoader implements BeanLoader {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
protected final Database database;
|
||||
|
||||
SingleBeanLoader(Database database) {
|
||||
@@ -18,6 +23,12 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
return database.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock lock() {
|
||||
lock.lock();
|
||||
return lock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single bean lazy loaded when bean from L2 cache.
|
||||
*/
|
||||
@@ -45,4 +56,18 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
database.getPluginApi().loadBeanRef(ebi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Single bean lazy loaded when a reference bean.
|
||||
*/
|
||||
public static class Dflt extends SingleBeanLoader {
|
||||
public Dflt(Database database) {
|
||||
super(database);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
database.getPluginApi().loadBean(ebi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.bean.BeanCollectionLoader;
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Base class for List Set and Map implementations of BeanCollection.
|
||||
@@ -15,6 +16,8 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
private static final long serialVersionUID = 3365725236140187588L;
|
||||
|
||||
protected final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
protected boolean readOnly;
|
||||
|
||||
protected boolean disableLazyLoad;
|
||||
|
||||
@@ -115,7 +115,8 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
private void initClear() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (list == null) {
|
||||
if (!disableLazyLoad && modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
@@ -123,11 +124,14 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (list == null) {
|
||||
if (disableLazyLoad) {
|
||||
list = new ArrayList<>();
|
||||
@@ -135,6 +139,8 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,8 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
private void initClear() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (map == null) {
|
||||
if (!disableLazyLoad && modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
@@ -129,11 +130,14 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
map = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (map == null) {
|
||||
if (disableLazyLoad) {
|
||||
map = new LinkedHashMap<>();
|
||||
@@ -141,6 +145,8 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,7 +114,8 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
private void initClear() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (set == null) {
|
||||
if (!disableLazyLoad && modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
@@ -122,11 +123,14 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
set = new LinkedHashSet<>();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void init() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (set == null) {
|
||||
if (disableLazyLoad) {
|
||||
set = new LinkedHashSet<>();
|
||||
@@ -134,6 +138,8 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
lazyLoadCollection(true);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,25 +6,27 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* List that copies itself on first write access. Needed to keep memory footprint low and the ability
|
||||
* to modify lists from cache.
|
||||
*
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements List<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* The underlying List implementation.
|
||||
*/
|
||||
private List<E> list;
|
||||
|
||||
|
||||
|
||||
public CopyOnFirstWriteList(List<E> list) {
|
||||
super();
|
||||
this.list = list;
|
||||
@@ -166,14 +168,17 @@ public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements Li
|
||||
public int lastIndexOf(Object o) {
|
||||
return list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
|
||||
private void checkCopyOnWrite() {
|
||||
if (!copied) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!copied) {
|
||||
list = new ArrayList<>(list);
|
||||
copied = true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,20 +26,6 @@ public class ClassLoadConfig {
|
||||
this.context = new ClassLoaderContext(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the Java.time types are available and should be supported.
|
||||
*/
|
||||
public boolean isJavaTimePresent() {
|
||||
return isPresent("java.time.LocalDate");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Java7 is present.
|
||||
*/
|
||||
public boolean isJava7Present() {
|
||||
return isPresent("java.nio.file.Path");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the Joda types are available and should be supported.
|
||||
*/
|
||||
@@ -69,6 +55,10 @@ public class ClassLoadConfig {
|
||||
return isPresent("com.fasterxml.jackson.annotation.JsonIgnore");
|
||||
}
|
||||
|
||||
public boolean isJacksonCorePresent() {
|
||||
return isPresent("com.fasterxml.jackson.core.JsonParser");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Jackson ObjectMapper is present.
|
||||
*/
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NavigableSet;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Database sequence based IdGenerator.
|
||||
@@ -24,15 +25,9 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
|
||||
protected static final Logger logger = LoggerFactory.getLogger("io.ebean.SEQ");
|
||||
|
||||
/**
|
||||
* Used to synchronise the idList access.
|
||||
*/
|
||||
protected final Object monitor = new Object();
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* Used to synchronise background loading (loadBatchInBackground).
|
||||
*/
|
||||
protected final Object backgroundLoadMonitor = new Object();
|
||||
private final ReentrantLock loadLock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* The actual sequence name.
|
||||
@@ -97,7 +92,8 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
*/
|
||||
@Override
|
||||
public Object nextId(Transaction t) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
int size = idList.size();
|
||||
if (size > 0) {
|
||||
maybeLoadMoreInBackground(size);
|
||||
@@ -105,6 +101,8 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
loadMore(allocationSize);
|
||||
}
|
||||
return idList.pollFirst();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,8 +116,11 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
|
||||
private void loadMore(int requestSize) {
|
||||
List<Long> newIds = getMoreIds(requestSize);
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
idList.addAll(newIds);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,23 +128,26 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
* Load another batch of Id's using a background thread.
|
||||
*/
|
||||
protected void loadInBackground(final int requestSize) {
|
||||
|
||||
// single threaded processing...
|
||||
synchronized (backgroundLoadMonitor) {
|
||||
loadLock.lock();
|
||||
try {
|
||||
if (currentlyBackgroundLoading) {
|
||||
// skip as already background loading
|
||||
logger.debug("... skip background sequence load (another load in progress)");
|
||||
return;
|
||||
}
|
||||
|
||||
currentlyBackgroundLoading = true;
|
||||
|
||||
backgroundExecutor.execute(() -> {
|
||||
loadMore(requestSize);
|
||||
synchronized (backgroundLoadMonitor) {
|
||||
loadLock.lock();
|
||||
try {
|
||||
currentlyBackgroundLoading = false;
|
||||
} finally {
|
||||
loadLock.unlock();
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
loadLock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the shutdown of the JVM Runtime.
|
||||
@@ -22,6 +23,8 @@ public final class ShutdownManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ShutdownManager.class);
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private static final List<Database> databases = new ArrayList<>();
|
||||
|
||||
private static final ShutdownHook shutdownHook = new ShutdownHook();
|
||||
@@ -56,9 +59,11 @@ public final class ShutdownManager {
|
||||
* Return true if the system is in the process of stopping.
|
||||
*/
|
||||
public static boolean isStopping() {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
lock.lock();
|
||||
try {
|
||||
return stopping;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,15 +79,15 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void deregisterShutdownHook() {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException ex) {
|
||||
if (!ex.getMessage().equals("Shutdown in progress")) {
|
||||
throw ex;
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
Runtime.getRuntime().removeShutdownHook(shutdownHook);
|
||||
} catch (IllegalStateException ex) {
|
||||
if (!ex.getMessage().equals("Shutdown in progress")) {
|
||||
throw ex;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,18 +95,18 @@ public final class ShutdownManager {
|
||||
* Register the shutdown hook with the Runtime.
|
||||
*/
|
||||
protected static void registerShutdownHook() {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
try {
|
||||
String value = System.getProperty("ebean.registerShutdownHook");
|
||||
if (value == null || !value.trim().equalsIgnoreCase("false")) {
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
if (!ex.getMessage().equals("Shutdown in progress")) {
|
||||
throw ex;
|
||||
}
|
||||
lock.lock();
|
||||
try {
|
||||
String value = System.getProperty("ebean.registerShutdownHook");
|
||||
if (value == null || !value.trim().equalsIgnoreCase("false")) {
|
||||
Runtime.getRuntime().addShutdownHook(shutdownHook);
|
||||
}
|
||||
} catch (IllegalStateException ex) {
|
||||
if (!ex.getMessage().equals("Shutdown in progress")) {
|
||||
throw ex;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +117,8 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void shutdown() {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (stopping) {
|
||||
// Already run shutdown...
|
||||
return;
|
||||
@@ -157,6 +162,8 @@ public final class ShutdownManager {
|
||||
if ("true".equalsIgnoreCase(System.getProperty("ebean.datasource.deregisterAllDrivers", "false"))) {
|
||||
deregisterAllJdbcDrivers();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,9 +185,11 @@ public final class ShutdownManager {
|
||||
* Register an ebeanServer to be shutdown when the JVM is shutdown.
|
||||
*/
|
||||
public static void registerDatabase(Database server) {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.add(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,9 +200,11 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void unregisterDatabase(Database server) {
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (databases) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.remove(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.bean.BeanLoader;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
@@ -12,7 +12,7 @@ import java.util.List;
|
||||
/**
|
||||
* Extensions to Database API made available to plugins.
|
||||
*/
|
||||
public interface SpiServer extends EbeanServer, BeanLoader {
|
||||
public interface SpiServer extends Database {
|
||||
|
||||
/**
|
||||
* Return the DatabaseConfig.
|
||||
@@ -45,14 +45,9 @@ public interface SpiServer extends EbeanServer, BeanLoader {
|
||||
BeanType<?> getBeanTypeForQueueId(String queueId);
|
||||
|
||||
/**
|
||||
* Return the associated DataSource for this Database instance.
|
||||
* Return a BeanLoader.
|
||||
*/
|
||||
DataSource getDataSource();
|
||||
|
||||
/**
|
||||
* Return the associated read only DataSource for this Database instance (can be null).
|
||||
*/
|
||||
DataSource getReadOnlyDataSource();
|
||||
BeanLoader beanLoader();
|
||||
|
||||
/**
|
||||
* Invoke lazy loading on this single bean (reference bean).
|
||||
|
||||
+18
-5
@@ -1,12 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
<!-- <artifactId>java8-oss</artifactId>-->
|
||||
<!-- <version>2.2</version>-->
|
||||
<!-- </parent>-->
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.5.2</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
<description>ebean automatic query tuning module</description>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
|
||||
<dependencies>
|
||||
@@ -14,7 +26,8 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- needed for java 11+ -->
|
||||
@@ -39,12 +52,12 @@
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<version>2.18</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<!-- other tiles ... -->
|
||||
<tile>io.ebean.tile:enhancement:12.4.2</tile>
|
||||
<tile>io.ebean.tile:enhancement:12.5.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
+11
-4
@@ -14,6 +14,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Implementation of the AutoTuneService which is comprised of profiling and query tuning.
|
||||
@@ -22,6 +23,8 @@ public class DefaultAutoTuneService implements AutoTuneService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultAutoTuneService.class);
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
private final long defaultGarbageCollectionWait;
|
||||
@@ -127,8 +130,8 @@ public class DefaultAutoTuneService implements AutoTuneService {
|
||||
* Collect profiling, check for new/diff to existing tuning and apply changes.
|
||||
*/
|
||||
private void runtimeTuningUpdate() {
|
||||
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
try {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
@@ -150,12 +153,14 @@ public class DefaultAutoTuneService implements AutoTuneService {
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error collecting or applying automatic query tuning", e);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void saveProfilingOnShutdown(boolean reset) {
|
||||
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (isRuntimeTuningUpdates()) {
|
||||
runtimeTuningUpdate();
|
||||
outputAllTuning();
|
||||
@@ -174,6 +179,8 @@ public class DefaultAutoTuneService implements AutoTuneService {
|
||||
logger.info("writing new:{} diff:{} profiling entries for server:{}", event.getNewCount(), event.getDiffCount(), serverName);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -11,12 +11,15 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the collection of object graph usage profiling.
|
||||
*/
|
||||
public class ProfileManager implements ProfilingListener {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final boolean queryTuningAddVersion;
|
||||
|
||||
/**
|
||||
@@ -32,8 +35,6 @@ public class ProfileManager implements ProfilingListener {
|
||||
*/
|
||||
private final Map<String, ProfileOrigin> profileMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
public ProfileManager(AutoTuneConfig config, SpiEbeanServer server) {
|
||||
@@ -101,8 +102,11 @@ public class ProfileManager implements ProfilingListener {
|
||||
}
|
||||
|
||||
private ProfileOrigin getProfileOrigin(ObjectGraphOrigin originQueryPoint) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
return profileMap.computeIfAbsent(originQueryPoint.getKey(), k -> new ProfileOrigin(originQueryPoint, queryTuningAddVersion, profilingBase, profilingRate));
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -12,9 +12,12 @@ import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class ProfileOrigin {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private static final long RESET_COUNT = -1000000000L;
|
||||
|
||||
private final ObjectGraphOrigin origin;
|
||||
@@ -29,8 +32,6 @@ public class ProfileOrigin {
|
||||
|
||||
private final Map<String, ProfileOriginNodeUsage> nodeUsageMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final AtomicLong requestCount = new AtomicLong();
|
||||
|
||||
private final AtomicLong profileCount = new AtomicLong();
|
||||
@@ -74,8 +75,8 @@ public class ProfileOrigin {
|
||||
* Collect profiling information with the option to reset the underlying profiling detail.
|
||||
*/
|
||||
public void profilingCollection(BeanDescriptor<?> rootDesc, AutoTuneCollection req, boolean reset) {
|
||||
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (nodeUsageMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -94,6 +95,8 @@ public class ProfileOrigin {
|
||||
profileCount.set(0);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,8 +158,8 @@ public class ProfileOrigin {
|
||||
}
|
||||
|
||||
private ProfileOriginNodeUsage getNodeStats(String path) {
|
||||
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
// handle null paths as using ConcurrentHashMap
|
||||
path = (path == null) ? "" : path;
|
||||
ProfileOriginNodeUsage nodeStats = nodeUsageMap.get(path);
|
||||
@@ -165,6 +168,8 @@ public class ProfileOrigin {
|
||||
nodeUsageMap.put(path, nodeStats);
|
||||
}
|
||||
return nodeStats;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-7
@@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Collects usages statistics for a given node in the object graph.
|
||||
@@ -20,7 +21,7 @@ public class ProfileOriginNodeUsage {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ProfileOriginNodeUsage.class);
|
||||
|
||||
private final Object monitor = new Object();
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final String path;
|
||||
|
||||
@@ -38,9 +39,8 @@ public class ProfileOriginNodeUsage {
|
||||
}
|
||||
|
||||
protected void buildTunedFetch(PathProperties pathProps, BeanDescriptor<?> rootDesc, boolean addVersionProperty) {
|
||||
|
||||
synchronized (monitor) {
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
BeanDescriptor<?> desc = rootDesc;
|
||||
if (path != null) {
|
||||
ElPropertyValue elGetValue = rootDesc.getElGetValue(path);
|
||||
@@ -95,6 +95,8 @@ public class ProfileOriginNodeUsage {
|
||||
ElPropertyValue assocOne = rootDesc.getElGetValue(path);
|
||||
pathProps.addToPath(SplitName.parent(path), assocOne.getName());
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +104,8 @@ public class ProfileOriginNodeUsage {
|
||||
* Collect usage from a node.
|
||||
*/
|
||||
protected void collectUsageInfo(NodeUsageCollector profile) {
|
||||
|
||||
synchronized (monitor) {
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
Set<String> used = profile.getUsed();
|
||||
|
||||
profileCount++;
|
||||
@@ -115,6 +116,8 @@ public class ProfileOriginNodeUsage {
|
||||
if (profile.isModified()) {
|
||||
modified = true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-13
@@ -1,12 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>ebean bom</name>
|
||||
<description>ebean bill of materials pom</description>
|
||||
<artifactId>ebean-bom</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -38,69 +40,69 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddlgen</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+12
-17
@@ -3,23 +3,24 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean-core</name>
|
||||
<url>http://ebean-orm.github.io/</url>
|
||||
<name>ebean core</name>
|
||||
<description>ebean core module</description>
|
||||
<url>https://ebean.io/</url>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.5.0</tag>
|
||||
<tag>ebean-parent-12.5.2</tag>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jackson-core.version>2.10.0</jackson-core.version>
|
||||
<jackson-databind.version>2.10.0</jackson-databind.version>
|
||||
<jackson-core.version>2.11.3</jackson-core.version>
|
||||
<jackson-databind.version>2.11.3</jackson-databind.version>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
@@ -51,7 +52,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddlgen</artifactId>
|
||||
<version>12.4.1</version>
|
||||
<version>12.5.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- test scope for supporting ebean-ddlgen -->
|
||||
@@ -65,13 +66,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -91,12 +92,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.ebean</groupId>-->
|
||||
<!-- <artifactId>ebean-migration</artifactId>-->
|
||||
<!-- <version>12.1.4</version>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
@@ -131,9 +126,9 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson-core.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for JsonNode support -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
@@ -267,7 +262,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.4.2</version>
|
||||
<version>12.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebeaninternal.server.type.GeoTypeBinder;
|
||||
|
||||
/**
|
||||
* Provider of Geometry type binder support.
|
||||
*/
|
||||
public interface GeoTypeProvider {
|
||||
|
||||
/**
|
||||
* Create a binder for binding geometry types.
|
||||
*/
|
||||
GeoTypeBinder createBinder(DatabaseConfig config);
|
||||
}
|
||||
+6
-5
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the construction of caches.
|
||||
@@ -26,17 +27,14 @@ class DefaultCacheHolder {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentHashMap<String, Set<String>> collectIdCaches = new ConcurrentHashMap<>();
|
||||
|
||||
private final ServerCacheFactory cacheFactory;
|
||||
|
||||
private final ServerCacheOptions beanDefault;
|
||||
private final ServerCacheOptions queryDefault;
|
||||
|
||||
private final CurrentTenantProvider tenantProvider;
|
||||
|
||||
private final QueryCacheEntryValidate queryCacheEntryValidate;
|
||||
|
||||
DefaultCacheHolder(CacheManagerOptions builder) {
|
||||
@@ -87,8 +85,11 @@ class DefaultCacheHolder {
|
||||
private ServerCache createCache(Class<?> beanType, ServerCacheType type, String key, String shortName) {
|
||||
ServerCacheOptions options = getCacheOptions(beanType, type);
|
||||
if (type == ServerCacheType.COLLECTION_IDS) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
collectIdCaches.computeIfAbsent(beanType.getName(), s -> new ConcurrentSkipListSet<>()).add(key);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
return cacheFactory.createCache(new ServerCacheConfig(type, key, shortName, options, tenantProvider, queryCacheEntryValidate));
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the cluster service.
|
||||
@@ -17,6 +18,8 @@ public class ClusterManager implements ServerLookup {
|
||||
|
||||
private static final Logger clusterLogger = LoggerFactory.getLogger("io.ebean.Cluster");
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final ConcurrentHashMap<String, EbeanServer> serverMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
@@ -51,18 +54,24 @@ public class ClusterManager implements ServerLookup {
|
||||
}
|
||||
|
||||
public void registerServer(EbeanServer server) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
serverMap.put(server.getName(), server);
|
||||
if (!started) {
|
||||
startup();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EbeanServer getServer(String name) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
return serverMap.get(name);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@ class DScriptRunner implements ScriptRunner {
|
||||
|
||||
private Connection obtainConnection() {
|
||||
try {
|
||||
return server.getPluginApi().getDataSource().getConnection();
|
||||
return server.getDataSource().getConnection();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Failed to obtain connection to run script", e);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Default Server side implementation of ServerFactory.
|
||||
@@ -34,6 +35,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("io.ebean.internal.DefaultContainer");
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
public DefaultContainer(ContainerConfig containerConfig) {
|
||||
@@ -72,7 +74,8 @@ public class DefaultContainer implements SpiContainer {
|
||||
*/
|
||||
@Override
|
||||
public SpiEbeanServer createServer(DatabaseConfig config) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
applyConfigServices(config);
|
||||
setNamingConvention(config);
|
||||
BootupClasses bootupClasses = getBootupClasses(config);
|
||||
@@ -114,6 +117,8 @@ public class DefaultContainer implements SpiContainer {
|
||||
}
|
||||
DbOffline.reset();
|
||||
return server;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,11 +36,13 @@ import io.ebean.Version;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.BeanLoader;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.bean.PersistenceContext.WithOption;
|
||||
import io.ebean.bean.SingleBeanLoader;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
@@ -142,6 +144,7 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
@@ -157,98 +160,47 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultServer.class);
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final DatabaseConfig config;
|
||||
|
||||
private final String serverName;
|
||||
|
||||
private final DatabasePlatform databasePlatform;
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final QueryPlanManager queryPlanManager;
|
||||
|
||||
private final ExtraMetrics extraMetrics;
|
||||
|
||||
private final DataTimeZone dataTimeZone;
|
||||
|
||||
/**
|
||||
* Clock to use for WhenModified and WhenCreated.
|
||||
*/
|
||||
private final ClockService clockService;
|
||||
|
||||
private final CallOriginFactory callStackFactory;
|
||||
|
||||
/**
|
||||
* Handles the save, delete, updateSql CallableSql.
|
||||
*/
|
||||
private final Persister persister;
|
||||
|
||||
private final OrmQueryEngine queryEngine;
|
||||
|
||||
private final RelationalQueryEngine relationalQueryEngine;
|
||||
private final DtoQueryEngine dtoQueryEngine;
|
||||
|
||||
private final ServerCacheManager serverCacheManager;
|
||||
|
||||
private final DtoBeanManager dtoBeanManager;
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
private final AutoTuneService autoTuneService;
|
||||
|
||||
private final ReadAuditPrepare readAuditPrepare;
|
||||
|
||||
private final ReadAuditLogger readAuditLogger;
|
||||
|
||||
private final CQueryEngine cqueryEngine;
|
||||
|
||||
private final List<Plugin> serverPlugins;
|
||||
|
||||
private final SpiDdlGenerator ddlGenerator;
|
||||
|
||||
private final ScriptRunner scriptRunner;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
|
||||
private final SpiBackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final DefaultBeanLoader beanLoader;
|
||||
|
||||
private final EncryptKeyManager encryptKeyManager;
|
||||
|
||||
private final SpiJsonContext jsonContext;
|
||||
|
||||
private final DocumentStore documentStore;
|
||||
|
||||
private final MetaInfoManager metaInfoManager;
|
||||
|
||||
private final CurrentTenantProvider currentTenantProvider;
|
||||
|
||||
private final SpiLogManager logManager;
|
||||
|
||||
/**
|
||||
* The default PersistenceContextScope used if it is not explicitly set on a query.
|
||||
*/
|
||||
private final PersistenceContextScope defaultPersistenceContextScope;
|
||||
|
||||
/**
|
||||
* Flag set when the server has shutdown.
|
||||
*/
|
||||
private boolean shutdown;
|
||||
|
||||
/**
|
||||
* The default batch size for lazy loading beans or collections.
|
||||
*/
|
||||
private final int lazyLoadBatchSize;
|
||||
|
||||
private final int queryBatchSize;
|
||||
|
||||
private final boolean updateAllPropertiesInBatch;
|
||||
|
||||
private final long slowQueryMicros;
|
||||
|
||||
private final SlowQueryListener slowQueryListener;
|
||||
|
||||
private final boolean disableL2Cache;
|
||||
private boolean shutdown;
|
||||
|
||||
/**
|
||||
* Create the DefaultServer.
|
||||
@@ -452,8 +404,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
shutdownInternal(true, false);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,10 +417,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public void shutdown(boolean shutdownDataSource, boolean deregisterDriver) {
|
||||
synchronized (this) {
|
||||
// Unregister from JVM Shutdown hook
|
||||
lock.lock();
|
||||
try {
|
||||
ShutdownManager.unregisterDatabase(this);
|
||||
shutdownInternal(shutdownDataSource, deregisterDriver);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -575,6 +532,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
beanLoader.loadBean(loadRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanLoader beanLoader() {
|
||||
return new SingleBeanLoader.Dflt(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
beanLoader.loadBean(ebi);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Used to reduce memory consumption of strings used in deployment processing.
|
||||
@@ -12,6 +13,8 @@ public final class InternString {
|
||||
|
||||
private static final HashMap<String, String> map = new HashMap<>();
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* Return the shared instance of this string.
|
||||
*/
|
||||
@@ -19,8 +22,8 @@ public final class InternString {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
//noinspection SynchronizationOnStaticField
|
||||
synchronized (map) {
|
||||
lock.lock();
|
||||
try {
|
||||
String v = map.get(s);
|
||||
if (v != null) {
|
||||
return v;
|
||||
@@ -28,6 +31,8 @@ public final class InternString {
|
||||
map.put(s, s);
|
||||
return s;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,69 +118,41 @@ public class InternalConfiguration {
|
||||
private static final Logger logger = LoggerFactory.getLogger(InternalConfiguration.class);
|
||||
|
||||
private final TableModState tableModState;
|
||||
|
||||
private final boolean online;
|
||||
|
||||
private final DatabaseConfig config;
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
private final DatabasePlatform databasePlatform;
|
||||
|
||||
private final DeployInherit deployInherit;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final DtoBeanManager dtoBeanManager;
|
||||
|
||||
private final ClockService clockService;
|
||||
|
||||
private final DataTimeZone dataTimeZone;
|
||||
|
||||
private final Binder binder;
|
||||
|
||||
private final DeployCreateProperties deployCreateProperties;
|
||||
|
||||
private final DeployUtil deployUtil;
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
private final CQueryEngine cQueryEngine;
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final SpiCacheManager cacheManager;
|
||||
|
||||
private final ServerCachePlugin serverCachePlugin;
|
||||
|
||||
private ServerCacheNotify cacheNotify;
|
||||
|
||||
private boolean localL2Caching;
|
||||
|
||||
private final boolean jacksonCorePresent;
|
||||
private final ExpressionFactory expressionFactory;
|
||||
|
||||
private final SpiBackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final JsonFactory jsonFactory;
|
||||
|
||||
private final DocStoreFactory docStoreFactory;
|
||||
|
||||
/**
|
||||
* List of plugins (that ultimately the DefaultServer configures late in construction).
|
||||
*/
|
||||
private final List<Plugin> plugins = new ArrayList<>();
|
||||
|
||||
private final MultiValueBind multiValueBind;
|
||||
|
||||
private final SpiLogManager logManager;
|
||||
|
||||
private final ExtraMetrics extraMetrics = new ExtraMetrics();
|
||||
private ServerCacheNotify cacheNotify;
|
||||
private boolean localL2Caching;
|
||||
|
||||
InternalConfiguration(boolean online, ClusterManager clusterManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
DatabaseConfig config, BootupClasses bootupClasses) {
|
||||
|
||||
this.online = online;
|
||||
this.config = config;
|
||||
this.jacksonCorePresent = config.getClassLoadConfig().isJacksonCorePresent();
|
||||
this.clockService = new ClockService(config.getClock());
|
||||
this.tableModState = new TableModState();
|
||||
this.logManager = initLogManager();
|
||||
@@ -210,6 +182,10 @@ public class InternalConfiguration {
|
||||
this.cQueryEngine = new CQueryEngine(config, databasePlatform, binder, asOfTableMapping, draftTableMap);
|
||||
}
|
||||
|
||||
public boolean isJacksonCorePresent() {
|
||||
return jacksonCorePresent;
|
||||
}
|
||||
|
||||
private InternalConfigXmlMap initExternalMapping() {
|
||||
final List<XmapEbean> xmEbeans = readExternalMapping();
|
||||
return new InternalConfigXmlMap(xmEbeans, config.getClassLoadConfig().getClassLoader());
|
||||
@@ -307,7 +283,7 @@ public class InternalConfiguration {
|
||||
* Return the ChangeLogListener to use with a default implementation if none defined.
|
||||
*/
|
||||
public ChangeLogListener changeLogListener(ChangeLogListener listener) {
|
||||
return plugin((listener != null) ? listener : new DefaultChangeLogListener());
|
||||
return plugin((listener != null) ? listener : jacksonCorePresent ? new DefaultChangeLogListener() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -315,7 +291,7 @@ public class InternalConfiguration {
|
||||
*/
|
||||
ReadAuditLogger getReadAuditLogger() {
|
||||
ReadAuditLogger found = bootupClasses.getReadAuditLogger();
|
||||
return plugin(found != null ? found : new DefaultReadAuditLogger());
|
||||
return plugin(found != null ? found : jacksonCorePresent? new DefaultReadAuditLogger(): null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,7 +332,7 @@ public class InternalConfiguration {
|
||||
}
|
||||
|
||||
SpiJsonContext createJsonContext(SpiEbeanServer server) {
|
||||
return new DJsonContext(server, jsonFactory, typeManager);
|
||||
return jacksonCorePresent ? new DJsonContext(server, jsonFactory, typeManager) : null;
|
||||
}
|
||||
|
||||
AutoTuneService createAutoTuneService(SpiEbeanServer server) {
|
||||
|
||||
@@ -432,7 +432,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
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.jsonHelp = initJsonHelp();
|
||||
this.draftHelp = new BeanDescriptorDraftHelp<>(this);
|
||||
this.docStoreAdapter = owner.createDocStoreBeanAdapter(this, deploy);
|
||||
this.docStoreQueueId = docStoreAdapter.getQueueId();
|
||||
@@ -469,6 +469,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isJacksonCorePresent() {
|
||||
return owner.isJacksonCorePresent();
|
||||
}
|
||||
|
||||
private BeanDescriptorJsonHelp<T> initJsonHelp() {
|
||||
return isJacksonCorePresent() ? new BeanDescriptorJsonHelp<>(this) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the bean should be treated as a reference bean when it only has its id populated.
|
||||
* To be true it has other scalar properties that are not generated on insert.
|
||||
|
||||
+10
-46
@@ -95,87 +95,47 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
private static final BeanDescComparator beanDescComparator = new BeanDescComparator();
|
||||
|
||||
private final ReadAnnotations readAnnotations;
|
||||
|
||||
private final TransientProperties transientProperties;
|
||||
|
||||
/**
|
||||
* Helper to derive inheritance information.
|
||||
*/
|
||||
private final DeployInherit deplyInherit;
|
||||
|
||||
private final BeanPropertyAccess beanPropertyAccess = new EnhanceBeanPropertyAccess();
|
||||
|
||||
private final DeployUtil deployUtil;
|
||||
|
||||
private final PersistControllerManager persistControllerManager;
|
||||
|
||||
private final PostLoadManager postLoadManager;
|
||||
|
||||
private final PostConstructManager postConstructManager;
|
||||
|
||||
private final BeanFinderManager beanFinderManager;
|
||||
|
||||
private final PersistListenerManager persistListenerManager;
|
||||
|
||||
private final BeanQueryAdapterManager beanQueryAdapterManager;
|
||||
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
private final DeployCreateProperties createProperties;
|
||||
|
||||
private final BeanManagerFactory beanManagerFactory;
|
||||
|
||||
private final DatabaseConfig config;
|
||||
|
||||
private final ChangeLogListener changeLogListener;
|
||||
|
||||
private final ChangeLogRegister changeLogRegister;
|
||||
|
||||
private final ChangeLogPrepare changeLogPrepare;
|
||||
|
||||
private final DocStoreFactory docStoreFactory;
|
||||
|
||||
private final MultiValueBind multiValueBind;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private int entityBeanCount;
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
private final String serverName;
|
||||
|
||||
private final Map<Class<?>, BeanTable> beanTableMap = new HashMap<>();
|
||||
|
||||
private final Map<String, BeanDescriptor<?>> descMap = new HashMap<>();
|
||||
|
||||
private final Map<String, BeanDescriptor<?>> descQueueMap = new HashMap<>();
|
||||
|
||||
private final Map<String, BeanManager<?>> beanManagerMap = new HashMap<>();
|
||||
|
||||
private final Map<String, List<BeanDescriptor<?>>> tableToDescMap = new HashMap<>();
|
||||
|
||||
private final Map<String, List<BeanDescriptor<?>>> tableToViewDescMap = new HashMap<>();
|
||||
|
||||
private List<BeanDescriptor<?>> immutableDescriptorList;
|
||||
|
||||
private final DbIdentity dbIdentity;
|
||||
|
||||
private final DataSource dataSource;
|
||||
|
||||
private final DatabasePlatform databasePlatform;
|
||||
|
||||
private final SpiCacheManager cacheManager;
|
||||
|
||||
private final BackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final EncryptKeyManager encryptKeyManager;
|
||||
|
||||
private final IdBinderFactory idBinderFactory;
|
||||
|
||||
private final BeanLifecycleAdapterFactory beanLifecycleAdapterFactory;
|
||||
|
||||
private final String asOfViewSuffix;
|
||||
private final boolean jacksonCorePresent;
|
||||
private final int queryPlanTTLSeconds;
|
||||
private int entityBeanCount;
|
||||
private List<BeanDescriptor<?>> immutableDescriptorList;
|
||||
|
||||
/**
|
||||
* Map of base tables to 'with history views' used to support 'as of' queries.
|
||||
@@ -187,8 +147,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private final Map<String, String> draftTableMap = new HashMap<>();
|
||||
|
||||
private final int queryPlanTTLSeconds;
|
||||
|
||||
// temporary collections used during startup and then cleared
|
||||
|
||||
private Map<Class<?>, DeployBeanInfo<?>> deployInfoMap = new HashMap<>();
|
||||
@@ -232,6 +190,12 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
this.changeLogPrepare = config.changeLogPrepare(bootupClasses.getChangeLogPrepare());
|
||||
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
|
||||
this.changeLogRegister = config.changeLogRegister(bootupClasses.getChangeLogRegister());
|
||||
this.jacksonCorePresent = config.isJacksonCorePresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJacksonCorePresent() {
|
||||
return jacksonCorePresent;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,4 +71,9 @@ public interface BeanDescriptorMap {
|
||||
* Return the scalarType for the given logical type.
|
||||
*/
|
||||
ScalarType<?> getScalarType(String cast);
|
||||
|
||||
/**
|
||||
* Return true if Jackson core is present on the classpath.
|
||||
*/
|
||||
boolean isJacksonCorePresent();
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
this.inverseJoin = deploy.createInverseTableJoin();
|
||||
this.modifyListenMode = deploy.getModifyListenMode();
|
||||
this.jsonHelp = new BeanPropertyAssocManyJsonHelp(this);
|
||||
this.jsonHelp = descriptor.isJacksonCorePresent() ? new BeanPropertyAssocManyJsonHelp(this) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-6
@@ -26,12 +26,10 @@ class InsertTimestampFactory {
|
||||
map.put(Long.class, longTime);
|
||||
map.put(long.class, longTime);
|
||||
|
||||
if (classLoadConfig.isJavaTimePresent()) {
|
||||
map.put(Instant.class, new GeneratedInsertJavaTime.InstantDT());
|
||||
map.put(LocalDateTime.class, new GeneratedInsertJavaTime.LocalDT());
|
||||
map.put(OffsetDateTime.class, new GeneratedInsertJavaTime.OffsetDT());
|
||||
map.put(ZonedDateTime.class, new GeneratedInsertJavaTime.ZonedDT());
|
||||
}
|
||||
map.put(Instant.class, new GeneratedInsertJavaTime.InstantDT());
|
||||
map.put(LocalDateTime.class, new GeneratedInsertJavaTime.LocalDT());
|
||||
map.put(OffsetDateTime.class, new GeneratedInsertJavaTime.OffsetDT());
|
||||
map.put(ZonedDateTime.class, new GeneratedInsertJavaTime.ZonedDT());
|
||||
if (classLoadConfig.isJodaTimePresent()) {
|
||||
map.put(org.joda.time.LocalDateTime.class, new GeneratedInsertJodaTime.LocalDT());
|
||||
map.put(org.joda.time.DateTime.class, new GeneratedInsertJodaTime.DateTimeDT());
|
||||
|
||||
+5
-6
@@ -26,12 +26,11 @@ class UpdateTimestampFactory {
|
||||
map.put(Long.class, longTime);
|
||||
map.put(long.class, longTime);
|
||||
|
||||
if (classLoadConfig.isJavaTimePresent()) {
|
||||
map.put(Instant.class, new GeneratedUpdateJavaTime.InstantDT());
|
||||
map.put(LocalDateTime.class, new GeneratedUpdateJavaTime.LocalDT());
|
||||
map.put(OffsetDateTime.class, new GeneratedUpdateJavaTime.OffsetDT());
|
||||
map.put(ZonedDateTime.class, new GeneratedUpdateJavaTime.ZonedDT());
|
||||
}
|
||||
map.put(Instant.class, new GeneratedUpdateJavaTime.InstantDT());
|
||||
map.put(LocalDateTime.class, new GeneratedUpdateJavaTime.LocalDT());
|
||||
map.put(OffsetDateTime.class, new GeneratedUpdateJavaTime.OffsetDT());
|
||||
map.put(ZonedDateTime.class, new GeneratedUpdateJavaTime.ZonedDT());
|
||||
|
||||
if (classLoadConfig.isJodaTimePresent()) {
|
||||
map.put(org.joda.time.LocalDateTime.class, new GeneratedUpdateJodaTime.LocalDT());
|
||||
map.put(org.joda.time.DateTime.class, new GeneratedUpdateJodaTime.DateTimeDT());
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -44,6 +45,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
|
||||
|
||||
private AtomicLong nanoToMilliOffset = new AtomicLong(currentUuidTime());
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the uuid epoch.
|
||||
@@ -106,7 +109,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
|
||||
logger.info("Clock skew of {} ms detected", delta / -10000);
|
||||
// The clock was adjusted back about 2 seconds, or we were generating a lot of ids too fast
|
||||
// if so, we try to set the current as last and also increment the clockSeq.
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (clockSeq.compareAndSet(seq, seq + 1)) {
|
||||
timeStamp.set(current);
|
||||
saveState();
|
||||
@@ -114,6 +118,8 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
// If current is in the future (most of the cases) try to set it.
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* A "CachedThreadPool" based on Daemon threads.
|
||||
@@ -16,6 +17,8 @@ public final class DaemonExecutorService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DaemonExecutorService.class);
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final String namePrefix;
|
||||
|
||||
private final int shutdownWaitSeconds;
|
||||
@@ -49,7 +52,8 @@ public final class DaemonExecutorService {
|
||||
* </p>
|
||||
*/
|
||||
public void shutdown() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (service.isShutdown()) {
|
||||
logger.debug("DaemonExecutorService[{}] already shut down", namePrefix);
|
||||
return;
|
||||
@@ -66,6 +70,8 @@ public final class DaemonExecutorService {
|
||||
logger.error("Error during shutdown of DaemonThreadPool[" + namePrefix + "]", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Daemon based ScheduleThreadPool.
|
||||
@@ -16,6 +17,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DaemonScheduleThreadPool.class);
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final String namePrefix;
|
||||
|
||||
private final int shutdownWaitSeconds;
|
||||
@@ -38,7 +41,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (super.isShutdown()) {
|
||||
logger.debug("DaemonScheduleThreadPool {} already shut down", namePrefix);
|
||||
return;
|
||||
@@ -55,6 +59,8 @@ public final class DaemonScheduleThreadPool extends ScheduledThreadPoolExecutor
|
||||
logger.error("Error during shutdown of " + namePrefix, e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,15 @@ import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Base class for Bean and BeanCollection loading (lazy loading and query join loading).
|
||||
*/
|
||||
abstract class DLoadBaseContext {
|
||||
|
||||
protected final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
protected final DLoadContext parent;
|
||||
|
||||
protected final BeanDescriptor<?> desc;
|
||||
|
||||
@@ -17,6 +17,8 @@ import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* ToOne bean load context.
|
||||
@@ -86,11 +88,11 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
|
||||
@Override
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
}
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
@@ -108,6 +110,8 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +120,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
*/
|
||||
static class LoadBuffer implements BeanLoader, LoadBeanBuffer {
|
||||
|
||||
private final ReentrantLock bufferLock = new ReentrantLock(false);
|
||||
private final DLoadBeanContext context;
|
||||
private final int batchSize;
|
||||
private final List<EntityBeanIntercept> list;
|
||||
@@ -127,6 +132,12 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
this.list = new ArrayList<>(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock lock() {
|
||||
bufferLock.lock();
|
||||
return bufferLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
@@ -182,7 +193,7 @@ class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext {
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
// A synchronized (this) is effectively held by EntityBeanIntercept.loadBean()
|
||||
// A lock is effectively held by EntityBeanIntercept.loadBean()
|
||||
if (context.desc.lazyLoadMany(ebi, context)) {
|
||||
// lazy load property was a Many
|
||||
return;
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* ToMany bean load context.
|
||||
@@ -94,11 +95,11 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
|
||||
@Override
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
}
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
@@ -118,6 +119,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
this.bufferList = null;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +130,7 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
*/
|
||||
static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadManyContext context;
|
||||
private final int batchSize;
|
||||
@@ -208,7 +212,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
@Override
|
||||
public void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
boolean useCache = !onlyIds && context.hitCache && context.property.isUseCache();
|
||||
if (useCache) {
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
@@ -231,6 +236,8 @@ class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
|
||||
LoadManyRequest req = new LoadManyRequest(this, onlyIds, useCache);
|
||||
context.parent.getEbeanServer().loadMany(req);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.persist.platform.MultiValueBind;
|
||||
import io.ebeaninternal.server.type.DataBind;
|
||||
import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.GeoTypeBinder;
|
||||
import io.ebeaninternal.server.type.PostgresHelper;
|
||||
import io.ebeaninternal.server.type.RsetDataReader;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
@@ -35,26 +36,18 @@ public class Binder {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Binder.class);
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final int asOfBindCount;
|
||||
|
||||
private final boolean asOfStandardsBased;
|
||||
|
||||
private final DbExpressionHandler dbExpressionHandler;
|
||||
|
||||
private final DataTimeZone dataTimeZone;
|
||||
|
||||
private final MultiValueBind multiValueBind;
|
||||
|
||||
private final boolean enableBindLog;
|
||||
private final GeoTypeBinder geoTypeBinder;
|
||||
|
||||
/**
|
||||
* Set the PreparedStatement with which to bind variables to.
|
||||
*/
|
||||
public Binder(TypeManager typeManager, SpiLogManager logManager, int asOfBindCount, boolean asOfStandardsBased,
|
||||
DbExpressionHandler dbExpressionHandler, DataTimeZone dataTimeZone, MultiValueBind multiValueBind) {
|
||||
|
||||
this.typeManager = typeManager;
|
||||
this.geoTypeBinder = typeManager.getGeoTypeBinder();
|
||||
this.asOfBindCount = asOfBindCount;
|
||||
this.asOfStandardsBased = asOfStandardsBased;
|
||||
this.dbExpressionHandler = dbExpressionHandler;
|
||||
@@ -88,9 +81,7 @@ public class Binder {
|
||||
* Bind the values to the Prepared Statement.
|
||||
*/
|
||||
public void bind(BindValues bindValues, DataBind dataBind, StringBuilder bindBuf) throws SQLException {
|
||||
|
||||
String logPrefix = "";
|
||||
|
||||
ArrayList<BindValues.Value> list = bindValues.values();
|
||||
for (BindValues.Value bindValue : list) {
|
||||
Object val = bindValue.getValue();
|
||||
@@ -124,7 +115,6 @@ public class Binder {
|
||||
* Bind the list of positionedParameters in BindParams.
|
||||
*/
|
||||
private String bind(BindParams bindParams, DataBind dataBind) throws SQLException {
|
||||
|
||||
StringBuilder bindLog = new StringBuilder();
|
||||
bind(bindParams, dataBind, bindLog);
|
||||
return bindLog.toString();
|
||||
@@ -134,7 +124,6 @@ public class Binder {
|
||||
* Bind the list of positionedParameters in BindParams.
|
||||
*/
|
||||
public void bind(BindParams bindParams, DataBind dataBind, StringBuilder bindLog) throws SQLException {
|
||||
|
||||
bind(bindParams.positionedParameters(), dataBind, bindLog);
|
||||
}
|
||||
|
||||
@@ -142,13 +131,10 @@ public class Binder {
|
||||
* Bind the list of parameters..
|
||||
*/
|
||||
private void bind(List<BindParams.Param> list, DataBind dataBind, StringBuilder bindLog) throws SQLException {
|
||||
|
||||
CallableStatement cstmt = null;
|
||||
|
||||
if (dataBind.getPstmt() instanceof CallableStatement) {
|
||||
cstmt = (CallableStatement) dataBind.getPstmt();
|
||||
}
|
||||
|
||||
// the iterator is assumed to be in the correct order
|
||||
Object value = null;
|
||||
try {
|
||||
@@ -211,7 +197,6 @@ public class Binder {
|
||||
* Bind an Object with unknown data type.
|
||||
*/
|
||||
public Object bindObject(DataBind dataBind, Object value) throws SQLException {
|
||||
|
||||
if (value == null) {
|
||||
// null of unknown type
|
||||
bindObject(dataBind, null, Types.OTHER);
|
||||
@@ -233,9 +218,7 @@ public class Binder {
|
||||
// convert to a JDBC native type
|
||||
value = type.toJdbcType(value);
|
||||
}
|
||||
|
||||
int dbType = type.getJdbcType();
|
||||
bindObject(dataBind, value, dbType);
|
||||
bindObject(dataBind, value, type.getJdbcType());
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -261,12 +244,10 @@ public class Binder {
|
||||
* </p>
|
||||
*/
|
||||
private void bindObject(DataBind dataBind, Object data, int dbType) throws SQLException {
|
||||
|
||||
if (data == null) {
|
||||
dataBind.setNull(dbType);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dbType) {
|
||||
case java.sql.Types.LONGVARCHAR:
|
||||
bindLongVarChar(dataBind, data);
|
||||
@@ -293,7 +274,6 @@ public class Binder {
|
||||
* Binds the value to the statement according to the data type.
|
||||
*/
|
||||
private void bindSimpleData(DataBind b, int dataType, Object data) {
|
||||
|
||||
try {
|
||||
switch (dataType) {
|
||||
case java.sql.Types.BOOLEAN:
|
||||
@@ -370,6 +350,15 @@ public class Binder {
|
||||
b.setObject(PostgresHelper.asInet(data.toString()));
|
||||
break;
|
||||
|
||||
case DbPlatformType.POINT:
|
||||
case DbPlatformType.POLYGON:
|
||||
case DbPlatformType.MULTIPOINT:
|
||||
case DbPlatformType.LINESTRING:
|
||||
case DbPlatformType.MULTILINESTRING:
|
||||
case DbPlatformType.MULTIPOLYGON:
|
||||
geoTypeBinder.bind(b, dataType, data);
|
||||
break;
|
||||
|
||||
case java.sql.Types.OTHER:
|
||||
b.setObject(data, dataType);
|
||||
break;
|
||||
@@ -393,7 +382,6 @@ public class Binder {
|
||||
* Bind String data to a LONGVARCHAR column.
|
||||
*/
|
||||
private void bindLongVarChar(DataBind dataBind, Object data) throws SQLException {
|
||||
|
||||
dataBind.setClob((String) data);
|
||||
}
|
||||
|
||||
@@ -401,7 +389,6 @@ public class Binder {
|
||||
* Bind byte[] data to a LONGVARBINARY column.
|
||||
*/
|
||||
private void bindLongVarBinary(DataBind dataBind, Object data) throws SQLException {
|
||||
|
||||
dataBind.setBlob((byte[]) data);
|
||||
}
|
||||
|
||||
@@ -409,7 +396,6 @@ public class Binder {
|
||||
* Bind String data to a CLOB column.
|
||||
*/
|
||||
private void bindClob(DataBind dataBind, Object data) throws SQLException {
|
||||
|
||||
dataBind.setClob((String) data);
|
||||
}
|
||||
|
||||
@@ -417,7 +403,6 @@ public class Binder {
|
||||
* Bind byte[] data to a BLOB column.
|
||||
*/
|
||||
private void bindBlob(DataBind dataBind, Object data) throws SQLException {
|
||||
|
||||
dataBind.setBlob((byte[]) data);
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* An object that represents a SqlSelect statement.
|
||||
@@ -58,6 +59,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
|
||||
private static final CQueryCollectionAddNoop NOOP_ADD = new CQueryCollectionAddNoop();
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
/**
|
||||
* The resultSet rows read.
|
||||
*/
|
||||
@@ -288,7 +291,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
this.cancelled = true;
|
||||
if (pstmt != null) {
|
||||
try {
|
||||
@@ -298,6 +302,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,8 +332,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
}
|
||||
|
||||
ResultSet prepareResultSet(boolean forwardOnlyHint) throws SQLException {
|
||||
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (cancelled || query.isCancelled()) {
|
||||
// cancelled before we started
|
||||
cancelled = true;
|
||||
@@ -370,6 +376,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
|
||||
// executeQuery
|
||||
return pstmt.executeQuery();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,8 +532,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
}
|
||||
|
||||
boolean hasNext() throws SQLException {
|
||||
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (noMoreRows || cancelled) {
|
||||
return false;
|
||||
}
|
||||
@@ -534,6 +542,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfileTran
|
||||
}
|
||||
hasNextCache = readNextBean();
|
||||
return hasNextCache;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,13 @@ import io.ebeaninternal.api.SpiQueryBindCapture;
|
||||
import io.ebeaninternal.api.SpiQueryPlan;
|
||||
import io.ebeaninternal.server.type.bindcapture.BindCapture;
|
||||
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
class CQueryBindCapture implements SpiQueryBindCapture {
|
||||
|
||||
private static final double multiplier = 1.3d;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final CQueryPlanManager manager;
|
||||
private final SpiQueryPlan queryPlan;
|
||||
|
||||
@@ -35,13 +38,16 @@ class CQueryBindCapture implements SpiQueryBindCapture {
|
||||
|
||||
@Override
|
||||
public void setBind(BindCapture bindCapture, long queryTimeMicros, long startNanos) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
this.thresholdMicros = Math.round(queryTimeMicros * multiplier);
|
||||
this.captureCount++;
|
||||
this.bindCapture = bindCapture;
|
||||
this.queryTimeMicros = queryTimeMicros;
|
||||
lastBindCapture = System.currentTimeMillis();
|
||||
manager.notifyBindCapture(this, startNanos);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,29 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.PagedList;
|
||||
import io.ebeaninternal.api.Monitor;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* PagedList implementation based on limit offset types of queries.
|
||||
*
|
||||
* @param <T> the entity bean type
|
||||
*/
|
||||
public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
|
||||
private final transient SpiEbeanServer server;
|
||||
|
||||
private final transient ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final int firstRow;
|
||||
|
||||
private final int maxRows;
|
||||
|
||||
private final Monitor monitor = new Monitor();
|
||||
|
||||
private int foregroundTotalRowCount = -1;
|
||||
|
||||
private Future<Integer> futureRowCount;
|
||||
@@ -49,21 +47,27 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public Future<Integer> getFutureCount() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (futureRowCount == null) {
|
||||
futureRowCount = server.findFutureCount(query, null);
|
||||
}
|
||||
return futureRowCount;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getList() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (list == null) {
|
||||
list = server.findList(query, null);
|
||||
}
|
||||
return list;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +81,6 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public int getTotalPageCount() {
|
||||
|
||||
int rowCount = getTotalCount();
|
||||
if (rowCount == 0) {
|
||||
return 0;
|
||||
@@ -88,7 +91,8 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public int getTotalCount() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (futureRowCount != null) {
|
||||
try {
|
||||
// background query already initiated so get it with a wait
|
||||
@@ -103,6 +107,8 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
// just using foreground thread
|
||||
foregroundTotalRowCount = server.findCount(query, null);
|
||||
return foregroundTotalRowCount;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +129,9 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public String getDisplayXtoYofZ(String to, String of) {
|
||||
|
||||
int first = firstRow + 1;
|
||||
int last = firstRow + getList().size();
|
||||
int total = getTotalCount();
|
||||
|
||||
return first + to + last + of + total;
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@@ -88,6 +89,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private static final FetchConfig FETCH_LAZY = new FetchConfig().lazy();
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final Class<T> beanType;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
@@ -1992,8 +1995,11 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public void setCancelableQuery(CancelableQuery cancelableQuery) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
this.cancelableQuery = cancelableQuery;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2026,18 +2032,24 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
cancelled = true;
|
||||
if (cancelableQuery != null) {
|
||||
cancelableQuery.cancel();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
return cancelled;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-13
@@ -1,12 +1,12 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.api.Monitor;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Default implementation of PersistenceContext.
|
||||
@@ -32,7 +32,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
*/
|
||||
private final HashMap<Class<?>, ClassContext> typeCache = new HashMap<>();
|
||||
|
||||
private final Monitor monitor = new Monitor();
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private int putCount;
|
||||
|
||||
@@ -68,7 +68,8 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
|
||||
public boolean resetLimit() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (putCount < 100) {
|
||||
return false;
|
||||
}
|
||||
@@ -80,6 +81,8 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
// checking after another 100 puts
|
||||
return false;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,17 +91,23 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
*/
|
||||
@Override
|
||||
public void put(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
putCount++;
|
||||
getClassContext(rootType).put(id, bean);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object putIfAbsent(Class<?> rootType, Object id, Object bean) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
putCount++;
|
||||
return getClassContext(rootType).putIfAbsent(id, bean);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,15 +116,21 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
*/
|
||||
@Override
|
||||
public Object get(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
return getClassContext(rootType).get(id);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WithOption getWithOption(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
return getClassContext(rootType).getWithOption(id);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,9 +139,12 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
*/
|
||||
@Override
|
||||
public int size(Class<?> rootType) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
return classMap == null ? 0 : classMap.size();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,45 +153,60 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
typeCache.clear();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> rootType) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null) {
|
||||
classMap.clear();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleted(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null && id != null) {
|
||||
classMap.deleted(id);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(Class<?> rootType, Object id) {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
ClassContext classMap = typeCache.get(rootType);
|
||||
if (classMap != null && id != null) {
|
||||
classMap.remove(id);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
synchronized (monitor) {
|
||||
lock.lock();
|
||||
try {
|
||||
return typeCache.toString();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
|
||||
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
|
||||
@@ -65,6 +66,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
|
||||
private final ExecutorService executor;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
|
||||
private final File dir;
|
||||
|
||||
private final long minMicros;
|
||||
@@ -117,7 +120,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
}
|
||||
|
||||
private void flushCurrentFile() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
@@ -126,6 +130,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
log.error("Failed to flush and close transaction profiling file ", e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +139,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
* Move to the next file to write to.
|
||||
*/
|
||||
private void incrementFile() {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
flushCurrentFile();
|
||||
try {
|
||||
String now = DTF.format(LocalDateTime.now());
|
||||
@@ -142,6 +149,8 @@ public class DefaultProfileHandler implements SpiProfileHandler, Plugin {
|
||||
} catch (IOException e) {
|
||||
log.error("Not expected", e);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import io.ebean.types.Inet;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.api.ExtraTypeFactory;
|
||||
import io.ebeaninternal.api.DbOffline;
|
||||
import io.ebeaninternal.api.GeoTypeProvider;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
@@ -145,8 +146,6 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
private final Object objectMapper;
|
||||
|
||||
private final boolean java7Present;
|
||||
|
||||
private final boolean objectMapperPresent;
|
||||
|
||||
private final boolean postgres;
|
||||
@@ -180,13 +179,12 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
private final PlatformArrayTypeFactory arrayTypeListFactory;
|
||||
private final PlatformArrayTypeFactory arrayTypeSetFactory;
|
||||
private GeoTypeBinder geoTypeBinder;
|
||||
|
||||
/**
|
||||
* Create the DefaultTypeManager.
|
||||
*/
|
||||
public DefaultTypeManager(DatabaseConfig config, BootupClasses bootupClasses) {
|
||||
|
||||
this.java7Present = config.getClassLoadConfig().isJava7Present();
|
||||
this.jsonDateTime = config.getJsonDateTime();
|
||||
this.jsonDate = config.getJsonDate();
|
||||
this.typeMap = new ConcurrentHashMap<>();
|
||||
@@ -211,6 +209,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
initialiseJacksonTypes(config);
|
||||
|
||||
loadTypesFromProviders(config, objectMapper);
|
||||
loadGeoTypeBinder(config);
|
||||
|
||||
if (bootupClasses != null) {
|
||||
initialiseCustomScalarTypes(bootupClasses);
|
||||
@@ -219,6 +218,13 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadGeoTypeBinder(DatabaseConfig config) {
|
||||
final GeoTypeProvider provider = config.service(GeoTypeProvider.class);
|
||||
if (provider != null) {
|
||||
geoTypeBinder = provider.createBinder(config);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the factory to use to support DB ARRAY types.
|
||||
*/
|
||||
@@ -335,19 +341,17 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
private ScalarType<?> checkInterfaceTypes(Class<?> type) {
|
||||
if (java7Present) {
|
||||
return checkJava7InterfaceTypes(type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ScalarType<?> checkJava7InterfaceTypes(Class<?> type) {
|
||||
if (java.nio.file.Path.class.isAssignableFrom(type)) {
|
||||
return typeMap.get(java.nio.file.Path.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeoTypeBinder getGeoTypeBinder() {
|
||||
return geoTypeBinder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType<?> getDbMapScalarType() {
|
||||
return (postgres) ? hstoreType : ScalarTypeJsonMap.typeFor(false, Types.VARCHAR);
|
||||
@@ -882,33 +886,25 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
}
|
||||
|
||||
private void initialiseJavaTimeTypes(DatabaseConfig config) {
|
||||
if (java7Present) {
|
||||
typeMap.put(java.nio.file.Path.class, new ScalarTypePath());
|
||||
}
|
||||
if (config.getClassLoadConfig().isJavaTimePresent()) {
|
||||
logger.debug("Registering java.time data types");
|
||||
addType(java.time.Period.class, new ScalarTypePeriod());
|
||||
addType(java.time.LocalDate.class, new ScalarTypeLocalDate(jsonDate));
|
||||
addType(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(jsonDateTime));
|
||||
addType(OffsetDateTime.class, new ScalarTypeOffsetDateTime(jsonDateTime));
|
||||
addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(jsonDateTime));
|
||||
addType(Instant.class, new ScalarTypeInstant(jsonDateTime));
|
||||
|
||||
addType(DayOfWeek.class, new ScalarTypeDayOfWeek());
|
||||
addType(Month.class, new ScalarTypeMonth());
|
||||
addType(Year.class, new ScalarTypeYear());
|
||||
addType(YearMonth.class, new ScalarTypeYearMonthDate(jsonDate));
|
||||
addType(MonthDay.class, new ScalarTypeMonthDay());
|
||||
addType(OffsetTime.class, new ScalarTypeOffsetTime());
|
||||
addType(ZoneId.class, new ScalarTypeZoneId());
|
||||
addType(ZoneOffset.class, new ScalarTypeZoneOffset());
|
||||
|
||||
boolean localTimeNanos = config.isLocalTimeWithNanos();
|
||||
addType(java.time.LocalTime.class, (localTimeNanos) ? new ScalarTypeLocalTimeWithNanos() : new ScalarTypeLocalTime());
|
||||
|
||||
boolean durationNanos = config.isDurationWithNanos();
|
||||
addType(Duration.class, (durationNanos) ? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
|
||||
}
|
||||
typeMap.put(java.nio.file.Path.class, new ScalarTypePath());
|
||||
addType(java.time.Period.class, new ScalarTypePeriod());
|
||||
addType(java.time.LocalDate.class, new ScalarTypeLocalDate(jsonDate));
|
||||
addType(java.time.LocalDateTime.class, new ScalarTypeLocalDateTime(jsonDateTime));
|
||||
addType(OffsetDateTime.class, new ScalarTypeOffsetDateTime(jsonDateTime));
|
||||
addType(ZonedDateTime.class, new ScalarTypeZonedDateTime(jsonDateTime));
|
||||
addType(Instant.class, new ScalarTypeInstant(jsonDateTime));
|
||||
addType(DayOfWeek.class, new ScalarTypeDayOfWeek());
|
||||
addType(Month.class, new ScalarTypeMonth());
|
||||
addType(Year.class, new ScalarTypeYear());
|
||||
addType(YearMonth.class, new ScalarTypeYearMonthDate(jsonDate));
|
||||
addType(MonthDay.class, new ScalarTypeMonthDay());
|
||||
addType(OffsetTime.class, new ScalarTypeOffsetTime());
|
||||
addType(ZoneId.class, new ScalarTypeZoneId());
|
||||
addType(ZoneOffset.class, new ScalarTypeZoneOffset());
|
||||
boolean localTimeNanos = config.isLocalTimeWithNanos();
|
||||
addType(java.time.LocalTime.class, (localTimeNanos) ? new ScalarTypeLocalTimeWithNanos() : new ScalarTypeLocalTime());
|
||||
boolean durationNanos = config.isDurationWithNanos();
|
||||
addType(Duration.class, (durationNanos) ? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
|
||||
}
|
||||
|
||||
private void addType(Class<?> clazz, ScalarType<?> scalarType) {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Binder for Geometry types.
|
||||
*/
|
||||
public interface GeoTypeBinder {
|
||||
|
||||
/**
|
||||
* Bind the geometry type.
|
||||
*/
|
||||
void bind(DataBind b, int dataType, Object data) throws SQLException;
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.util.Collections.EMPTY_LIST;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final Map<String, ScalarTypeArrayList> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -40,7 +42,8 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
*/
|
||||
@Override
|
||||
public ScalarTypeArrayList typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
@@ -58,6 +61,8 @@ public class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements Sc
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayList(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.util.Collections.EMPTY_LIST;
|
||||
|
||||
@@ -24,6 +25,7 @@ class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final Map<String, ScalarTypeArrayListH2> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -31,7 +33,8 @@ class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
@@ -49,6 +52,8 @@ class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArrayListH2(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.util.Collections.EMPTY_SET;
|
||||
|
||||
@@ -33,6 +34,7 @@ public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements Scal
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final Map<String, ScalarTypeArraySet> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -40,7 +42,8 @@ public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements Scal
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
@@ -58,6 +61,8 @@ public class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements Scal
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySet(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.util.Collections.EMPTY_SET;
|
||||
|
||||
@@ -24,6 +25,7 @@ class ScalarTypeArraySetH2 extends ScalarTypeArraySet {
|
||||
|
||||
static class Factory implements PlatformArrayTypeFactory {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final Map<String, ScalarTypeArraySetH2> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -31,7 +33,8 @@ class ScalarTypeArraySetH2 extends ScalarTypeArraySet {
|
||||
*/
|
||||
@Override
|
||||
public ScalarType<?> typeFor(Type valueType, boolean nullable) {
|
||||
synchronized (this) {
|
||||
lock.lock();
|
||||
try {
|
||||
String key = valueType + ":" + nullable;
|
||||
if (valueType.equals(UUID.class)) {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "uuid", DocPropertyType.UUID, ArrayElementConverter.UUID));
|
||||
@@ -49,6 +52,8 @@ class ScalarTypeArraySetH2 extends ScalarTypeArraySet {
|
||||
return cache.computeIfAbsent(key, s -> new ScalarTypeArraySetH2(nullable, "varchar", DocPropertyType.TEXT, ArrayElementConverter.STRING));
|
||||
}
|
||||
throw new IllegalArgumentException("Type [" + valueType + "] not supported for @DbArray mapping");
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,4 +69,9 @@ public interface TypeManager {
|
||||
* Return the ScalarType used to handle HSTORE (Map<String,String>).
|
||||
*/
|
||||
ScalarType<?> getDbMapScalarType();
|
||||
|
||||
/**
|
||||
* Return the Geometry type binder if provided.
|
||||
*/
|
||||
GeoTypeBinder getGeoTypeBinder();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.config.CurrentTenantProvider;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.TenantCatalogProvider;
|
||||
import io.ebean.config.TenantDataSourceProvider;
|
||||
import io.ebean.config.TenantMode;
|
||||
@@ -29,7 +29,7 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
TenantDataSourceProvider dataSourceProvider = Mockito.mock(TenantDataSourceProvider.class);
|
||||
Mockito.doReturn(mockedDataSource).when(dataSourceProvider).dataSource(tenant);
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("multiTenantDb");
|
||||
config.loadFromProperties();
|
||||
config.setRegister(false);
|
||||
@@ -45,7 +45,8 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
//config.setDdlRun(false);
|
||||
config.setDatabasePlatform(new PostgresPlatform());
|
||||
|
||||
EbeanServerFactory.create(config);
|
||||
final Database database = DatabaseFactory.create(config);
|
||||
database.shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -63,9 +64,10 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
TenantSchemaProvider schemaProvider = Mockito.mock(TenantSchemaProvider.class);
|
||||
Mockito.doReturn("tenant_schema").when(schemaProvider).schema(tenant);
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2");
|
||||
config.loadFromProperties();
|
||||
config.setName("multi-tenancy");
|
||||
config.setRegister(false);
|
||||
config.setDefaultServer(false);
|
||||
|
||||
@@ -76,7 +78,8 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
config.setDdlRun(false);
|
||||
config.setDatabasePlatform(new MySqlPlatform());
|
||||
|
||||
EbeanServerFactory.create(config);
|
||||
final Database database = DatabaseFactory.create(config);
|
||||
database.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,9 +95,10 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
TenantCatalogProvider catalogProvider = Mockito.mock(TenantCatalogProvider.class);
|
||||
Mockito.doReturn("tenant_catalog").when(catalogProvider).catalog(tenant);
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2");
|
||||
config.loadFromProperties();
|
||||
config.setName("multi-tenancy");
|
||||
config.setRegister(false);
|
||||
config.setDefaultServer(false);
|
||||
|
||||
@@ -105,6 +109,7 @@ public class EbeanServerFactory_MultiTenancy_Test extends BaseTestCase {
|
||||
config.setDdlRun(false);
|
||||
config.setDatabasePlatform(new MySqlPlatform());
|
||||
|
||||
EbeanServerFactory.create(config);
|
||||
final Database database = DatabaseFactory.create(config);
|
||||
database.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.event.ServerConfigStartup;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
@@ -13,7 +12,7 @@ public class EbeanServerFactory_ServerConfigStart_Test {
|
||||
@Test
|
||||
public void test() throws InterruptedException {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2");
|
||||
config.loadFromProperties();
|
||||
config.setName("h2other");
|
||||
@@ -30,17 +29,17 @@ public class EbeanServerFactory_ServerConfigStart_Test {
|
||||
OnStartup onStartup = new OnStartup();
|
||||
config.addServerConfigStartup(onStartup);
|
||||
|
||||
EbeanServer ebeanServer = EbeanServerFactory.create(config);
|
||||
Database db = DatabaseFactory.create(config);
|
||||
|
||||
assertThat(onStartup.calledWithConfig).isSameAs(config);
|
||||
assertThat(OnStartupViaClass.calledWithConfig).isSameAs(config);
|
||||
|
||||
assertThat(ebeanServer).isNotNull();
|
||||
assertThat(db).isNotNull();
|
||||
|
||||
// test server shutdown and restart using the same ServerConfig
|
||||
ebeanServer.shutdown(true, false);
|
||||
db.shutdown(true, false);
|
||||
|
||||
EbeanServer restartedServer = EbeanServerFactory.create(config);
|
||||
Database restartedServer = DatabaseFactory.create(config);
|
||||
restartedServer.shutdown(true, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DbIdentity;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.draftable.BasicDraftableBean;
|
||||
@@ -15,7 +16,12 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class PlatformNoGeneratedKeysTest {
|
||||
|
||||
static EbeanServer server = testH2Server();
|
||||
static Database server = testH2Server();
|
||||
|
||||
@AfterClass
|
||||
public static void shutdown() {
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void global_serverConfig_setDisableLazyLoading() {
|
||||
@@ -79,9 +85,9 @@ public class PlatformNoGeneratedKeysTest {
|
||||
assertThat(one.isDraft()).isFalse();
|
||||
}
|
||||
|
||||
private static EbeanServer testH2Server() {
|
||||
private static Database testH2Server() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2_noGeneratedKeys");
|
||||
|
||||
OtherH2Platform platform = new OtherH2Platform();
|
||||
@@ -108,7 +114,7 @@ public class PlatformNoGeneratedKeysTest {
|
||||
config.getClasses().add(BasicDraftableBean.class);
|
||||
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
public static class OtherH2Platform extends H2Platform {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package io.ebean.config;
|
||||
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import org.junit.Ignore;
|
||||
@@ -26,7 +26,7 @@ public class ServerConfigSqlServerTest {
|
||||
// no explicit databasePlatformName set ..
|
||||
//props.setProperty("ebean.some_sqlserver.databasePlatformName", "sqlserver17");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("some_sqlserver");
|
||||
config.loadFromProperties(props);
|
||||
|
||||
@@ -38,9 +38,10 @@ public class ServerConfigSqlServerTest {
|
||||
config.setRegister(false);
|
||||
config.getClasses().add(EBasicVer.class);
|
||||
|
||||
EbeanServer sqlServer = EbeanServerFactory.create(config);
|
||||
Database sqlServer = DatabaseFactory.create(config);
|
||||
|
||||
assertThat(sqlServer).isNotNull();
|
||||
sqlServer.shutdown();
|
||||
|
||||
// javax.persistence.PersistenceException: java.lang.IllegalArgumentException: For SqlServer please choose the more specific sqlserver16 or sqlserver17 platform via ServerConfig.setDatabasePlatformName. Refer to issue #1340 for details
|
||||
//
|
||||
@@ -61,7 +62,7 @@ public class ServerConfigSqlServerTest {
|
||||
|
||||
String name = "testsqlserver17";
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName(name);
|
||||
|
||||
Properties props = props(name);
|
||||
@@ -79,9 +80,10 @@ public class ServerConfigSqlServerTest {
|
||||
config.loadFromProperties(props);
|
||||
config.getClasses().add(EBasicVer.class);
|
||||
|
||||
EbeanServer sqlServer = EbeanServerFactory.create(config);
|
||||
Database sqlServer = DatabaseFactory.create(config);
|
||||
|
||||
assertThat(sqlServer).isNotNull();
|
||||
sqlServer.shutdown();
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@@ -93,7 +95,7 @@ public class ServerConfigSqlServerTest {
|
||||
Properties props = props(name);
|
||||
//props.setProperty("ebean.testsqlserver16.databasePlatformName", "sqlserver16");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
config.setDdlGenerate(true);
|
||||
@@ -104,9 +106,10 @@ public class ServerConfigSqlServerTest {
|
||||
config.loadFromProperties(props);
|
||||
config.getClasses().add(EBasicVer.class);
|
||||
|
||||
EbeanServer sqlServer = EbeanServerFactory.create(config);
|
||||
Database sqlServer = DatabaseFactory.create(config);
|
||||
|
||||
assertThat(sqlServer).isNotNull();
|
||||
sqlServer.shutdown();
|
||||
}
|
||||
|
||||
private Properties props(String dbName) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ public class SqlServerStepSequenceTest extends BaseTestCase {
|
||||
server().sqlUpdate("create sequence sqls_testseq_9876 start with 1 increment by 50").execute();
|
||||
|
||||
BackgroundExecutor be = server().getBackgroundExecutor();
|
||||
DataSource ds = server().getPluginApi().getDataSource();
|
||||
DataSource ds = server().getDataSource();
|
||||
|
||||
SqlServerStepSequence s = new SqlServerStepSequence(be, ds, "sqls_testseq_9876", 50);
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.common.BeanList;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import org.junit.Test;
|
||||
import org.tests.example.ModUuidGenerator;
|
||||
import org.tests.model.basic.EBasic;
|
||||
@@ -23,7 +23,7 @@ public class BeanFindControllerTest extends BaseTestCase {
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
|
||||
config.setName("h2otherfind");
|
||||
config.loadFromProperties();
|
||||
@@ -40,27 +40,27 @@ public class BeanFindControllerTest extends BaseTestCase {
|
||||
EBasicFindController findController = new EBasicFindController();
|
||||
config.getFindControllers().add(findController);
|
||||
|
||||
EbeanServer ebeanServer = EbeanServerFactory.create(config);
|
||||
Database db = DatabaseFactory.create(config);
|
||||
|
||||
assertFalse(findController.calledInterceptFind);
|
||||
ebeanServer.find(EBasic.class, 42);
|
||||
db.find(EBasic.class, 42);
|
||||
assertTrue(findController.calledInterceptFind);
|
||||
|
||||
findController.findIntercept = true;
|
||||
EBasic eBasic = ebeanServer.find(EBasic.class, 42);
|
||||
EBasic eBasic = db.find(EBasic.class, 42);
|
||||
|
||||
assertEquals(Integer.valueOf(47), eBasic.getId());
|
||||
assertEquals("47", eBasic.getName());
|
||||
|
||||
assertFalse(findController.calledInterceptFindMany);
|
||||
|
||||
List<EBasic> list = ebeanServer.find(EBasic.class).where().eq("name", "AnInvalidNameSoEmpty").findList();
|
||||
List<EBasic> list = db.find(EBasic.class).where().eq("name", "AnInvalidNameSoEmpty").findList();
|
||||
assertEquals(0, list.size());
|
||||
assertTrue(findController.calledInterceptFindMany);
|
||||
|
||||
findController.findManyIntercept = true;
|
||||
|
||||
list = ebeanServer.find(EBasic.class).where().eq("name", "AnInvalidNameSoEmpty").findList();
|
||||
list = db.find(EBasic.class).where().eq("name", "AnInvalidNameSoEmpty").findList();
|
||||
assertEquals(1, list.size());
|
||||
|
||||
eBasic = list.get(0);
|
||||
@@ -68,8 +68,9 @@ public class BeanFindControllerTest extends BaseTestCase {
|
||||
assertEquals("47", eBasic.getName());
|
||||
|
||||
ECustomId bean = new ECustomId("check");
|
||||
ebeanServer.save(bean);
|
||||
db.save(bean);
|
||||
assertNotNull(bean.getId());
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
static class EBasicFindController implements BeanFindController {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package io.ebean.event;
|
||||
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
@@ -18,22 +18,22 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class BeanPersistControllerTest {
|
||||
|
||||
private PersistAdapter continuePersistingAdapter = new PersistAdapter(true);
|
||||
private final PersistAdapter continuePersistingAdapter = new PersistAdapter(true);
|
||||
|
||||
private PersistAdapter stopPersistingAdapter = new PersistAdapter(false);
|
||||
private final PersistAdapter stopPersistingAdapter = new PersistAdapter(false);
|
||||
|
||||
@Test
|
||||
public void issue_1341() {
|
||||
|
||||
EbeanServer ebeanServer = getEbeanServer(continuePersistingAdapter);
|
||||
Database db = getDatabase(continuePersistingAdapter);
|
||||
|
||||
UTMaster bean0 = new UTMaster("one0");
|
||||
UTDetail detail0 = new UTDetail("detail0", 12, 23D);
|
||||
bean0.getDetails().add(detail0);
|
||||
|
||||
ebeanServer.save(bean0);
|
||||
db.save(bean0);
|
||||
|
||||
UTMaster master = ebeanServer.find(UTMaster.class)
|
||||
UTMaster master = db.find(UTMaster.class)
|
||||
.setId(bean0.getId())
|
||||
.fetch("details", "name, version")
|
||||
.findOne();
|
||||
@@ -41,79 +41,82 @@ public class BeanPersistControllerTest {
|
||||
UTDetail utDetail = master.getDetails().get(0);
|
||||
utDetail.setName("detail0 mod");
|
||||
|
||||
Transaction txn = ebeanServer.beginTransaction();
|
||||
Transaction txn = db.beginTransaction();
|
||||
try {
|
||||
txn.setBatchMode(true);
|
||||
ebeanServer.save(master);
|
||||
db.save(master);
|
||||
txn.commit();
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertUpdateDelete_given_continuePersistingAdapter() {
|
||||
|
||||
EbeanServer ebeanServer = getEbeanServer(continuePersistingAdapter);
|
||||
|
||||
Database db = getDatabase(continuePersistingAdapter);
|
||||
|
||||
EBasicVer bean = new EBasicVer("testController");
|
||||
|
||||
ebeanServer.save(bean);
|
||||
db.save(bean);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).hasSize(2);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).containsExactly("preInsert", "postInsert");
|
||||
continuePersistingAdapter.methodsCalled.clear();
|
||||
|
||||
bean.setName("modified");
|
||||
ebeanServer.save(bean);
|
||||
db.save(bean);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).hasSize(2);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).containsExactly("preUpdate", "postUpdate");
|
||||
continuePersistingAdapter.methodsCalled.clear();
|
||||
|
||||
ebeanServer.delete(bean);
|
||||
db.delete(bean);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).hasSize(2);
|
||||
assertThat(continuePersistingAdapter.methodsCalled).containsExactly("preDelete", "postDelete");
|
||||
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertUpdateDelete_given_stopPersistingAdapter() {
|
||||
|
||||
EbeanServer ebeanServer = getEbeanServer(stopPersistingAdapter);
|
||||
Database db = getDatabase(stopPersistingAdapter);
|
||||
|
||||
EBasicVer bean = new EBasicVer("testController");
|
||||
|
||||
ebeanServer.save(bean);
|
||||
db.save(bean);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).hasSize(1);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preInsert");
|
||||
stopPersistingAdapter.methodsCalled.clear();
|
||||
|
||||
bean.setName("modified");
|
||||
ebeanServer.update(bean);
|
||||
db.update(bean);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).hasSize(1);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preUpdate");
|
||||
stopPersistingAdapter.methodsCalled.clear();
|
||||
|
||||
ebeanServer.delete(bean);
|
||||
db.delete(bean);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).hasSize(1);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preDelete");
|
||||
stopPersistingAdapter.methodsCalled.clear();
|
||||
|
||||
ebeanServer.delete(EBasicVer.class, 22);
|
||||
db.delete(EBasicVer.class, 22);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).hasSize(1);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preDeleteById");
|
||||
stopPersistingAdapter.methodsCalled.clear();
|
||||
|
||||
ebeanServer.deleteAll(EBasicVer.class, Arrays.asList(22,23,24));
|
||||
db.deleteAll(EBasicVer.class, Arrays.asList(22,23,24));
|
||||
assertThat(stopPersistingAdapter.methodsCalled).hasSize(3);
|
||||
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preDeleteById", "preDeleteById", "preDeleteById");
|
||||
stopPersistingAdapter.methodsCalled.clear();
|
||||
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
private EbeanServer getEbeanServer(PersistAdapter persistAdapter) {
|
||||
private Database getDatabase(PersistAdapter persistAdapter) {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2ebasicver");
|
||||
config.loadFromProperties();
|
||||
config.setDdlGenerate(true);
|
||||
@@ -128,7 +131,7 @@ public class BeanPersistControllerTest {
|
||||
|
||||
config.add(persistAdapter);
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
static class PersistAdapter extends BeanPersistAdapter {
|
||||
|
||||
@@ -3,12 +3,12 @@ package io.ebean.event;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.BeanState;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -22,15 +22,15 @@ public class BeanPostLoadTest extends BaseTestCase {
|
||||
@Test
|
||||
public void testPostLoad() {
|
||||
|
||||
EbeanServer ebeanServer = getEbeanServer();
|
||||
Database db = createDatabase();
|
||||
|
||||
EBasicVer bean = new EBasicVer("testPostLoad");
|
||||
bean.setDescription("someDescription");
|
||||
bean.setOther("other");
|
||||
|
||||
ebeanServer.save(bean);
|
||||
db.save(bean);
|
||||
|
||||
EBasicVer found = ebeanServer.find(EBasicVer.class)
|
||||
EBasicVer found = db.find(EBasicVer.class)
|
||||
.select("name, other")
|
||||
.setId(bean.getId())
|
||||
.findOne();
|
||||
@@ -40,13 +40,14 @@ public class BeanPostLoadTest extends BaseTestCase {
|
||||
assertThat(postLoad.beanState.getLoadedProps()).containsExactly("id", "name", "other");
|
||||
assertThat(postLoad.bean).isSameAs(found);
|
||||
|
||||
ebeanServer.delete(bean);
|
||||
db.delete(bean);
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
|
||||
private EbeanServer getEbeanServer() {
|
||||
private Database createDatabase() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
|
||||
config.setName("h2ebasicver");
|
||||
config.loadFromProperties();
|
||||
@@ -60,7 +61,7 @@ public class BeanPostLoadTest extends BaseTestCase {
|
||||
|
||||
config.add(postLoad);
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
static class PostLoad implements BeanPostLoad {
|
||||
@@ -90,7 +91,7 @@ public class BeanPostLoadTest extends BaseTestCase {
|
||||
public void postLoad(Object bean) {
|
||||
this.methodsCalled.add("postLoad");
|
||||
this.bean = bean;
|
||||
this.beanState = Ebean.getBeanState(bean);
|
||||
this.beanState = DB.getBeanState(bean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ import io.ebeaninternal.server.transaction.RemoteTransactionEvent;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Clock;
|
||||
import java.util.Collection;
|
||||
@@ -336,6 +337,16 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getDataSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getReadOnlyDataSource() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
|
||||
+7
-4
@@ -26,10 +26,13 @@ public class BeanDescriptor_registerTest {
|
||||
config.getClasses().add(EBasic.class);
|
||||
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer)DatabaseFactory.create(config);
|
||||
BeanDescriptor<EBasic> desc = ebeanServer.getBeanDescriptor(EBasic.class);
|
||||
|
||||
persistListenerRegistrationTests(desc);
|
||||
persistControllerRegistrationTests(desc);
|
||||
try {
|
||||
BeanDescriptor<EBasic> desc = ebeanServer.getBeanDescriptor(EBasic.class);
|
||||
persistListenerRegistrationTests(desc);
|
||||
persistControllerRegistrationTests(desc);
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void persistControllerRegistrationTests(BeanDescriptor<EBasic> desc) {
|
||||
|
||||
@@ -258,7 +258,7 @@ public class TestRawSqlBuilder extends BaseTestCase {
|
||||
"join o_customer c on o.kcustomer_id = c.id " +
|
||||
"where c.id = ? and o.id > ?";
|
||||
|
||||
final DataSource dataSource = DB.getDefault().getPluginApi().getDataSource();
|
||||
final DataSource dataSource = DB.getDefault().getDataSource();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
try (PreparedStatement stmt = connection.prepareStatement(sql)) {
|
||||
|
||||
+25
-23
@@ -4,7 +4,6 @@ import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
@@ -25,7 +24,7 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@ForPlatform({Platform.H2})
|
||||
@Test
|
||||
public void get() {
|
||||
Ebean.execute(() -> {
|
||||
DB.execute(() -> {
|
||||
SpiTransaction txn = getInScopeTransaction();
|
||||
assertNotNull(txn);
|
||||
});
|
||||
@@ -38,12 +37,12 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@Test
|
||||
public void tryWithResources_expect_scopeCleanup() {
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
assertNotNull(transaction);
|
||||
SpiTransaction txn = getInScopeTransaction();
|
||||
assertSame(txn, transaction);
|
||||
|
||||
try (Transaction nested = Ebean.beginTransaction()) {
|
||||
try (Transaction nested = DB.beginTransaction()) {
|
||||
assertNotNull(nested);
|
||||
SpiTransaction txnNested = getInScopeTransaction();
|
||||
assertSame(txnNested, nested);
|
||||
@@ -59,7 +58,7 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@Test
|
||||
public void afterCommit_expect_scopeCleanup() {
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.commit();
|
||||
assertNull(getInScopeTransaction());
|
||||
}
|
||||
@@ -70,7 +69,7 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@Test
|
||||
public void afterRollback_expect_scopeCleanup() {
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
|
||||
transaction.rollback();
|
||||
assertNull(getInScopeTransaction());
|
||||
@@ -82,8 +81,8 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@Test
|
||||
public void end_withoutActiveTransaction_isFine() {
|
||||
|
||||
assertNull(Ebean.currentTransaction());
|
||||
Ebean.endTransaction();
|
||||
assertNull(DB.currentTransaction());
|
||||
DB.endTransaction();
|
||||
}
|
||||
|
||||
@ForPlatform({Platform.H2})
|
||||
@@ -106,28 +105,31 @@ public class DefaultTransactionThreadLocalTest extends BaseTestCase {
|
||||
@ForPlatform(Platform.H2)
|
||||
@Test
|
||||
public void usingDatabase() {
|
||||
|
||||
// setup
|
||||
Database otherDb = createOtherDatabase();
|
||||
EBasicVer bean = new EBasicVer("TestUsingDatabase");
|
||||
otherDb.save(bean);
|
||||
try {
|
||||
EBasicVer bean = new EBasicVer("TestUsingDatabase");
|
||||
otherDb.save(bean);
|
||||
|
||||
// act
|
||||
final EBasicVer foundOtherDb = DB.find(EBasicVer.class)
|
||||
.usingDatabase(otherDb)
|
||||
.where().eq("name", "TestUsingDatabase")
|
||||
.findOne();
|
||||
// act
|
||||
final EBasicVer foundOtherDb = DB.find(EBasicVer.class)
|
||||
.usingDatabase(otherDb)
|
||||
.where().eq("name", "TestUsingDatabase")
|
||||
.findOne();
|
||||
|
||||
assertNotNull(foundOtherDb);
|
||||
assertThat(foundOtherDb.getId()).isEqualTo(bean.getId());
|
||||
assertNotNull(foundOtherDb);
|
||||
assertThat(foundOtherDb.getId()).isEqualTo(bean.getId());
|
||||
|
||||
final EBasicVer foundDefaultDb = DB.find(EBasicVer.class)
|
||||
.where().eq("name", "TestUsingDatabase")
|
||||
.findOne();
|
||||
final EBasicVer foundDefaultDb = DB.find(EBasicVer.class)
|
||||
.where().eq("name", "TestUsingDatabase")
|
||||
.findOne();
|
||||
|
||||
assertNull(foundDefaultDb);
|
||||
assertNull(foundDefaultDb);
|
||||
|
||||
otherDb.delete(bean);
|
||||
otherDb.delete(bean);
|
||||
} finally {
|
||||
otherDb.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ public class Main {
|
||||
|
||||
|
||||
EbeanServer ms = Ebean.getServer("ms");
|
||||
DataSource dataSource = ms.getPluginApi().getDataSource();
|
||||
DataSource dataSource = ms.getDataSource();
|
||||
|
||||
Connection connection = dataSource.getConnection();
|
||||
PreparedStatement statement = connection.prepareStatement("select next VALUE for j2_seq");
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package org;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.PlatformNoGeneratedKeysTest;
|
||||
import io.ebean.config.ServerConfig;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
@@ -40,13 +40,13 @@ public class MainMemoryLeak {
|
||||
|
||||
PlatformNoGeneratedKeysTest.OtherH2Platform platform = new PlatformNoGeneratedKeysTest.OtherH2Platform();
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
|
||||
config.setDatabasePlatform(platform);
|
||||
config.addClass(ECachedBean.class);
|
||||
config.loadFromProperties();
|
||||
|
||||
EbeanServer server = EbeanServerFactory.create(config);
|
||||
Database server = DatabaseFactory.create(config);
|
||||
|
||||
// create a string with 10k chars
|
||||
char[] c = new char[10_000];
|
||||
@@ -70,6 +70,6 @@ public class MainMemoryLeak {
|
||||
System.out.println("Success, no mem limit detected");
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
server.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package org.multitenant.partition;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.TenantMode;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -16,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class MultiTenantPartitionTest extends BaseTestCase {
|
||||
|
||||
private static String[] names = {"Ace", "Base", "Case", "Dae", "Eva"};
|
||||
private static final String[] names = {"Ace", "Base", "Case", "Dae", "Eva"};
|
||||
|
||||
static List<MtTenant> tenants() {
|
||||
List<MtTenant> tenants = new ArrayList<>();
|
||||
@@ -26,12 +27,16 @@ public class MultiTenantPartitionTest extends BaseTestCase {
|
||||
return tenants;
|
||||
}
|
||||
|
||||
private static EbeanServer server = init();
|
||||
|
||||
private static final Database server = init();
|
||||
static {
|
||||
server.saveAll(tenants());
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdown() {
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void start() {
|
||||
|
||||
@@ -103,9 +108,9 @@ public class MultiTenantPartitionTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
|
||||
private static EbeanServer init() {
|
||||
private static Database init() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
|
||||
config.setName("h2multitenant");
|
||||
config.loadFromProperties();
|
||||
@@ -120,6 +125,6 @@ public class MultiTenantPartitionTest extends BaseTestCase {
|
||||
config.getClasses().add(MtTenant.class);
|
||||
config.getClasses().add(MtContent.class);
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class TestQueryUsingConnection extends BaseTestCase {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
DataSource dataSource = DB.getDefault().getPluginApi().getDataSource();
|
||||
DataSource dataSource = DB.getDefault().getDataSource();
|
||||
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.tests.basic;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.ESimple;
|
||||
@@ -22,6 +23,11 @@ public class TestQueryUsingDatabase {
|
||||
DB.byName(SOME_OTHER_DB_NAME).insert(RECORD2);
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
DB.byName(SOME_OTHER_DB_NAME).shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void usingNonDefaultDatabase() {
|
||||
final Database nonDefaultDb = DB.byName(SOME_OTHER_DB_NAME);
|
||||
|
||||
@@ -3,9 +3,10 @@ package org.tests.changelog;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.annotation.ChangeLog;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.event.BeanPersistRequest;
|
||||
import io.ebean.event.changelog.BeanChange;
|
||||
import io.ebean.event.changelog.ChangeLogFilter;
|
||||
@@ -14,7 +15,6 @@ import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.changelog.ChangeSet;
|
||||
import io.ebean.event.changelog.ChangeType;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -31,16 +31,16 @@ public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
TDChangeLogRegister changeLogRegister = new TDChangeLogRegister();
|
||||
|
||||
SpiEbeanServer server;
|
||||
Database server;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
server = getServer();
|
||||
server = createServer();
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
server.shutdown(true, false);
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -65,7 +65,7 @@ public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
assertThat(change.getEvent()).isEqualTo(ChangeType.UPDATE);
|
||||
assertThat(change.getOldData()).contains("\"name\":\"logBean\"");
|
||||
assertThat(change.getData()) .contains("\"name\":\"ChangedName\"");
|
||||
assertThat(change.getData()).contains("\"name\":\"ChangedName\"");
|
||||
|
||||
|
||||
server.delete(bean);
|
||||
@@ -120,31 +120,27 @@ public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
}
|
||||
|
||||
private Database createServer() {
|
||||
|
||||
private SpiEbeanServer getServer() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2other");
|
||||
config.loadFromProperties();
|
||||
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.setDdlExtra(false);
|
||||
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
config.setChangeLogAsync(false);
|
||||
|
||||
config.addClass(EBasicChangeLog.class);
|
||||
|
||||
config.setChangeLogPrepare(changeLogPrepare);
|
||||
config.setChangeLogListener(changeLogListener);
|
||||
config.setChangeLogRegister(changeLogRegister);
|
||||
|
||||
return (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
class TDChangeLogPrepare implements ChangeLogPrepare {
|
||||
public static class TDChangeLogPrepare implements ChangeLogPrepare {
|
||||
@Override
|
||||
public boolean prepare(ChangeSet changes) {
|
||||
changes.setUserId("appUser1");
|
||||
@@ -153,14 +149,12 @@ public class TestChangeLog extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
class TDChangeLogListener implements ChangeLogListener {
|
||||
public static class TDChangeLogListener implements ChangeLogListener {
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
ChangeSet changes;
|
||||
|
||||
/**
|
||||
*/
|
||||
public TDChangeLogListener() {
|
||||
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
|
||||
}
|
||||
@@ -184,7 +178,7 @@ public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
}
|
||||
|
||||
class TDChangeLogRegister implements ChangeLogRegister {
|
||||
public static class TDChangeLogRegister implements ChangeLogRegister {
|
||||
|
||||
@Override
|
||||
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
|
||||
@@ -198,11 +192,10 @@ public class TestChangeLog extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Change log filter that includes all the inserts, updates and deletes.
|
||||
*/
|
||||
class TDFilter implements ChangeLogFilter {
|
||||
public static class TDFilter implements ChangeLogFilter {
|
||||
|
||||
/**
|
||||
* Returns true including all the inserts.
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package org.tests.ddl;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import org.tests.model.basic.EBasic;
|
||||
|
||||
public class MainDdlWithSchema {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
ServerConfig cfg = new ServerConfig();
|
||||
cfg.setName("h2");
|
||||
cfg.loadFromProperties();
|
||||
cfg.addClass(EBasic.class);
|
||||
|
||||
// .... other settings ...
|
||||
//UnderscoreNamingConvention naming = new UnderscoreNamingConvention();
|
||||
//naming.setSchema("test");
|
||||
//cfg.setNamingConvention(naming);
|
||||
cfg.setDdlGenerate(true);
|
||||
cfg.setDdlRun(true);
|
||||
EbeanServer ebean = EbeanServerFactory.create(cfg);
|
||||
//ebean.createSqlUpdate("create schema foo").execute();
|
||||
System.out.println(ebean);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -30,7 +30,7 @@ public class TestCacheViaComplexNaturalKey extends BaseTestCase {
|
||||
return server().getServerCacheManager();
|
||||
}
|
||||
|
||||
private static synchronized void insertSome() {
|
||||
private static void insertSome() {
|
||||
if (!loadOnce) {
|
||||
Ebean.find(OCachedNatKeyBean.class).delete();
|
||||
for (String store : Arrays.asList("abc", "def")) {
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase {
|
||||
return server().getServerCacheManager();
|
||||
}
|
||||
|
||||
private static synchronized void insertSome() {
|
||||
private static void insertSome() {
|
||||
if (!loadOnce) {
|
||||
Ebean.find(OCachedNatKeyBean3.class).delete();
|
||||
|
||||
|
||||
+14
-22
@@ -1,16 +1,16 @@
|
||||
package org.tests.persistencecontext;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.config.ContainerConfig;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -20,20 +20,20 @@ public class TestPersistenceContextServerConfig extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test_config() {
|
||||
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer) create();
|
||||
try {
|
||||
Query<EBasicVer> query = ebeanServer.find(EBasicVer.class);
|
||||
PersistenceContextScope scope = ebeanServer.getPersistenceContextScope((SpiQuery<?>) query);
|
||||
|
||||
Query<EBasicVer> query = ebeanServer.find(EBasicVer.class);
|
||||
|
||||
PersistenceContextScope scope = ebeanServer.getPersistenceContextScope((SpiQuery<?>) query);
|
||||
|
||||
assertEquals(PersistenceContextScope.QUERY, scope);
|
||||
assertEquals(PersistenceContextScope.QUERY, scope);
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
static EbeanServer create() {
|
||||
static Database create() {
|
||||
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("withPCQuery");
|
||||
config.setDdlExtra(false);
|
||||
|
||||
@@ -49,15 +49,7 @@ public class TestPersistenceContextServerConfig extends BaseTestCase {
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
|
||||
// DataSourceConfig dataSourceConfig = new DataSourceConfig();
|
||||
// dataSourceConfig.setUsername("sa");
|
||||
// dataSourceConfig.setPassword("");
|
||||
// dataSourceConfig.setUrl("jdbc:h2:mem:withPCQuery;");
|
||||
// dataSourceConfig.setDriver("org.h2.Driver");
|
||||
// config.setDataSourceConfig(dataSourceConfig);
|
||||
|
||||
config.addClass(EBasicVer.class);
|
||||
|
||||
return EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class TestQueryFindIterate extends BaseTestCase {
|
||||
SpiServer pluginApi = server().getPluginApi();
|
||||
DataSourcePool dsPool = (DataSourcePool) pluginApi.getServerConfig().getReadOnlyDataSource();
|
||||
if (dsPool == null) {
|
||||
dsPool = (DataSourcePool) server().getPluginApi().getDataSource();
|
||||
dsPool = (DataSourcePool) server().getDataSource();
|
||||
}
|
||||
|
||||
int startConns = dsPool.getStatus(false).getBusy();
|
||||
|
||||
@@ -5,9 +5,9 @@ import io.ebean.Ebean;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -38,7 +38,7 @@ public class TestNativeILikeExpression extends BaseTestCase {
|
||||
|
||||
SpiServer pluginApi = server().getPluginApi();
|
||||
boolean expressionNativeIlike = pluginApi.getServerConfig().isExpressionNativeIlike();
|
||||
Platform platform = pluginApi.getDatabasePlatform().getPlatform();
|
||||
Platform platform = pluginApi.getPlatform().base();
|
||||
|
||||
return expressionNativeIlike && platform == Platform.POSTGRES;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package org.tests.readaudit;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheStatistics;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.event.readaudit.ReadAuditQueryPlan;
|
||||
import io.ebean.event.readaudit.ReadEvent;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.EBasicChangeLog;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Country;
|
||||
import org.tests.model.basic.EBasicChangeLog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -30,18 +30,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestReadAudit extends BaseTestCase {
|
||||
|
||||
TDReadAuditPrepare readAuditPrepare = new TDReadAuditPrepare(true);
|
||||
TDReadAuditPrepare readAuditPrepare = new TDReadAuditPrepare();
|
||||
|
||||
TDReadAuditLogger readAuditLogger = new TDReadAuditLogger(true);
|
||||
TDReadAuditLogger readAuditLogger = new TDReadAuditLogger();
|
||||
|
||||
SpiEbeanServer server;
|
||||
Database server;
|
||||
|
||||
Long id1;
|
||||
Long id2;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
server = getServer();
|
||||
server = createServer();
|
||||
|
||||
EBasicChangeLog bean = new EBasicChangeLog();
|
||||
bean.setName("readAudito1");
|
||||
@@ -63,7 +63,7 @@ public class TestReadAudit extends BaseTestCase {
|
||||
|
||||
@After
|
||||
public void shutdown() {
|
||||
server.shutdown(true, false);
|
||||
server.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -304,9 +304,9 @@ public class TestReadAudit extends BaseTestCase {
|
||||
assertThat(readAuditLogger.many).hasSize(2);
|
||||
}
|
||||
|
||||
private SpiEbeanServer getServer() {
|
||||
private Database createServer() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2other");
|
||||
config.loadFromProperties();
|
||||
|
||||
@@ -323,7 +323,7 @@ public class TestReadAudit extends BaseTestCase {
|
||||
config.setReadAuditLogger(readAuditLogger);
|
||||
config.setReadAuditPrepare(readAuditPrepare);
|
||||
|
||||
return (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
private void resetCounters() {
|
||||
@@ -331,13 +331,10 @@ public class TestReadAudit extends BaseTestCase {
|
||||
readAuditPrepare.resetCounters();
|
||||
}
|
||||
|
||||
class TDReadAuditPrepare implements ReadAuditPrepare {
|
||||
static class TDReadAuditPrepare implements ReadAuditPrepare {
|
||||
|
||||
int count;
|
||||
|
||||
TDReadAuditPrepare(boolean dummy) {
|
||||
}
|
||||
|
||||
void resetCounters() {
|
||||
count = 0;
|
||||
}
|
||||
@@ -351,15 +348,12 @@ public class TestReadAudit extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
class TDReadAuditLogger implements ReadAuditLogger {
|
||||
static class TDReadAuditLogger implements ReadAuditLogger {
|
||||
|
||||
Set<ReadAuditQueryPlan> plans = new HashSet<>();
|
||||
List<ReadEvent> beans = new ArrayList<>();
|
||||
List<ReadEvent> many = new ArrayList<>();
|
||||
|
||||
TDReadAuditLogger(boolean dummy) {
|
||||
}
|
||||
|
||||
void resetCounters() {
|
||||
plans.clear();
|
||||
beans.clear();
|
||||
|
||||
@@ -72,7 +72,7 @@ datasource.db.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
datasource.h2.url=jdbc:h2:mem:tests
|
||||
datasource.h2.url=jdbc:h2:mem:testsMem;DB_CLOSE_ON_EXIT=FALSE
|
||||
#datasource.h2.driver=org.h2.Driver
|
||||
datasource.h2.minConnections=1
|
||||
datasource.h2.maxConnections=25
|
||||
@@ -86,7 +86,7 @@ datasource.h2.poolListener=org.tests.basic.MyTestDataSourcePoolListener
|
||||
|
||||
datasource.h2multitenant.username=sa
|
||||
datasource.h2multitenant.password=
|
||||
datasource.h2multitenant.url=jdbc:h2:mem:h2multitenant
|
||||
datasource.h2multitenant.url=jdbc:h2:mem:h2multitenant;DB_CLOSE_ON_EXIT=FALSE
|
||||
|
||||
datasource.h2autocommit.autoCommit=true
|
||||
datasource.h2autocommit.username=sa
|
||||
@@ -100,11 +100,11 @@ datasource.h2autocommit2.url=jdbc:h2:mem:autocommit2tests
|
||||
|
||||
datasource.h2other.username=sa
|
||||
datasource.h2other.password=
|
||||
datasource.h2other.url=jdbc:h2:mem:h2other
|
||||
datasource.h2other.url=jdbc:h2:mem:h2other;DB_CLOSE_ON_EXIT=FALSE
|
||||
|
||||
datasource.h2otherfind.username=sa
|
||||
datasource.h2otherfind.password=
|
||||
datasource.h2otherfind.url=jdbc:h2:mem:h2otherfind
|
||||
datasource.h2otherfind.url=jdbc:h2:mem:h2otherfind;DB_CLOSE_ON_EXIT=FALSE
|
||||
|
||||
datasource.h2ebasicver.username=sa
|
||||
datasource.h2ebasicver.password=
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
<description>DDL and DB Migration generation</description>
|
||||
<artifactId>ebean-ddlgen</artifactId>
|
||||
<!-- <version>12.4.1</version>-->
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- needed for java 11+ -->
|
||||
@@ -48,7 +49,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.4.2</version>
|
||||
<version>12.5.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -142,7 +142,7 @@ public class DdlGenerator implements SpiDdlGenerator {
|
||||
|
||||
private Connection obtainConnection() {
|
||||
try {
|
||||
return server.getPluginApi().getDataSource().getConnection();
|
||||
return server.getDataSource().getConnection();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException("Failed to obtain connection to run DDL", e);
|
||||
}
|
||||
|
||||
+1
-1
@@ -562,7 +562,7 @@ public class PlatformDdl {
|
||||
|
||||
/**
|
||||
* Return true if unique constraints for nullable columns can be inlined as normal.
|
||||
* Returns false for MsSqlServer & DB2 due to it's not possible to to put a constraint
|
||||
* Returns false for MsSqlServer and DB2 due to it's not possible to to put a constraint
|
||||
* on a nullable column
|
||||
*/
|
||||
public boolean isInlineUniqueWhenNullable() {
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Vilmos Nagy <vilmos.nagy@outlook.com>
|
||||
* @author Vilmos Nagy
|
||||
*/
|
||||
public class SqlServerHistoryDdl implements PlatformHistoryDdl {
|
||||
|
||||
|
||||
+8
-6
@@ -1,8 +1,8 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -42,7 +42,7 @@ public class DbMigrationDropHistoryTest {
|
||||
|
||||
migration.setPathToResources("src/test/resources");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("migrationtest-history");
|
||||
config.loadFromProperties();
|
||||
config.setRegister(false);
|
||||
@@ -50,7 +50,7 @@ public class DbMigrationDropHistoryTest {
|
||||
|
||||
|
||||
config.setPackages(Arrays.asList("misc.migration.history.v1_0"));
|
||||
EbeanServer server = EbeanServerFactory.create(config);
|
||||
Database server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
|
||||
// First, we clean up the output-directory
|
||||
@@ -65,7 +65,8 @@ public class DbMigrationDropHistoryTest {
|
||||
|
||||
// and now for v1_1
|
||||
config.setPackages(Arrays.asList("misc.migration.history.v1_1"));
|
||||
server = EbeanServerFactory.create(config);
|
||||
server.shutdown();
|
||||
server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.1");
|
||||
assertThat(migration.generateMigration()).isNull(); // subsequent call
|
||||
@@ -82,6 +83,7 @@ public class DbMigrationDropHistoryTest {
|
||||
.hasMessageContaining("No 'pendingDrops'"); // subsequent call
|
||||
System.clearProperty("ddl.migration.pendingDropsFor");
|
||||
|
||||
server.shutdown();
|
||||
logger.info("end");
|
||||
}
|
||||
|
||||
|
||||
+11
-8
@@ -1,9 +1,9 @@
|
||||
package io.ebeaninternal.dbmigration;
|
||||
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -57,7 +57,7 @@ public class DbMigrationGenerateTest {
|
||||
migration.addPlatform(Platform.SQLSERVER17, "sqlserver17");
|
||||
migration.addPlatform(Platform.HANA, "hana");
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("migrationtest");
|
||||
config.loadFromProperties();
|
||||
config.setRegister(false);
|
||||
@@ -66,7 +66,7 @@ public class DbMigrationGenerateTest {
|
||||
|
||||
|
||||
config.setPackages(Arrays.asList("misc.migration.v1_0"));
|
||||
EbeanServer server = EbeanServerFactory.create(config);
|
||||
Database server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
|
||||
// First, we clean up the output-directory
|
||||
@@ -81,7 +81,8 @@ public class DbMigrationGenerateTest {
|
||||
|
||||
// and now for v1_1
|
||||
config.setPackages(Arrays.asList("misc.migration.v1_1"));
|
||||
server = EbeanServerFactory.create(config);
|
||||
server.shutdown();
|
||||
server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.1");
|
||||
assertThat(migration.generateMigration()).isNull(); // subsequent call
|
||||
@@ -100,7 +101,8 @@ public class DbMigrationGenerateTest {
|
||||
|
||||
// and now for v1_2 with
|
||||
config.setPackages(Arrays.asList("misc.migration.v1_2"));
|
||||
server = EbeanServerFactory.create(config);
|
||||
server.shutdown();
|
||||
server = DatabaseFactory.create(config);
|
||||
migration.setServer(server);
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.3");
|
||||
assertThat(migration.generateMigration()).isNull(); // subsequent call
|
||||
@@ -108,13 +110,14 @@ public class DbMigrationGenerateTest {
|
||||
|
||||
System.setProperty("ddl.migration.pendingDropsFor", "1.3");
|
||||
assertThat(migration.generateMigration()).isEqualTo("1.4__dropsFor_1.3");
|
||||
assertThatThrownBy(()->migration.generateMigration())
|
||||
assertThatThrownBy(migration::generateMigration)
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.hasMessageContaining("No 'pendingDrops'"); // subsequent call
|
||||
|
||||
System.clearProperty("ddl.migration.pendingDropsFor");
|
||||
assertThat(migration.generateMigration()).isNull(); // subsequent call
|
||||
|
||||
server.shutdown();
|
||||
logger.info("end");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
public class DbMigrationTest extends BaseTestCase {
|
||||
|
||||
private void runScript(boolean expectErrors, String scriptName) throws IOException {
|
||||
String ddl = Helper.asText(this, "/dbmigration/migrationtest/" + server().getPluginApi().getDatabasePlatform().getName()+"/" + scriptName);
|
||||
String ddl = Helper.asText(this, "/dbmigration/migrationtest/" + server().getPlatform().name().toLowerCase() + "/" + scriptName);
|
||||
runScript(expectErrors, ddl, scriptName);
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -73,27 +73,28 @@ public class ModelBuildBeanVisitorTest extends BaseTestCase {
|
||||
config.setDatabasePlatform(new SqlServer17Platform());
|
||||
|
||||
final SpiEbeanServer database = (SpiEbeanServer)DatabaseFactory.create(config);
|
||||
try {
|
||||
ModelBuildContext ctx = new ModelBuildContext(model, config.getDatabasePlatform(), config.getConstraintNaming(), true);
|
||||
|
||||
ModelBuildBeanVisitor addTable = new ModelBuildBeanVisitor(ctx);
|
||||
|
||||
ModelBuildContext ctx = new ModelBuildContext(model, config.getDatabasePlatform(), config.getConstraintNaming(), true);
|
||||
new VisitAllUsing(addTable, database).visitAllBeans();
|
||||
|
||||
ModelBuildBeanVisitor addTable = new ModelBuildBeanVisitor(ctx);
|
||||
MTable parent = model.getTable("[CKeyParent]");
|
||||
assertThat(parent.getPkName()).isEqualTo("[pk_CKeyParent]");
|
||||
|
||||
new VisitAllUsing(addTable, database).visitAllBeans();
|
||||
MTable detail = model.getTable("[CKeyDetail]");
|
||||
assertThat(detail.getPkName()).isEqualTo("[pk_CKeyDetail]");
|
||||
|
||||
MTable parent = model.getTable("[CKeyParent]");
|
||||
assertThat(parent.getPkName()).isEqualTo("[pk_CKeyParent]");
|
||||
final List<MCompoundForeignKey> compoundKeys = detail.getCompoundKeys();
|
||||
assertThat(compoundKeys).hasSize(1);
|
||||
final MCompoundForeignKey fkey = compoundKeys.get(0);
|
||||
assertThat(fkey.getName()).isEqualTo("[fk_CKeyDetail_parent]");
|
||||
assertThat(fkey.getIndexName()).isEqualTo("[ix_CKeyDetail_parent]");
|
||||
|
||||
MTable detail = model.getTable("[CKeyDetail]");
|
||||
assertThat(detail.getPkName()).isEqualTo("[pk_CKeyDetail]");
|
||||
|
||||
final List<MCompoundForeignKey> compoundKeys = detail.getCompoundKeys();
|
||||
assertThat(compoundKeys).hasSize(1);
|
||||
final MCompoundForeignKey fkey = compoundKeys.get(0);
|
||||
assertThat(fkey.getName()).isEqualTo("[fk_CKeyDetail_parent]");
|
||||
assertThat(fkey.getIndexName()).isEqualTo("[ix_CKeyDetail_parent]");
|
||||
|
||||
database.shutdown(true, false);
|
||||
} finally {
|
||||
database.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private void assert_compound_pk(ModelContainer model) {
|
||||
|
||||
+33
-30
@@ -2,20 +2,20 @@ package io.ebeaninternal.dbmigration.model.build;
|
||||
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.Helper;
|
||||
import io.ebeaninternal.dbmigration.migration.Migration;
|
||||
import io.ebeaninternal.dbmigration.migrationreader.MigrationXmlReader;
|
||||
import io.ebeaninternal.dbmigration.model.CurrentModel;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import io.ebeaninternal.dbmigration.model.ModelContainer;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.CKeyAssoc;
|
||||
import org.tests.model.basic.CKeyDetail;
|
||||
import org.tests.model.basic.CKeyParent;
|
||||
import org.tests.model.basic.CKeyParentId;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -23,9 +23,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ModelBuild_compoundKeyTest extends BaseTestCase {
|
||||
|
||||
private SpiEbeanServer getServer() {
|
||||
private SpiEbeanServer createServer() {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2");
|
||||
config.loadFromProperties();
|
||||
config.setName("h2other");
|
||||
@@ -40,46 +40,49 @@ public class ModelBuild_compoundKeyTest extends BaseTestCase {
|
||||
config.addClass(CKeyAssoc.class);
|
||||
config.addClass(CKeyParentId.class);
|
||||
|
||||
return (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
return (SpiEbeanServer) DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
SpiEbeanServer ebeanServer = createServer();
|
||||
try {
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
ModelContainer model = currentModel.read();
|
||||
|
||||
SpiEbeanServer ebeanServer = getServer();
|
||||
MTable parent = model.getTable("ckey_parent");
|
||||
MTable detail = model.getTable("ckey_detail");
|
||||
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
ModelContainer model = currentModel.read();
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(detail).isNotNull();
|
||||
assertThat(parent.primaryKeyColumns()).hasSize(2);
|
||||
assertThat(detail.getCompoundKeys()).hasSize(1);
|
||||
|
||||
MTable parent = model.getTable("ckey_parent");
|
||||
MTable detail = model.getTable("ckey_detail");
|
||||
String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql");
|
||||
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(detail).isNotNull();
|
||||
assertThat(parent.primaryKeyColumns()).hasSize(2);
|
||||
assertThat(detail.getCompoundKeys()).hasSize(1);
|
||||
|
||||
String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql");
|
||||
|
||||
String createDdl = currentModel.getCreateDdl();
|
||||
assertThat(createDdl).startsWith("-- Generated by ebean").endsWith(apply);
|
||||
String createDdl = currentModel.getCreateDdl();
|
||||
assertThat(createDdl).startsWith("-- Generated by ebean").endsWith(apply);
|
||||
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFromMigration() throws IOException {
|
||||
|
||||
|
||||
Migration migration = MigrationXmlReader.read("/container/test-compoundkey.xml");
|
||||
SpiEbeanServer ebeanServer = createServer();
|
||||
try {
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
currentModel.setChangeSet(migration.getChangeSet().get(0));
|
||||
|
||||
SpiEbeanServer ebeanServer = getServer();
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
currentModel.setChangeSet(migration.getChangeSet().get(0));
|
||||
String createDdl = currentModel.getCreateDdl();
|
||||
String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql");
|
||||
|
||||
String createDdl = currentModel.getCreateDdl();
|
||||
String apply = Helper.asText(this, "/assert/ModelBuild_compoundKeyTest/apply.sql");
|
||||
|
||||
assertThat(createDdl).startsWith("-- Generated by ebean").endsWith(apply);
|
||||
assertThat(createDdl).startsWith("-- Generated by ebean").endsWith(apply);
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+29
-24
@@ -2,15 +2,15 @@ package io.ebeaninternal.dbmigration.model.build;
|
||||
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.EbeanServerFactory;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.Helper;
|
||||
import io.ebeaninternal.dbmigration.model.CurrentModel;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Person;
|
||||
import org.tests.model.basic.Phone;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -18,9 +18,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ModelBuild_explicitSequencesTest extends BaseTestCase {
|
||||
|
||||
private SpiEbeanServer getServer(boolean postgres) {
|
||||
private SpiEbeanServer createServer(boolean postgres) {
|
||||
|
||||
ServerConfig config = new ServerConfig();
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2");
|
||||
config.loadFromProperties();
|
||||
config.setName("h2other");
|
||||
@@ -34,35 +34,40 @@ public class ModelBuild_explicitSequencesTest extends BaseTestCase {
|
||||
|
||||
config.addClass(Person.class);
|
||||
config.addClass(Phone.class);
|
||||
|
||||
return (SpiEbeanServer) EbeanServerFactory.create(config);
|
||||
return (SpiEbeanServer) DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws IOException {
|
||||
SpiEbeanServer ebeanServer = createServer(false);
|
||||
try {
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
|
||||
SpiEbeanServer ebeanServer = getServer(false);
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
|
||||
String apply = currentModel.getCreateDdl();
|
||||
assertThat(apply)
|
||||
.startsWith("-- Generated by ebean")
|
||||
.endsWith(Helper.asText(this, "/assert/ModelBuild_explicitSequencesTest/apply.sql"));
|
||||
String apply = currentModel.getCreateDdl();
|
||||
assertThat(apply)
|
||||
.startsWith("-- Generated by ebean")
|
||||
.endsWith(Helper.asText(this, "/assert/ModelBuild_explicitSequencesTest/apply.sql"));
|
||||
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_asPostgres() throws IOException {
|
||||
SpiEbeanServer ebeanServer = createServer(true);
|
||||
try {
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
final DdlOptions ddlOptions = currentModel.getDdlOptions();
|
||||
ddlOptions.setForeignKeySkipCheck(true);
|
||||
|
||||
SpiEbeanServer ebeanServer = getServer(true);
|
||||
CurrentModel currentModel = new CurrentModel(ebeanServer);
|
||||
final DdlOptions ddlOptions = currentModel.getDdlOptions();
|
||||
ddlOptions.setForeignKeySkipCheck(true);
|
||||
|
||||
String apply = currentModel.getCreateDdl();
|
||||
assertThat(apply)
|
||||
.startsWith("-- Generated by ebean")
|
||||
.endsWith(Helper.asText(this, "/assert/ModelBuild_explicitSequencesTest/pg-apply.sql"));
|
||||
String apply = currentModel.getCreateDdl();
|
||||
assertThat(apply)
|
||||
.startsWith("-- Generated by ebean")
|
||||
.endsWith(Helper.asText(this, "/assert/ModelBuild_explicitSequencesTest/pg-apply.sql"));
|
||||
} finally {
|
||||
ebeanServer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<name>ebean external mapping api</name>
|
||||
<description>API for mapping external named queries</description>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,20 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.5.0</version>
|
||||
<version>12.5.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
<!-- <artifactId>java8-oss</artifactId>-->
|
||||
<!-- <version>2.2</version>-->
|
||||
<!-- </parent>-->
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.5.2</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean external mapping xml</name>
|
||||
<description>XML implementation for mapping external named queries</description>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.25</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -33,14 +52,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddlgen</artifactId>
|
||||
<version>12.4.1</version>
|
||||
<version>12.5.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -51,12 +77,12 @@
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.17</version>
|
||||
<version>2.18</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<!-- other tiles ... -->
|
||||
<tile>io.ebean.tile:enhancement:12.4.2</tile>
|
||||
<tile>io.ebean.tile:enhancement:12.5.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
spaces_around_operators = true
|
||||
max_line_length = 130
|
||||
|
||||
[pom.xml]
|
||||
# Because of <project... line
|
||||
max_line_length = 999
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user