mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
62
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d758590da4 | ||
|
|
21a5efa9b9 | ||
|
|
55a2cb12bb | ||
|
|
293700acc0 | ||
|
|
8980a3b6fd | ||
|
|
72efc5d7d6 | ||
|
|
84589fcce6 | ||
|
|
a0e44aedf3 | ||
|
|
41102aca35 | ||
|
|
548cea432e | ||
|
|
592cb37693 | ||
|
|
f2178bf0a6 | ||
|
|
5cae425b09 | ||
|
|
94b78f1c2d | ||
|
|
561affef0f | ||
|
|
3310d2186d | ||
|
|
02bdace144 | ||
|
|
7c17098f17 | ||
|
|
6f194ce95d | ||
|
|
dbe473d5a1 | ||
|
|
ed0e9e7006 | ||
|
|
2a03198393 | ||
|
|
6f1472abe0 | ||
|
|
6dea4f0890 | ||
|
|
4a4ec42cdc | ||
|
|
92ea8e3738 | ||
|
|
c349832d35 | ||
|
|
90493ad57d | ||
|
|
5012f59371 | ||
|
|
149e63a272 | ||
|
|
d52a00a8fb | ||
|
|
f0dcec95dd | ||
|
|
2653931881 | ||
|
|
85207086e6 | ||
|
|
d0b0b02d6a | ||
|
|
34fa1def77 | ||
|
|
9f1aa958fc | ||
|
|
cdc5eefc69 | ||
|
|
c9588586c9 | ||
|
|
52735179d9 | ||
|
|
cef1fb9e80 | ||
|
|
c7e1964aae | ||
|
|
6d43883f77 | ||
|
|
f06f99dfc3 | ||
|
|
41e600be45 | ||
|
|
62a81c531a | ||
|
|
2cb1a626c4 | ||
|
|
18cde36b9d | ||
|
|
e05b6b78ad | ||
|
|
58c49deb06 | ||
|
|
4a41e88162 | ||
|
|
2e5becf48c | ||
|
|
4094339407 | ||
|
|
bf24949efb | ||
|
|
3b4549a7ee | ||
|
|
f194fdb132 | ||
|
|
2d274c46fa | ||
|
|
b61e9af750 | ||
|
|
a01362abad | ||
|
|
4387c662b6 | ||
|
|
ecdd027b3e | ||
|
|
2b0f572f4d |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.2.2</version>
|
||||
<version>12.3.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-12.2.2</tag>
|
||||
<tag>ebean-12.3.2</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -64,7 +64,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>config</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -99,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>4.7.3</version>
|
||||
<version>4.9.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -200,7 +200,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean.test</groupId>
|
||||
<artifactId>ebean-test-docker</artifactId>
|
||||
<version>3.1.3</version>
|
||||
<version>3.1.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -292,7 +292,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.2.2</version>
|
||||
<version>12.3.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
@@ -310,7 +310,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.1</version>
|
||||
<version>3.0.0-M4</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
|
||||
@@ -101,6 +101,22 @@ public class DB {
|
||||
// return originalPrimaryServer;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the ScriptRunner for the default database.
|
||||
* <p>
|
||||
* Useful to run SQL scripts that are resources. For example a test script
|
||||
* for inserting seed data for a particular test.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* DB.script().run("/scripts/test-script.sql")
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static ScriptRunner script() {
|
||||
return getDefault().script();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExpressionFactory from the default database.
|
||||
* <p>
|
||||
|
||||
@@ -24,7 +24,7 @@ import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Ebean will be Deprecated - please migrate to use DB.
|
||||
* Deprecated - please migrate to use <code>io.ebean.DB</code>.
|
||||
* <p>
|
||||
* Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
|
||||
* <p>
|
||||
@@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* <p>
|
||||
* The preference is to use DB and Database rather than Ebean and EbeanServer.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Ebean {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to <code>io.ebean.Database</code>.
|
||||
* Provides the API for fetching and saving beans to a particular Database.
|
||||
* <p>
|
||||
* Effectively this is an alias for {@link Database} which is now the new
|
||||
@@ -8,6 +9,7 @@ package io.ebean;
|
||||
* <p>
|
||||
* The preference is to use DB and Database rather than Ebean and EbeanServer.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface EbeanServer extends Database {
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to DatabaseFactory.
|
||||
* <p>
|
||||
* Creates EbeanServer instances.
|
||||
* <p>
|
||||
* This uses either a ServerConfig or properties in the ebean.properties file to
|
||||
@@ -28,6 +30,7 @@ import java.util.ServiceLoader;
|
||||
* convenient way of using the 'default/primary' EbeanServer.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
public class EbeanServerFactory {
|
||||
|
||||
|
||||
|
||||
@@ -36,10 +36,12 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
private transient BeanLoader beanLoader;
|
||||
|
||||
private volatile transient PreGetterCallback preGetterCallback;
|
||||
private transient PreGetterCallback preGetterCallback;
|
||||
|
||||
private String ebeanServerName;
|
||||
|
||||
private boolean deletedFromCollection;
|
||||
|
||||
/**
|
||||
* The actual entity bean that 'owns' this intercept.
|
||||
*/
|
||||
@@ -913,6 +915,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
private void preGetterCallback(int propertyIndex) {
|
||||
PreGetterCallback preGetterCallback = this.preGetterCallback;
|
||||
if (preGetterCallback != null) {
|
||||
preGetterCallback.preGetterTrigger(propertyIndex);
|
||||
}
|
||||
@@ -1137,6 +1140,17 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
this.sortOrder = sortOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the entity was deleted from a BeanCollection.
|
||||
*/
|
||||
public void setDeletedFromCollection(final boolean deletedFromCollection) {
|
||||
this.deletedFromCollection = deletedFromCollection;
|
||||
}
|
||||
|
||||
public boolean isOrphanDelete() {
|
||||
return deletedFromCollection && !isNew();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the load error that happened on this property.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -54,6 +56,11 @@ class ModifyHolder<E> implements Serializable {
|
||||
void modifyAddition(E bean) {
|
||||
if (bean != null) {
|
||||
touched = true;
|
||||
|
||||
if (bean instanceof EntityBean) {
|
||||
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(false);
|
||||
}
|
||||
|
||||
// If it is to delete then just remove the deletion
|
||||
if (!undoDeletion(bean)) {
|
||||
// Insert
|
||||
@@ -70,6 +77,11 @@ class ModifyHolder<E> implements Serializable {
|
||||
void modifyRemoval(Object bean) {
|
||||
if (bean != null) {
|
||||
touched = true;
|
||||
|
||||
if (bean instanceof EntityBean) {
|
||||
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(true);
|
||||
}
|
||||
|
||||
// If it is to be added then just remove the addition
|
||||
if (!undoAddition(bean)) {
|
||||
modifyDeletions.add((E) bean);
|
||||
|
||||
@@ -44,6 +44,8 @@ import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Deprecated - please migrate to <code>io.ebean.DatabaseConfig</code>.
|
||||
*
|
||||
* The configuration used for creating a Database.
|
||||
* <p>
|
||||
* Used to programmatically construct a Database and optionally register it
|
||||
@@ -80,6 +82,7 @@ import java.util.ServiceLoader;
|
||||
* @author rbygrave
|
||||
* @see DatabaseFactory
|
||||
*/
|
||||
@Deprecated
|
||||
public class ServerConfig {
|
||||
|
||||
/**
|
||||
@@ -331,18 +334,6 @@ public class ServerConfig {
|
||||
*/
|
||||
private ClassLoadConfig classLoadConfig = new ClassLoadConfig();
|
||||
|
||||
/**
|
||||
* Set to true if the DataSource uses autoCommit.
|
||||
* <p>
|
||||
* Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
private boolean autoCommitMode;
|
||||
|
||||
/**
|
||||
* Set to true if transaction begin should be started with explicit statement.
|
||||
*/
|
||||
private boolean explicitTransactionBeginMode;
|
||||
|
||||
/**
|
||||
* The data source JNDI name if using a JNDI DataSource.
|
||||
*/
|
||||
@@ -475,6 +466,11 @@ public class ServerConfig {
|
||||
|
||||
private String enabledL2Regions;
|
||||
|
||||
/**
|
||||
* Set to true to effectively disable L2 cache plugins.
|
||||
*/
|
||||
private boolean localOnlyL2Cache;
|
||||
|
||||
/**
|
||||
* Should the javax.validation.constraints.NotNull enforce a notNull column in DB.
|
||||
* If set to false, use io.ebean.annotation.NotNull or Column(nullable=true).
|
||||
@@ -1740,42 +1736,6 @@ public class ServerConfig {
|
||||
this.dataSourceJndiName = dataSourceJndiName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on. This indicates to Ebean to use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
public boolean isAutoCommitMode() {
|
||||
return autoCommitMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if autoCommit mode is on and Ebean should use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
public void setAutoCommitMode(boolean autoCommitMode) {
|
||||
this.autoCommitMode = autoCommitMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if transaction begin should be started with explicit statement.
|
||||
*/
|
||||
public boolean isExplicitTransactionBeginMode() {
|
||||
return explicitTransactionBeginMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if transaction begin should be started with explicit statement.
|
||||
* <p>
|
||||
* This works for H2 and Postgres but not for Oracle - only use this if you first name
|
||||
* is Daryl or you have explicitly talked to Rob about this feature.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is generally not expected to be turned on but instead allow transactions to start
|
||||
* implicitly which is generally the standard approach.
|
||||
* </p>
|
||||
*/
|
||||
public void setExplicitTransactionBeginMode(boolean explicitTransactionBeginMode) {
|
||||
this.explicitTransactionBeginMode = explicitTransactionBeginMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a value used to represent TRUE in the database.
|
||||
* <p>
|
||||
@@ -2799,7 +2759,7 @@ public class ServerConfig {
|
||||
*/
|
||||
protected void loadDataSourceSettings(PropertiesWrapper p) {
|
||||
dataSourceConfig.loadSettings(p.properties, name);
|
||||
readOnlyDataSourceConfig.loadSettings(p.properties, name);
|
||||
readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2860,10 +2820,9 @@ public class ServerConfig {
|
||||
collectQueryPlanThresholdMicros = p.getLong("collectQueryPlanThresholdMicros", collectQueryPlanThresholdMicros);
|
||||
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
|
||||
enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
|
||||
notifyL2CacheInForeground = p.getBoolean("notifyL2CacheInForeground", notifyL2CacheInForeground);
|
||||
explicitTransactionBeginMode = p.getBoolean("explicitTransactionBeginMode", explicitTransactionBeginMode);
|
||||
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
|
||||
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
|
||||
useJavaxValidationNotNull = p.getBoolean("useJavaxValidationNotNull", useJavaxValidationNotNull);
|
||||
autoReadOnlyDataSource = p.getBoolean("autoReadOnlyDataSource", autoReadOnlyDataSource);
|
||||
@@ -3100,6 +3059,20 @@ public class ServerConfig {
|
||||
this.disableL2Cache = disableL2Cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true to use local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
|
||||
*/
|
||||
public boolean isLocalOnlyL2Cache() {
|
||||
return localOnlyL2Cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the use of local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
|
||||
*/
|
||||
public void setLocalOnlyL2Cache(boolean localOnlyL2Cache) {
|
||||
this.localOnlyL2Cache = localOnlyL2Cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if we use javax.validation.constraints.NotNull
|
||||
*/
|
||||
|
||||
@@ -43,11 +43,8 @@ public abstract class AbstractDbEncrypt implements DbEncrypt {
|
||||
public DbEncryptFunction getDbEncryptFunction(int jdbcType) {
|
||||
switch (jdbcType) {
|
||||
case Types.VARCHAR:
|
||||
return varcharEncryptFunction;
|
||||
case Types.CLOB:
|
||||
return varcharEncryptFunction;
|
||||
case Types.CHAR:
|
||||
return varcharEncryptFunction;
|
||||
case Types.LONGVARCHAR:
|
||||
return varcharEncryptFunction;
|
||||
|
||||
|
||||
@@ -7,30 +7,18 @@ package io.ebean.config.dbplatform;
|
||||
* As an alternative to using DB encryption you can encrypt/decrypt in java via
|
||||
* a special ScalarType but this has the limitation that you can't include that
|
||||
* property in query where clauses.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface DbEncrypt {
|
||||
|
||||
// /**
|
||||
// * Return the SQL for decrypting a column returning a VARCHAR.
|
||||
// */
|
||||
// String getDecryptSql(String columnWithTableAlias);
|
||||
//
|
||||
// /**
|
||||
// * Return the DB function with bind variables used to encrypt a VARCHAR
|
||||
// * value.
|
||||
// */
|
||||
// String getEncryptBindSql();
|
||||
|
||||
/**
|
||||
* Return the DB encrypt function for the given JDBC type.
|
||||
*/
|
||||
DbEncryptFunction getDbEncryptFunction(int jdbcType);
|
||||
|
||||
/**
|
||||
* Return the DB type that encrypted Strings are stored in.
|
||||
* <p>
|
||||
* This is VARCHAR for MySql and VARBINARY for most others.
|
||||
* </p>
|
||||
*/
|
||||
int getEncryptDbType();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
|
||||
/**
|
||||
* Oracle 11 platform using rownum sql limiting.
|
||||
@@ -12,5 +13,6 @@ public class Oracle11Platform extends OraclePlatform {
|
||||
this.platform = Platform.ORACLE11;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.sqlLimiter = new OracleRownumSqlLimiter();
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
this.basicSqlLimiter = new BasicSqlAnsiLimiter();
|
||||
this.historySupport = new OracleDbHistorySupport();
|
||||
this.truncateTable = "truncate table %s cascade";
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
dbIdentity.setIdType(IdType.IDENTITY);
|
||||
dbIdentity.setSupportsSequence(true);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
|
||||
@@ -147,7 +147,7 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanCollect
|
||||
*
|
||||
* @param tenantId For multi-tenant lazy loading provide the tenantId to use.
|
||||
*/
|
||||
SpiTransaction createQueryTransaction(Object tenantId);
|
||||
SpiTransaction createReadOnlyTransaction(Object tenantId);
|
||||
|
||||
/**
|
||||
* An event from another server in the cluster used to notify local
|
||||
|
||||
@@ -458,7 +458,7 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
/**
|
||||
* Set the query to be a delete query.
|
||||
*/
|
||||
void setupForDeleteOrUpdate(boolean deleteRequest);
|
||||
void setupForDeleteOrUpdate();
|
||||
|
||||
/**
|
||||
* Set the query to be delete by ids due to cascading delete.
|
||||
|
||||
+10
-2
@@ -6,9 +6,9 @@ import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
/**
|
||||
* Oracle platform specific DDL.
|
||||
*/
|
||||
public class Oracle10Ddl extends PlatformDdl {
|
||||
public class OracleDdl extends PlatformDdl {
|
||||
|
||||
public Oracle10Ddl(DatabasePlatform platform) {
|
||||
public OracleDdl(DatabasePlatform platform) {
|
||||
super(platform);
|
||||
this.dropTableIfExists = "drop table ";
|
||||
this.dropSequenceIfExists = "drop sequence ";
|
||||
@@ -48,4 +48,12 @@ public class Oracle10Ddl extends PlatformDdl {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify and return the column definition for autoincrement or identity definition.
|
||||
*/
|
||||
@Override
|
||||
public String asIdentityColumn(String columnDefn, DdlIdentity identity) {
|
||||
return asIdentityStandardOptions(columnDefn, identity);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -195,7 +195,6 @@ public class PlatformDdl {
|
||||
* SQl2003 standard identity definition.
|
||||
*/
|
||||
protected String asIdentityStandardOptions(String columnDefn, DdlIdentity identity) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(columnDefn.length() + 60);
|
||||
sb.append(columnDefn).append(identity.optionGenerated());
|
||||
sb.append(identity.identityOptions(identityStartWith, identityIncrementBy, identityCache));
|
||||
|
||||
@@ -55,7 +55,7 @@ public class MCompoundUniqueConstraint {
|
||||
public MCompoundUniqueConstraint(AddUniqueConstraint change) {
|
||||
this.name = change.getConstraintName();
|
||||
this.columns = split(change.getColumnNames());
|
||||
this.oneToOne = change.isOneToOne();
|
||||
this.oneToOne = Boolean.TRUE.equals(change.isOneToOne());
|
||||
this.platforms = change.getPlatforms();
|
||||
this.nullableColumns = splitWithNull(change.getNullableColumns());
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class MCompoundUniqueConstraint {
|
||||
public MCompoundUniqueConstraint(UniqueConstraint uq) {
|
||||
this.name = uq.getName();
|
||||
this.columns = split(uq.getColumnNames());
|
||||
this.oneToOne = uq.isOneToOne();
|
||||
this.oneToOne = Boolean.TRUE.equals(uq.isOneToOne());
|
||||
this.platforms = uq.getPlatforms();
|
||||
this.nullableColumns = splitWithNull(uq.getNullableColumns());
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract class AbstractSqlQueryRequest {
|
||||
trans = server.currentServerTransaction();
|
||||
if (trans == null || !trans.isActive()) {
|
||||
// create a local readOnly transaction
|
||||
trans = server.createQueryTransaction(null);
|
||||
trans = server.createReadOnlyTransaction(null);
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ class DefaultBeanLoader {
|
||||
private List<?> executeQuery(LoadRequest loadRequest, SpiQuery<?> query) {
|
||||
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
|
||||
// MySql - we need a different transaction to execute the secondary query
|
||||
SpiTransaction extraTxn = server.createQueryTransaction(query.getTenantId());
|
||||
SpiTransaction extraTxn = server.createReadOnlyTransaction(query.getTenantId());
|
||||
try {
|
||||
return server.findList(query, extraTxn);
|
||||
} finally {
|
||||
|
||||
@@ -8,10 +8,6 @@ import io.ebean.config.TenantMode;
|
||||
import io.ebean.config.UnderscoreNamingConvention;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.datasource.DataSourceAlertFactory;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import io.ebean.datasource.DataSourceFactory;
|
||||
import io.ebean.datasource.DataSourcePoolListener;
|
||||
import io.ebean.service.SpiContainer;
|
||||
import io.ebeaninternal.api.SpiBackgroundExecutor;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
@@ -24,7 +20,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
@@ -39,13 +34,8 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final JndiDataSourceLookup jndiDataSourceFactory;
|
||||
|
||||
public DefaultContainer(ContainerConfig containerConfig) {
|
||||
|
||||
this.clusterManager = new ClusterManager(containerConfig);
|
||||
this.jndiDataSourceFactory = new JndiDataSourceLookup();
|
||||
|
||||
// register so that we can shutdown any Ebean wide
|
||||
// resources such as clustering
|
||||
ShutdownManager.registerContainer(this);
|
||||
@@ -230,75 +220,10 @@ public class DefaultContainer implements SpiContainer {
|
||||
* Set the DataSource if it has not already been set.
|
||||
*/
|
||||
private void setDataSource(ServerConfig config) {
|
||||
if (config.getDataSource() == null) {
|
||||
config.setDataSource(getDataSourceFromConfig(config, false));
|
||||
}
|
||||
if (config.getReadOnlyDataSource() == null && config.isAutoReadOnlyDataSource()) {
|
||||
config.setReadOnlyDataSource(getDataSourceFromConfig(config, true));
|
||||
}
|
||||
}
|
||||
|
||||
private DataSource getDataSourceFromConfig(ServerConfig config, boolean readOnly) {
|
||||
|
||||
if (isOfflineMode(config)) {
|
||||
logger.debug("... DbOffline using platform [{}]", DbOffline.getPlatform());
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!readOnly && config.getDataSourceJndiName() != null) {
|
||||
DataSource ds = jndiDataSourceFactory.lookup(config.getDataSourceJndiName());
|
||||
if (ds == null) {
|
||||
throw new PersistenceException("JNDI lookup for DataSource " + config.getDataSourceJndiName() + " returned null.");
|
||||
} else {
|
||||
return ds;
|
||||
}
|
||||
}
|
||||
|
||||
DataSourceConfig dsConfig = (readOnly) ? config.getReadOnlyDataSourceConfig() : config.getDataSourceConfig();
|
||||
if (dsConfig == null) {
|
||||
throw new PersistenceException("No DataSourceConfig defined for " + config.getName());
|
||||
}
|
||||
|
||||
if (dsConfig.isOffline()) {
|
||||
if (config.getDatabasePlatformName() == null) {
|
||||
throw new PersistenceException("You MUST specify a DatabasePlatformName on ServerConfig when offline");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
DataSourceFactory factory = DataSourceFactory.get();
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException("No DataSourceFactory service implementation found in class path."
|
||||
+ " Probably missing dependency to avaje-datasource?");
|
||||
}
|
||||
|
||||
DataSourceAlertFactory alertFactory = config.service(DataSourceAlertFactory.class);
|
||||
if (alertFactory != null) {
|
||||
dsConfig.setAlert(alertFactory.createAlert());
|
||||
}
|
||||
|
||||
attachListener(config, dsConfig);
|
||||
|
||||
if (readOnly) {
|
||||
// setup to use AutoCommit such that we skip explicit commit
|
||||
dsConfig.setAutoCommit(true);
|
||||
//dsConfig.setReadOnly(true);
|
||||
dsConfig.setDefaults(config.getDataSourceConfig());
|
||||
dsConfig.setIsolationLevel(config.getDataSourceConfig().getIsolationLevel());
|
||||
}
|
||||
String poolName = config.getName() + (readOnly ? "-ro" : "");
|
||||
return factory.createPool(poolName, dsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and attach a DataSourcePoolListener if it has been specified via properties and there is not one already attached.
|
||||
*/
|
||||
private void attachListener(ServerConfig config, DataSourceConfig dsConfig) {
|
||||
if (dsConfig.getListener() == null) {
|
||||
String poolListener = dsConfig.getPoolListener();
|
||||
if (poolListener != null) {
|
||||
dsConfig.setListener((DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener));
|
||||
}
|
||||
} else {
|
||||
InitDataSource.init(config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -331,7 +256,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
}
|
||||
|
||||
try (Connection connection = serverConfig.getDataSource().getConnection()) {
|
||||
if (!serverConfig.isAutoCommitMode() && connection.getAutoCommit()) {
|
||||
if (connection.getAutoCommit()) {
|
||||
logger.warn("DataSource [{}] has autoCommit defaulting to true!", serverConfig.getName());
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2322,8 +2322,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
return transactionManager.createQueryTransaction(tenantId);
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return transactionManager.createReadOnlyTransaction(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -102,7 +102,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
@SuppressWarnings("unchecked")
|
||||
public T readNextBean() throws SQLException {
|
||||
dataReader.resetColumnPosition();
|
||||
return (T)plan.readRow(dataReader);
|
||||
return (T) plan.readRow(dataReader);
|
||||
}
|
||||
|
||||
private DtoMappingRequest mappingRequest() throws SQLException {
|
||||
@@ -110,19 +110,29 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
}
|
||||
|
||||
private DtoColumn[] readMeta() throws SQLException {
|
||||
|
||||
ResultSetMetaData metaData = resultSet.getMetaData();
|
||||
int cols = metaData.getColumnCount();
|
||||
DtoColumn[] meta = new DtoColumn[cols];
|
||||
for (int i = 0; i < cols; i++) {
|
||||
int pos = i+1;
|
||||
int pos = i + 1;
|
||||
String columnLabel = metaData.getColumnLabel(pos);
|
||||
if (columnLabel == null) {
|
||||
columnLabel = metaData.getColumnName(pos);
|
||||
}
|
||||
meta[i] = new DtoColumn(columnLabel);
|
||||
meta[i] = new DtoColumn(parseColumn(columnLabel));
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
static String parseColumn(String columnLabel) {
|
||||
if (columnLabel.startsWith("_e_") || columnLabel.startsWith("_E_")) {
|
||||
// encrypted column alias in the form _e_<tableAlias>_<column>
|
||||
final int pos = columnLabel.indexOf("_", 3);
|
||||
if (pos > -1) {
|
||||
return columnLabel.substring(pos + 1);
|
||||
}
|
||||
}
|
||||
return columnLabel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.datasource.DataSourceAlertFactory;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import io.ebean.datasource.DataSourceFactory;
|
||||
import io.ebean.datasource.DataSourcePoolListener;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Initialise the main DataSource and read-only DataSource.
|
||||
*/
|
||||
class InitDataSource {
|
||||
|
||||
private final JndiDataSourceLookup jndiDataSourceFactory = new JndiDataSourceLookup();
|
||||
|
||||
private final ServerConfig config;
|
||||
|
||||
/**
|
||||
* Create and set the main DataSource and read-only DataSource.
|
||||
*/
|
||||
static void init(ServerConfig config) {
|
||||
new InitDataSource(config).initialise();
|
||||
}
|
||||
|
||||
InitDataSource(ServerConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private void initialise() {
|
||||
if (config.getDataSource() == null) {
|
||||
config.setDataSource(initDataSource());
|
||||
}
|
||||
if (config.getReadOnlyDataSource() == null) {
|
||||
config.setReadOnlyDataSource(initReadOnlyDataSource());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the "main" read write DataSource from configuration.
|
||||
*/
|
||||
private DataSource initDataSource() {
|
||||
final String jndiName = config.getDataSourceJndiName();
|
||||
if (jndiName != null) {
|
||||
return jndiDataSource(jndiName);
|
||||
}
|
||||
return createFromConfig(config.getDataSourceConfig(), false);
|
||||
}
|
||||
|
||||
private DataSource jndiDataSource(String jndiName) {
|
||||
DataSource ds = jndiDataSourceFactory.lookup(jndiName);
|
||||
if (ds == null) {
|
||||
throw new PersistenceException("JNDI lookup for DataSource " + jndiName + " returned null.");
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the "read only" DataSource from configuration.
|
||||
*/
|
||||
private DataSource initReadOnlyDataSource() {
|
||||
DataSourceConfig roConfig = readOnlyConfig();
|
||||
return roConfig == null ? null : createFromConfig(roConfig, true);
|
||||
}
|
||||
|
||||
DataSourceConfig readOnlyConfig() {
|
||||
DataSourceConfig roConfig = config.getReadOnlyDataSourceConfig();
|
||||
if (roConfig == null) {
|
||||
// it has explicitly been set to null, not expected but ok
|
||||
return null;
|
||||
}
|
||||
if (urlSet(roConfig.getUrl())) {
|
||||
return roConfig;
|
||||
}
|
||||
// convenient alternate place to set the read-only url
|
||||
final String readOnlyUrl = config.getDataSourceConfig().getReadOnlyUrl();
|
||||
if (urlSet(readOnlyUrl)) {
|
||||
roConfig.setUrl(readOnlyUrl);
|
||||
return roConfig;
|
||||
}
|
||||
if (config.isAutoReadOnlyDataSource()) {
|
||||
roConfig.setUrl(null); // blank out in case it is "none"
|
||||
return roConfig;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean urlSet(String url) {
|
||||
return url != null && !"none".equalsIgnoreCase(url) && !url.trim().isEmpty();
|
||||
}
|
||||
|
||||
private DataSource createFromConfig(DataSourceConfig dsConfig, boolean readOnly) {
|
||||
if (dsConfig == null) {
|
||||
throw new PersistenceException("No DataSourceConfig defined for " + config.getName());
|
||||
}
|
||||
if (dsConfig.isOffline()) {
|
||||
if (config.getDatabasePlatformName() == null) {
|
||||
throw new PersistenceException("You MUST specify a DatabasePlatformName on ServerConfig when offline");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
attachAlert(dsConfig);
|
||||
attachListener(dsConfig);
|
||||
|
||||
if (readOnly) {
|
||||
// setup to use AutoCommit such that we skip explicit commit
|
||||
dsConfig.setAutoCommit(true);
|
||||
dsConfig.setReadOnly(true);
|
||||
dsConfig.setDefaults(config.getDataSourceConfig());
|
||||
dsConfig.setIsolationLevel(config.getDataSourceConfig().getIsolationLevel());
|
||||
}
|
||||
return create(dsConfig, readOnly);
|
||||
}
|
||||
|
||||
private DataSource create(DataSourceConfig dsConfig, boolean readOnly) {
|
||||
DataSourceFactory factory = DataSourceFactory.get();
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException("No DataSourceFactory service implementation found in class path. Missing dependency to ebean-datasource?");
|
||||
}
|
||||
String poolName = config.getName() + (readOnly ? "-ro" : "");
|
||||
return factory.createPool(poolName, dsConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach DataSourceAlert via service loader if present.
|
||||
*/
|
||||
private void attachAlert(DataSourceConfig dsConfig) {
|
||||
DataSourceAlertFactory alertFactory = config.service(DataSourceAlertFactory.class);
|
||||
if (alertFactory != null) {
|
||||
dsConfig.setAlert(alertFactory.createAlert());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and attach a DataSourcePoolListener if it has been specified via properties and there is not one already attached.
|
||||
*/
|
||||
private void attachListener(DataSourceConfig dsConfig) {
|
||||
if (dsConfig.getListener() == null) {
|
||||
String poolListener = dsConfig.getPoolListener();
|
||||
if (poolListener != null) {
|
||||
dsConfig.setListener((DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@ import io.ebean.config.ServerConfig;
|
||||
import io.ebean.config.SlowQueryListener;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbHistorySupport;
|
||||
import io.ebean.datasource.DataSourcePool;
|
||||
import io.ebean.event.changelog.ChangeLogListener;
|
||||
import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
@@ -45,10 +44,10 @@ import io.ebeaninternal.server.changelog.DefaultChangeLogPrepare;
|
||||
import io.ebeaninternal.server.changelog.DefaultChangeLogRegister;
|
||||
import io.ebeaninternal.server.cluster.ClusterManager;
|
||||
import io.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import io.ebeaninternal.server.core.timezone.CloneDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.LocalDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.MySqlDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.NoDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.OracleDataTimeZone;
|
||||
import io.ebeaninternal.server.core.timezone.SimpleDataTimeZone;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
@@ -78,12 +77,10 @@ import io.ebeaninternal.server.query.QueryPlanLoggerSqlServer;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditLogger;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditPrepare;
|
||||
import io.ebeaninternal.server.text.json.DJsonContext;
|
||||
import io.ebeaninternal.server.transaction.AutoCommitTransactionManager;
|
||||
import io.ebeaninternal.server.transaction.DataSourceSupplier;
|
||||
import io.ebeaninternal.server.transaction.DefaultProfileHandler;
|
||||
import io.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
|
||||
import io.ebeaninternal.server.transaction.DocStoreTransactionManager;
|
||||
import io.ebeaninternal.server.transaction.ExplicitTransactionManager;
|
||||
import io.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
|
||||
import io.ebeaninternal.server.transaction.JtaTransactionManager;
|
||||
import io.ebeaninternal.server.transaction.NoopProfileHandler;
|
||||
@@ -100,7 +97,6 @@ import io.ebeanservice.docstore.none.NoneDocStoreFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -450,12 +446,6 @@ public class InternalConfiguration {
|
||||
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
|
||||
tableModState, cacheNotify, clockService);
|
||||
|
||||
if (serverConfig.isExplicitTransactionBeginMode()) {
|
||||
return new ExplicitTransactionManager(options);
|
||||
}
|
||||
if (isAutoCommitMode()) {
|
||||
return new AutoCommitTransactionManager(options);
|
||||
}
|
||||
if (serverConfig.isDocStoreOnly()) {
|
||||
return new DocStoreTransactionManager(options);
|
||||
}
|
||||
@@ -492,18 +482,6 @@ public class InternalConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on.
|
||||
*/
|
||||
private boolean isAutoCommitMode() {
|
||||
if (serverConfig.isAutoCommitMode()) {
|
||||
// explicitly set
|
||||
return true;
|
||||
}
|
||||
DataSource dataSource = serverConfig.getDataSource();
|
||||
return dataSource instanceof DataSourcePool && ((DataSourcePool) dataSource).isAutoCommit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the TransactionScopeManager taking into account JTA or external transaction manager.
|
||||
*/
|
||||
@@ -529,12 +507,12 @@ public class InternalConfiguration {
|
||||
String tz = serverConfig.getDataTimeZone();
|
||||
if (tz == null) {
|
||||
if (isMySql(getPlatform())) {
|
||||
return new LocalDataTimeZone();
|
||||
return new MySqlDataTimeZone();
|
||||
}
|
||||
return new NoDataTimeZone();
|
||||
}
|
||||
if (getPlatform().base() == Platform.ORACLE) {
|
||||
return new CloneDataTimeZone(tz);
|
||||
return new OracleDataTimeZone(tz);
|
||||
} else {
|
||||
return new SimpleDataTimeZone(tz);
|
||||
}
|
||||
@@ -594,7 +572,10 @@ public class InternalConfiguration {
|
||||
}
|
||||
|
||||
private ServerCachePlugin initServerCachePlugin() {
|
||||
|
||||
if (serverConfig.isLocalOnlyL2Cache()) {
|
||||
localL2Caching = true;
|
||||
return new DefaultServerCachePlugin();
|
||||
}
|
||||
ServerCachePlugin plugin = serverConfig.getServerCachePlugin();
|
||||
if (plugin == null) {
|
||||
ServiceLoader<ServerCachePlugin> cacheFactories = ServiceLoader.load(ServerCachePlugin.class);
|
||||
|
||||
@@ -286,7 +286,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
} else {
|
||||
// create an implicit transaction to execute this query
|
||||
// potentially using read-only DataSource with autoCommit
|
||||
transaction = ebeanServer.createQueryTransaction(query.getTenantId());
|
||||
transaction = ebeanServer.createReadOnlyTransaction(query.getTenantId());
|
||||
}
|
||||
createdTransaction = true;
|
||||
}
|
||||
|
||||
@@ -1399,7 +1399,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
changes.put(property.getName(), val);
|
||||
if (property.isNaturalKey()) {
|
||||
updateNaturalKey = true;
|
||||
changeSet.addNaturalKeyPut(beanDescriptor, key, val.toString());
|
||||
String valStr = (val == null) ? null : val.toString();
|
||||
changeSet.addNaturalKeyPut(beanDescriptor, key, valStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import io.ebeaninternal.dbmigration.ddlgeneration.platform.HanaColumnStoreDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.HsqldbDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.MySqlDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.NuoDbDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.Oracle10Ddl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.OracleDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.PlatformDdl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.Postgres9Ddl;
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.PostgresDdl;
|
||||
@@ -40,7 +40,7 @@ public class PlatformDdlBuilder {
|
||||
return new NuoDbDdl(platform);
|
||||
case ORACLE:
|
||||
case ORACLE11:
|
||||
return new Oracle10Ddl(platform);
|
||||
return new OracleDdl(platform);
|
||||
case SQLITE:
|
||||
return new SQLiteDdl(platform);
|
||||
case POSTGRES9:
|
||||
|
||||
+5
-5
@@ -5,11 +5,11 @@ import java.util.Calendar;
|
||||
/**
|
||||
* Implementation of DataTimeZone when single Calendar instance is used with local timezone.
|
||||
*/
|
||||
public class LocalDataTimeZone implements DataTimeZone {
|
||||
public class MySqlDataTimeZone implements DataTimeZone {
|
||||
|
||||
protected final Calendar zone;
|
||||
|
||||
public LocalDataTimeZone() {
|
||||
public MySqlDataTimeZone() {
|
||||
this.zone = Calendar.getInstance();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class LocalDataTimeZone implements DataTimeZone {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Calendar getDateTimeZone() {
|
||||
return zone; // workaround for MySQL. TODO: rename class to MySqlDataTimeZone!?
|
||||
}
|
||||
public Calendar getDateTimeZone() {
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,9 +8,9 @@ import java.util.Calendar;
|
||||
* Used with Oracle JDBC driver as that wants to mutate the Calender.
|
||||
* </p>
|
||||
*/
|
||||
public class CloneDataTimeZone extends SimpleDataTimeZone {
|
||||
public class OracleDataTimeZone extends SimpleDataTimeZone {
|
||||
|
||||
public CloneDataTimeZone(String zoneId) {
|
||||
public OracleDataTimeZone(String zoneId) {
|
||||
super(zoneId);
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanTable;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployIdentityMode;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployOrderColumn;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployIdentityMode;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
@@ -357,7 +357,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* Deploy returning the asOfTableMap (which is required by the SQL builders).
|
||||
*/
|
||||
public Map<String, String> deploy(List<XmEbean> mappings) {
|
||||
|
||||
try {
|
||||
createListeners();
|
||||
readEntityDeploymentInitial();
|
||||
@@ -365,7 +364,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
readEntityBeanTable();
|
||||
readEntityDeploymentAssociations();
|
||||
readInheritedIdGenerators();
|
||||
setProfileIds();
|
||||
// creates the BeanDescriptors
|
||||
readEntityRelationships();
|
||||
|
||||
@@ -375,9 +373,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
initialiseAll();
|
||||
readForeignKeys();
|
||||
|
||||
readTableToDescriptor();
|
||||
|
||||
logStatus();
|
||||
|
||||
// clear collections we no longer need
|
||||
@@ -778,18 +774,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set profileIds based on descriptor full name order.
|
||||
*/
|
||||
private void setProfileIds() {
|
||||
|
||||
List<? extends DeployBeanDescriptor<?>> deployDescriptors = deployInfoMap.values().stream()
|
||||
.map(DeployBeanInfo::getDescriptor)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
deployDescriptors.sort(Comparator.comparing(DeployBeanDescriptor::getFullName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the BeanTable from the deployment information gathered so far.
|
||||
*/
|
||||
@@ -1004,6 +988,14 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
orderProperty.setDbRead(true);
|
||||
orderProperty.setOwningType(targetDesc.getBeanType());
|
||||
|
||||
final InheritInfo targetInheritInfo = targetDesc.getInheritInfo();
|
||||
if (targetInheritInfo != null) {
|
||||
for (InheritInfo child : targetInheritInfo.getChildren()) {
|
||||
final DeployBeanDescriptor<?> childDescriptor = deployInfoMap.get(child.getType()).getDescriptor();
|
||||
childDescriptor.setOrderColumn(orderProperty);
|
||||
}
|
||||
}
|
||||
|
||||
targetDesc.setOrderColumn(orderProperty);
|
||||
}
|
||||
|
||||
|
||||
@@ -542,12 +542,11 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
return dbEncryptFunction.getDecryptSql(propertyName);
|
||||
}
|
||||
|
||||
public String getDecryptSql() {
|
||||
return dbEncryptFunction.getDecryptSql(this.getDbColumn());
|
||||
}
|
||||
|
||||
private String getDecryptSql(String tableAlias) {
|
||||
return dbEncryptFunction.getDecryptSql(tableAlias + "." + this.getDbColumn());
|
||||
/**
|
||||
* Return the SQL for the column including decryption function and column alias.
|
||||
*/
|
||||
private String getDecryptSqlWithColumnAlias(String tableAlias) {
|
||||
return dbEncryptFunction.getDecryptSql(tableAlias + "." + this.getDbColumn()) + " _e_" + tableAlias + "_" + this.getDbColumn();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -600,8 +599,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
if (dbEncrypted) {
|
||||
String decryptSql = getDecryptSql(ctx.peekTableAlias());
|
||||
ctx.appendRawColumn(decryptSql);
|
||||
ctx.appendRawColumn(getDecryptSqlWithColumnAlias(ctx.peekTableAlias()));
|
||||
ctx.addEncryptedProp(this);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -36,7 +36,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private final ScalarType scalarType;
|
||||
|
||||
|
||||
public IdBinderSimple(BeanProperty idProperty, MultiValueBind multiValueBind) {
|
||||
this.idProperty = idProperty;
|
||||
this.scalarType = idProperty.getScalarType();
|
||||
@@ -71,7 +70,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
|
||||
idProperty.buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
|
||||
@@ -218,7 +216,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
sb.append(prefix);
|
||||
@@ -231,7 +228,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
sb.append(prefix);
|
||||
@@ -243,7 +239,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object convertId(Object idValue) {
|
||||
|
||||
if (!idValue.getClass().equals(expectedType)) {
|
||||
return scalarType.toBeanType(idValue);
|
||||
}
|
||||
@@ -252,12 +247,10 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object convertSetId(Object idValue, EntityBean bean) {
|
||||
|
||||
if (!idValue.getClass().equals(expectedType)) {
|
||||
idValue = scalarType.toBeanType(idValue);
|
||||
}
|
||||
if (bean != null) {
|
||||
// support PropertyChangeSupport
|
||||
idProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
return idValue;
|
||||
|
||||
@@ -104,16 +104,18 @@ public class IdInExpression extends NonPrepareExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
|
||||
BeanDescriptor<?> descriptor = request.getBeanDescriptor();
|
||||
IdBinder idBinder = descriptor.getIdBinder();
|
||||
if (idCollection.isEmpty()) {
|
||||
request.append(SQL_FALSE); // append false for this stage
|
||||
} else {
|
||||
request.append(descriptor.getIdBinderInLHSSql());
|
||||
String inClause = idBinder.getIdInValueExpr(false, idCollection.size());
|
||||
request.append(inClause);
|
||||
if (idBinder.isComplexId()) {
|
||||
request.append(descriptor.getIdBinderInLHSSql());
|
||||
request.append(idBinder.getIdInValueExpr(false, idCollection.size()));
|
||||
} else {
|
||||
request.append(idBinder.getBeanProperty().getName());
|
||||
request.appendInExpression(false, idCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
/**
|
||||
* Create with a given statement.
|
||||
*/
|
||||
public BatchedPstmt(PreparedStatement pstmt, boolean isGenKeys, String sql, SpiTransaction transaction) {
|
||||
public BatchedPstmt(PreparedStatement pstmt, boolean isGenKeys, String sql, SpiTransaction transaction) throws SQLException {
|
||||
this.pstmt = pstmt;
|
||||
this.pstmt.clearBatch();
|
||||
this.isGenKeys = isGenKeys;
|
||||
this.sql = sql;
|
||||
this.transaction = transaction;
|
||||
@@ -92,7 +93,7 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
private void flushStatementBatch() throws SQLException {
|
||||
final int[] rows = pstmt.executeBatch();
|
||||
if (rows.length != list.size()) {
|
||||
throw new IllegalStateException("Invalid state? rows:" + rows.length + " != " + list.size());
|
||||
throw new IllegalStateException("Invalid state on executeBatch, rows:" + rows.length + " != " + list.size());
|
||||
}
|
||||
for (BatchPostExecute item : list) {
|
||||
item.postExecute();
|
||||
@@ -156,8 +157,7 @@ public class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
try {
|
||||
results = pstmt.executeBatch();
|
||||
if (results.length != list.size()) {
|
||||
String s = "results array error " + results.length + " " + list.size();
|
||||
throw new SQLException(s);
|
||||
throw new SQLException("Invalid state on executeBatch, rows:" + results.length + " != " + list.size());
|
||||
}
|
||||
// check for concurrency exceptions...
|
||||
for (int i = 0; i < results.length; i++) {
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.ebeaninternal.server.persist.DmlUtil.isNullOrZero;
|
||||
@@ -68,10 +69,9 @@ public class SaveManyBeans extends SaveManyBase {
|
||||
resetModifyState();
|
||||
}
|
||||
} else {
|
||||
if (isModifyListenMode()) {
|
||||
// delete any removed beans via private owned. Needs to occur before
|
||||
// a 'deleteMissingChildren' statement occurs
|
||||
removeAssocManyPrivateOwned();
|
||||
if (isModifyListenMode() || many.hasOrderColumn()) {
|
||||
// delete any removed beans / orphans
|
||||
removeAssocManyOrphans();
|
||||
}
|
||||
if (cascade) {
|
||||
// potentially deletes 'missing children' for 'stateless update'
|
||||
@@ -108,7 +108,7 @@ public class SaveManyBeans extends SaveManyBase {
|
||||
BeanProperty orderColumn = null;
|
||||
boolean hasOrderColumn = many.hasOrderColumn();
|
||||
if (hasOrderColumn) {
|
||||
if (!insertedParent && canSkipForOrderColumn()) {
|
||||
if (!insertedParent && canSkipForOrderColumn() && saveRecurseSkippable) {
|
||||
return;
|
||||
}
|
||||
orderColumn = targetDescriptor.getOrderColumn();
|
||||
@@ -157,7 +157,7 @@ public class SaveManyBeans extends SaveManyBase {
|
||||
if (many.hasJoinTable()) {
|
||||
skipSavingThisBean = targetDescriptor.isReference(ebi);
|
||||
} else {
|
||||
if (orderColumn != null) {
|
||||
if (orderColumn != null && !Objects.equals(sortOrder, orderColumn.getValue(detail))) {
|
||||
orderColumn.setValue(detail, sortOrder);
|
||||
ebi.setDirty(true);
|
||||
}
|
||||
@@ -178,6 +178,11 @@ public class SaveManyBeans extends SaveManyBase {
|
||||
|
||||
if (!skipSavingThisBean) {
|
||||
persister.saveRecurse(detail, transaction, parentBean, request.getFlags());
|
||||
if (many.hasOrderColumn()) {
|
||||
// Clear the bean from the PersistenceContext (L1 cache), because the order of referenced beans might have changed
|
||||
final BeanDescriptor<?> beanDescriptor = many.getBeanDescriptor();
|
||||
beanDescriptor.contextClear(transaction.getPersistenceContext(), beanDescriptor.getId(parentBean));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -334,20 +339,25 @@ public class SaveManyBeans extends SaveManyBase {
|
||||
transaction.depth(-1);
|
||||
}
|
||||
|
||||
private void removeAssocManyPrivateOwned() {
|
||||
|
||||
private void removeAssocManyOrphans() {
|
||||
// check that the list is not null and if it is a BeanCollection
|
||||
// check that is has been populated (don't trigger lazy loading)
|
||||
if (value instanceof BeanCollection<?>) {
|
||||
|
||||
BeanCollection<?> c = (BeanCollection<?>) value;
|
||||
Set<?> modifyRemovals = c.getModifyRemovals();
|
||||
modifyListenReset(c);
|
||||
if (insertedParent) {
|
||||
// after insert set the modify listening mode for private owned etc
|
||||
c.setModifyListening(many.getModifyListenMode());
|
||||
}
|
||||
// We must not reset when we still have to update other entities in the collection and set their new orderColumn value
|
||||
if (!many.hasOrderColumn()) {
|
||||
c.modifyReset();
|
||||
}
|
||||
if (modifyRemovals != null && !modifyRemovals.isEmpty()) {
|
||||
for (Object removedBean : modifyRemovals) {
|
||||
if (removedBean instanceof EntityBean) {
|
||||
EntityBean eb = (EntityBean) removedBean;
|
||||
if (!eb._ebean_getIntercept().isNew()) {
|
||||
if (eb._ebean_intercept().isOrphanDelete()) {
|
||||
// only delete if the bean was loaded meaning that it is known to exist in the DB
|
||||
persister.deleteRequest(persister.createDeleteRemoved(removedBean, transaction, request.getFlags()));
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class CQueryBuilder {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
String rootTableAlias = query.getAlias();
|
||||
query.setupForDeleteOrUpdate(deleteRequest);
|
||||
query.setupForDeleteOrUpdate();
|
||||
|
||||
CQueryPredicates predicates = new CQueryPredicates(binder, request);
|
||||
CQueryPlan queryPlan = request.getQueryPlan();
|
||||
@@ -125,7 +125,7 @@ class CQueryBuilder {
|
||||
private <T> String buildDeleteSql(OrmQueryRequest<T> request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) {
|
||||
|
||||
String alias = alias(rootTableAlias);
|
||||
if (sqlTree.noJoins()) {
|
||||
if (sqlTree.noJoins() && !request.getQuery().hasMaxRowsOrFirstRow()) {
|
||||
if (dbPlatform.isSupportsDeleteTableAlias()) {
|
||||
// delete from table <alias> ...
|
||||
return aliasReplace(buildSqlDelete("delete", request, predicates, sqlTree).getSql(), alias);
|
||||
|
||||
@@ -328,11 +328,9 @@ class DefaultDbSqlContext implements DbSqlContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendRawColumn(String rawcolumnWithTableAlias) {
|
||||
public void appendRawColumn(String rawColumnWithAlias) {
|
||||
sb.append(COMMA);
|
||||
sb.append(rawcolumnWithTableAlias);
|
||||
|
||||
appendColumnAlias();
|
||||
sb.append(rawColumnWithAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -684,13 +684,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* Setup to be a delete or update query.
|
||||
*/
|
||||
@Override
|
||||
public void setupForDeleteOrUpdate(boolean deleteRequest) {
|
||||
// unset any paging and select on the id in the case where the query
|
||||
// includes joins and we use - delete ... where id in (...)
|
||||
if (deleteRequest) {
|
||||
maxRows = 0;
|
||||
}
|
||||
firstRow = 0;
|
||||
public void setupForDeleteOrUpdate() {
|
||||
forUpdate = null;
|
||||
rootTableAlias = "${RTA}"; // alias we remove later
|
||||
setSelectId();
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* AutoCommit friendly Transaction.
|
||||
* <p>
|
||||
* Skips actual commit and rollback as these are performed automatically.
|
||||
*/
|
||||
public class AutoCommitJdbcTransaction extends JdbcTransaction {
|
||||
|
||||
public AutoCommitJdbcTransaction(String id, boolean explicit, Connection connection, TransactionManager manager) {
|
||||
super(id, explicit, connection, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkAutoCommit(Connection connection) {
|
||||
// do nothing as autoCommit
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRollback() {
|
||||
// do nothing as autoCommit
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCommit() {
|
||||
// do nothing as autoCommit
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* AutoCommit based TransactionManager.
|
||||
* <p>
|
||||
* Intended to be used if when autoCommit mode is desired.
|
||||
*/
|
||||
public class AutoCommitTransactionManager extends TransactionManager {
|
||||
|
||||
public AutoCommitTransactionManager(TransactionManagerOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an autoCommit based Transaction.
|
||||
*/
|
||||
@Override
|
||||
protected SpiTransaction createTransaction(boolean explicit, Connection c) {
|
||||
return new AutoCommitJdbcTransaction(nextTxnId(), explicit, c, this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ public class DocStoreTransactionManager extends TransactionManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return new DocStoreOnlyTransaction("", false, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* This only works for Postgres and H2 (and doesn't work for Oracle).
|
||||
* <p>
|
||||
* Uses explicit begin statement to start the transactions.
|
||||
*/
|
||||
public class ExplicitJdbcTransaction extends JdbcTransaction {
|
||||
|
||||
public ExplicitJdbcTransaction(String id, boolean explicit, Connection connection, TransactionManager manager) {
|
||||
super(id, explicit, connection, manager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkAutoCommit(Connection connection) throws SQLException {
|
||||
// begin the transaction explicitly
|
||||
executeStatement("begin");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performRollback() throws SQLException {
|
||||
// Postgres needs this explicit rollback statement when used with AutoCommit=true
|
||||
executeStatement("rollback");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void performCommit() throws SQLException {
|
||||
// Postgres needs this explicit commit statement when used with AutoCommit=true
|
||||
executeStatement("commit");
|
||||
}
|
||||
|
||||
private void executeStatement(String statement) throws SQLException {
|
||||
try (PreparedStatement stmt = connection.prepareStatement(statement)) {
|
||||
stmt.execute();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package io.ebeaninternal.server.transaction;
|
||||
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
/**
|
||||
* TransactionManager where the transactions start with explicit "begin" statement.
|
||||
*/
|
||||
public class ExplicitTransactionManager extends TransactionManager {
|
||||
|
||||
public ExplicitTransactionManager(TransactionManagerOptions options) {
|
||||
super(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ExplicitJdbcTransaction.
|
||||
*/
|
||||
@Override
|
||||
protected SpiTransaction createTransaction(boolean explicit, Connection c) {
|
||||
return new ExplicitJdbcTransaction(nextTxnId(), explicit, c, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the initialise of OnQueryOnly with the intention not to use CLOSE with ExplicitJdbcTransaction.
|
||||
*/
|
||||
@Override
|
||||
protected DatabasePlatform.OnQueryOnly initOnQueryOnly(DatabasePlatform.OnQueryOnly dbPlatformOnQueryOnly) {
|
||||
|
||||
// first check for a system property 'override'
|
||||
String systemPropertyValue = System.getProperty("ebean.transaction.onqueryonly");
|
||||
if (systemPropertyValue != null) {
|
||||
return DatabasePlatform.OnQueryOnly.valueOf(systemPropertyValue.trim().toUpperCase());
|
||||
}
|
||||
|
||||
// default to rollback if not defined on the platform
|
||||
return dbPlatformOnQueryOnly == null ? DatabasePlatform.OnQueryOnly.ROLLBACK : dbPlatformOnQueryOnly;
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,8 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
|
||||
private final long startNanos;
|
||||
|
||||
private ProfileLocation profileLocation;
|
||||
|
||||
/**
|
||||
* Create without a tenantId.
|
||||
*/
|
||||
@@ -125,12 +127,12 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
|
||||
@Override
|
||||
public void setProfileLocation(ProfileLocation profileLocation) {
|
||||
throw new IllegalStateException(notExpectedMessage);
|
||||
this.profileLocation = profileLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileLocation getProfileLocation() {
|
||||
return null;
|
||||
return profileLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,7 +23,7 @@ abstract class TransactionFactory {
|
||||
*
|
||||
* @param tenantId The tenantId for lazy loading queries.
|
||||
*/
|
||||
abstract SpiTransaction createQueryTransaction(Object tenantId);
|
||||
abstract SpiTransaction createReadOnlyTransaction(Object tenantId);
|
||||
|
||||
/**
|
||||
* Return a new transaction.
|
||||
|
||||
@@ -21,7 +21,7 @@ class TransactionFactoryBasic extends TransactionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class TransactionFactoryBasicWithRead extends TransactionFactoryBasic {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
|
||||
@@ -24,7 +24,7 @@ class TransactionFactoryTenant extends TransactionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return create(false, tenantId);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ class TransactionFactoryTenantWithRead extends TransactionFactoryTenant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
|
||||
Connection connection = null;
|
||||
try {
|
||||
|
||||
@@ -356,6 +356,14 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
return t;
|
||||
}
|
||||
|
||||
private SpiTransaction createTransaction(TxScope txScope) {
|
||||
if (txScope.isReadonly()) {
|
||||
return createReadOnlyTransaction(null);
|
||||
} else {
|
||||
return createTransaction(true, txScope.getIsolationLevel());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Transaction.
|
||||
*/
|
||||
@@ -366,8 +374,8 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
/**
|
||||
* Create a new Transaction for query only purposes (can use read only datasource).
|
||||
*/
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
return transactionFactory.createQueryTransaction(tenantId);
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return transactionFactory.createReadOnlyTransaction(tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -669,7 +677,7 @@ public class TransactionManager implements SpiTransactionManager {
|
||||
transaction = NoTransaction.INSTANCE;
|
||||
break;
|
||||
default:
|
||||
transaction = createTransaction(true, txScope.getIsolationLevel());
|
||||
transaction = createTransaction(txScope);
|
||||
initNewTransaction(transaction, txScope);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.function.Predicate;
|
||||
public class NoneDocStore implements DocumentStore {
|
||||
|
||||
public static IllegalStateException implementationNotInClassPath() {
|
||||
throw new IllegalStateException("DocStore implementation not included in the classPath. You need to add the maven dependency for avaje-ebeanorm-elastic");
|
||||
throw new IllegalStateException("DocStore implementation not included in the classPath. You need to add the maven dependency for io.ebean:ebean-elastic");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -22,8 +22,8 @@ public class EbeanServer_refresh {
|
||||
map.put("tableName", "e_basic");
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
server.script().run("/scripts/test-script.sql");
|
||||
server.script().run("/scripts/test-script-2.sql", map);
|
||||
DB.script().run("/scripts/test-script.sql");
|
||||
DB.script().run("/scripts/test-script-2.sql", map);
|
||||
server.script().run(this.getClass().getResource("/scripts/test-script.sql"));
|
||||
server.script().run(this.getClass().getResource("/scripts/test-script-2.sql"), map);
|
||||
|
||||
|
||||
@@ -98,6 +98,31 @@ public class UpdateQueryTest extends BaseTestCase {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = status where id > ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void query_asUpdate_idIn() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
int rows = server().find(Customer.class)
|
||||
.where()
|
||||
.idIn(1000, 1001, 1002)
|
||||
.asUpdate()
|
||||
.setRaw("status = ?", "A")
|
||||
.setLabel("asUpdateByIds")
|
||||
.update();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(rows).isEqualTo(0);
|
||||
|
||||
if (isPostgres()) {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = ? where id = any(?)");
|
||||
} else {
|
||||
assertSql(sql.get(0)).contains("update o_customer set status = ? where id in (?,?,?,?,?)"); // bind padding to 5
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update_withTransactionBatch() {
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createQueryTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -6,16 +6,16 @@ import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class Oracle10DdlTest {
|
||||
public class OracleDdlTest {
|
||||
|
||||
Oracle10Ddl create() {
|
||||
return new Oracle10Ddl(new OraclePlatform());
|
||||
OracleDdl create() {
|
||||
return new OracleDdl(new OraclePlatform());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_expectEmtpy_when_nullRestrictSetDefault() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
OracleDdl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, oracle.withDefault(null));
|
||||
@@ -34,7 +34,7 @@ public class Oracle10DdlTest {
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_setNull() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
OracleDdl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.SET_NULL);
|
||||
@@ -44,7 +44,7 @@ public class Oracle10DdlTest {
|
||||
@Test
|
||||
public void appendForeignKeyOnDelete_cascade() {
|
||||
|
||||
Oracle10Ddl oracle = create();
|
||||
OracleDdl oracle = create();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
oracle.appendForeignKeyOnDelete(sb, ConstraintMode.CASCADE);
|
||||
+1
-1
@@ -267,7 +267,7 @@ public class PlatformDdl_AlterColumnTest {
|
||||
@Test
|
||||
public void useIdentityType_oracle() {
|
||||
|
||||
assertEquals(oraDdl.useIdentityType(null), IdType.SEQUENCE);
|
||||
assertEquals(oraDdl.useIdentityType(null), IdType.IDENTITY);
|
||||
assertEquals(oraDdl.useIdentityType(IdType.SEQUENCE), IdType.SEQUENCE);
|
||||
assertEquals(oraDdl.useIdentityType(IdType.IDENTITY), IdType.IDENTITY);
|
||||
assertEquals(oraDdl.useIdentityType(IdType.GENERATOR), IdType.GENERATOR);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class DtoQueryRequestTest {
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
|
||||
assertEquals("foo", DtoQueryRequest.parseColumn("foo"));
|
||||
assertEquals("bar", DtoQueryRequest.parseColumn("_e_t0_bar"));
|
||||
assertEquals("BAR", DtoQueryRequest.parseColumn("_E_T0_BAR"));
|
||||
assertEquals("baz", DtoQueryRequest.parseColumn("_e_t42_baz"));
|
||||
assertEquals("BAZ", DtoQueryRequest.parseColumn("_E_T42_BAZ"));
|
||||
|
||||
assertEquals("e_t42_nope", DtoQueryRequest.parseColumn("e_t42_nope"));
|
||||
assertEquals("_f_t42_nope", DtoQueryRequest.parseColumn("_f_t42_nope"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class InitDataSourceTest {
|
||||
|
||||
private ServerConfig newConfig(String readOnlyUrl) {
|
||||
ServerConfig config = new ServerConfig();
|
||||
DataSourceConfig roConfig = new DataSourceConfig();
|
||||
roConfig.setUrl(readOnlyUrl);
|
||||
config.setReadOnlyDataSourceConfig(roConfig);
|
||||
return config;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_nullByDefault() {
|
||||
InitDataSource init = new InitDataSource(new ServerConfig());
|
||||
assertNull(init.readOnlyConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_null_whenSetNullExplicitly() {
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setReadOnlyDataSourceConfig(null);
|
||||
|
||||
assertNull(new InitDataSource(config).readOnlyConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_null_whenSetNullExplicitly_2() {
|
||||
assertNull(new InitDataSource(newConfig(null)).readOnlyConfig());
|
||||
assertNull(new InitDataSource(newConfig("")).readOnlyConfig());
|
||||
assertNull(new InitDataSource(newConfig(" ")).readOnlyConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_null_whenValueNONE() {
|
||||
assertNull(new InitDataSource(newConfig("none")).readOnlyConfig());
|
||||
assertNull(new InitDataSource(newConfig("None")).readOnlyConfig());
|
||||
assertNull(new InitDataSource(newConfig("NONE")).readOnlyConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_autoReadOnlyDataSource() {
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.setAutoReadOnlyDataSource(true);
|
||||
|
||||
assertNotNull(new InitDataSource(config).readOnlyConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_autoReadOnlyDataSource_expect_setToNull() {
|
||||
ServerConfig config = newConfig("none");
|
||||
config.setAutoReadOnlyDataSource(true);
|
||||
|
||||
final DataSourceConfig readOnlyConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNull(readOnlyConfig.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_urlSet() {
|
||||
ServerConfig config = newConfig("foo");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNotNull(roConfig);
|
||||
assertEquals("foo", roConfig.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_readOnlyUrlSetOnMain() {
|
||||
ServerConfig config = newConfig(null);
|
||||
// alternate location to set read-only url for developer convenience
|
||||
config.getDataSourceConfig().setReadOnlyUrl("bar");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNotNull(roConfig);
|
||||
assertEquals("bar", roConfig.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_readOnlyUrlSetOnMain_withNone() {
|
||||
ServerConfig config = newConfig("None");
|
||||
// alternate location to set read-only url for developer convenience
|
||||
config.getDataSourceConfig().setReadOnlyUrl("bar");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNotNull(roConfig);
|
||||
assertEquals("bar", roConfig.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_bothReadOnlyUrlsSet() {
|
||||
ServerConfig config = newConfig("one");
|
||||
config.getDataSourceConfig().setReadOnlyUrl("two");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNotNull(roConfig);
|
||||
assertEquals("one", roConfig.getUrl());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_readOnlyUrlSetOnMain_withNoneNone() {
|
||||
ServerConfig config = newConfig("none");
|
||||
// alternate location to set read-only url for developer convenience
|
||||
config.getDataSourceConfig().setReadOnlyUrl("none");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNull(roConfig);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readOnlyConfig_when_urlSet_2() {
|
||||
ServerConfig config = new ServerConfig();
|
||||
config.getReadOnlyDataSourceConfig().setUrl("foo");
|
||||
|
||||
final DataSourceConfig roConfig = new InitDataSource(config).readOnlyConfig();
|
||||
assertNotNull(roConfig);
|
||||
assertEquals("foo", roConfig.getUrl());
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public class StartSqlServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
SqlServerConfig config = new SqlServerConfig("2017-CU4");
|
||||
SqlServerConfig config = new SqlServerConfig("2019-GA-ubuntu-16.04");
|
||||
config.setDbName("test_ebean");
|
||||
config.setUser("test_ebean");
|
||||
|
||||
|
||||
@@ -55,6 +55,49 @@ public class TestEncrypt extends BaseTestCase {
|
||||
assertThat(loggedSql.get(1)).contains("left join e_basicenc t1 on t1.id = t0.other_id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asDto() {
|
||||
DB.find(EBasicEncrypt.class).delete();
|
||||
|
||||
EBasicEncrypt e = new EBasicEncrypt();
|
||||
e.setName("name2");
|
||||
e.setDescription("descEncrypted2");
|
||||
e.setDob(new Date(System.currentTimeMillis() - 100000));
|
||||
|
||||
DB.save(e);
|
||||
|
||||
final EDto dto = DB.find(EBasicEncrypt.class)
|
||||
.select("name, description")
|
||||
.asDto(EDto.class)
|
||||
.findOne();
|
||||
|
||||
assertThat(dto).isNotNull();
|
||||
assertThat(dto.getName()).isEqualTo("name2");
|
||||
assertThat(dto.getDescription()).isEqualTo("descEncrypted2");
|
||||
}
|
||||
|
||||
public static class EDto {
|
||||
String name;
|
||||
String description;
|
||||
public EDto(){
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform(Platform.H2)
|
||||
public void test() {
|
||||
|
||||
@@ -85,11 +85,10 @@ public class TestOrderedList extends BaseTestCase {
|
||||
Ebean.save(fresh);
|
||||
|
||||
sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(8);
|
||||
assertSql(sql.get(0)).contains("update om_ordered_master set name=?, version=?");
|
||||
assertSql(sql.get(1)).contains("update om_ordered_detail set version=?, sort_order=? where id=? and version=?");
|
||||
assertThat(sql.get(3)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?");
|
||||
|
||||
assertThat(sql).hasSize(3);
|
||||
assertSql(sql.get(0)).contains("update om_ordered_master set name=?, version=? where id=? and version=?; -- bind(m1-mod3");
|
||||
assertSql(sql.get(1)).contains("update om_ordered_detail set name=?, version=?, sort_order=? where id=? and version=?");
|
||||
assertThat(sql.get(2)).contains("bind(was 1,3,2,");
|
||||
|
||||
Ebean.delete(fresh);
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ public class TestDefaults extends BaseTestCase {
|
||||
assertThat(current).isNotEmpty();
|
||||
if (isMySql()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft values (default);");
|
||||
} else if (isSqlServer()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft (id) values (?)");
|
||||
} else {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft default values;");
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.tests.delete;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.IgnorePlatform;
|
||||
@@ -21,15 +21,54 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
private void createUser(String name) {
|
||||
BBookmarkUser u1 = new BBookmarkUser(name);
|
||||
DB.save(u1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.MYSQL)
|
||||
public void deleteWithLimit() {
|
||||
createUser("deleteWithLimit1");
|
||||
createUser("deleteWithLimit2");
|
||||
createUser("deleteWithLimit3");
|
||||
createUser("deleteWithLimit4");
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
final int rows = DB.find(BBookmarkUser.class)
|
||||
.where().startsWith("name", "deleteWithLimit")
|
||||
.setMaxRows(3)
|
||||
.delete();
|
||||
|
||||
assertThat(rows).isEqualTo(3);
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
if (isSqlServer()) {
|
||||
assertSql(sql.get(0)).contains("delete from bbookmark_user where id in (select top 3 t0.id from bbookmark_user t0 where t0.name like ");
|
||||
} else {
|
||||
assertSql(sql.get(0)).contains("delete from bbookmark_user where id in (select t0.id from bbookmark_user t0 where t0.name like");
|
||||
if (isH2() || isPostgres()) {
|
||||
assertSql(sql.get(0)).contains("limit 3");
|
||||
}
|
||||
}
|
||||
|
||||
final int rowsAfter = DB.find(BBookmarkUser.class)
|
||||
.where().startsWith("name", "deleteWithLimit")
|
||||
.setMaxRows(3)
|
||||
.delete();
|
||||
|
||||
assertThat(rowsAfter).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform(Platform.MYSQL)
|
||||
// FIXME: MySql does not the sub query selecting from the delete table
|
||||
public void deleteWithSubquery() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database server = DB.getDefault();
|
||||
|
||||
BBookmarkUser u1 = new BBookmarkUser("u1");
|
||||
Ebean.save(u1);
|
||||
DB.save(u1);
|
||||
|
||||
Query<BBookmarkUser> query = server.find(BBookmarkUser.class)
|
||||
.where().eq("org.name", "NahYeahMaybe")
|
||||
@@ -71,7 +110,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
// FIXME: MySql does not the sub query selecting from the delete table
|
||||
public void deleteWithSubquery_withEscalation() {
|
||||
|
||||
EbeanServer server = Ebean.getDefaultServer();
|
||||
Database server = DB.getDefault();
|
||||
|
||||
Query<Contact> query = server.find(Contact.class).where().eq("group.name", "NahYeahMaybe").query();
|
||||
|
||||
@@ -104,8 +143,8 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(BBookmarkUser.class).where().eq("id", 7000).delete();
|
||||
Ebean.find(BBookmarkUser.class).setId(7000).delete();
|
||||
DB.find(BBookmarkUser.class).where().eq("id", 7000).delete();
|
||||
DB.find(BBookmarkUser.class).setId(7000).delete();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
if (isPlatformSupportsDeleteTableAlias()) {
|
||||
@@ -117,7 +156,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
}
|
||||
|
||||
// and note this is the easiest option
|
||||
Ebean.delete(BBookmarkUser.class, 7000);
|
||||
DB.delete(BBookmarkUser.class, 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -125,8 +164,8 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(Contact.class).where().eq("id", 7000).delete();
|
||||
Ebean.find(Contact.class).setId(7000).delete();
|
||||
DB.find(Contact.class).where().eq("id", 7000).delete();
|
||||
DB.find(Contact.class).setId(7000).delete();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
// escalate to fetch ids then delete ... but no rows found
|
||||
@@ -134,7 +173,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
assertSql(sql.get(1)).contains("select t0.id from contact t0 where t0.id = ?");
|
||||
|
||||
// and note this is the easiest option
|
||||
Ebean.delete(Contact.class, 7000);
|
||||
DB.delete(Contact.class, 7000);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -142,10 +181,10 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
try (Transaction transaction = Ebean.beginTransaction()) {
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
transaction.setPersistCascade(false);
|
||||
|
||||
Ebean.find(Contact.class).where().eq("id", 7001).delete();
|
||||
DB.find(Contact.class).where().eq("id", 7001).delete();
|
||||
|
||||
transaction.commit();
|
||||
}
|
||||
@@ -163,7 +202,7 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.find(Customer.class)
|
||||
DB.find(Customer.class)
|
||||
.where().eq("name", "Don Roberto")
|
||||
.query().forUpdate()
|
||||
.delete();
|
||||
@@ -181,11 +220,11 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
public void deleteByPredicate() {
|
||||
|
||||
BBookmarkUser ud = new BBookmarkUser("deleteQueryByPredicate");
|
||||
Ebean.save(ud);
|
||||
DB.save(ud);
|
||||
|
||||
Ebean.find(BBookmarkUser.class).where().eq("name", "deleteQueryByPredicate").delete();
|
||||
DB.find(BBookmarkUser.class).where().eq("name", "deleteQueryByPredicate").delete();
|
||||
|
||||
BBookmarkUser found = Ebean.find(BBookmarkUser.class, ud.getId());
|
||||
BBookmarkUser found = DB.find(BBookmarkUser.class, ud.getId());
|
||||
assertThat(found).isNull();
|
||||
}
|
||||
|
||||
@@ -200,11 +239,11 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
contact.setLastName("deleteMe");
|
||||
contact.setCustomer(all.get(0));
|
||||
|
||||
Ebean.save(contact);
|
||||
DB.save(contact);
|
||||
|
||||
Ebean.find(Contact.class).where().eq("firstName", "DelByQueryFirstName").delete();
|
||||
DB.find(Contact.class).where().eq("firstName", "DelByQueryFirstName").delete();
|
||||
|
||||
Contact contactFind = Ebean.find(Contact.class, contact.getId());
|
||||
Contact contactFind = DB.find(Contact.class, contact.getId());
|
||||
assertThat(contactFind).isNull();
|
||||
}
|
||||
|
||||
@@ -214,13 +253,13 @@ public class TestDeleteByQuery extends BaseTestCase {
|
||||
Country country = new Country();
|
||||
country.setCode("XX");
|
||||
country.setName("SecretName");
|
||||
Ebean.save(country);
|
||||
Query<Country> query = Ebean.find(Country.class).where().eq("name", "SecretName").setUseQueryCache(true);
|
||||
DB.save(country);
|
||||
Query<Country> query = DB.find(Country.class).where().eq("name", "SecretName").setUseQueryCache(true);
|
||||
|
||||
assertThat(query.findList()).hasSize(1);
|
||||
assertThat(query.findCount()).isEqualTo(1);
|
||||
|
||||
Ebean.find(Country.class).where().eq("name", "SecretName").delete();
|
||||
DB.find(Country.class).where().eq("name", "SecretName").delete();
|
||||
//Ebean.getDefaultServer().getPluginApi().getBeanType(Country.class).clearQueryCache();
|
||||
assertThat(query.findList()).hasSize(0);
|
||||
assertThat(query.findCount()).isEqualTo(0);
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.tests.inheritance;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebeantest.LoggedSql;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
import org.tests.inheritance.order.OrderMasterInheritance;
|
||||
import org.tests.inheritance.order.OrderedA;
|
||||
import org.tests.inheritance.order.OrderedB;
|
||||
import org.tests.inheritance.order.OrderedParent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestInheritanceOrderColumn extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
final OrderMasterInheritance master = new OrderMasterInheritance();
|
||||
final OrderedA orderedA = new OrderedA();
|
||||
orderedA.setCommonName("commonOrderedA");
|
||||
orderedA.setOrderedAName("orderedA");
|
||||
|
||||
final OrderedB orderedB = new OrderedB();
|
||||
orderedB.setCommonName("commonOrderedB");
|
||||
orderedB.setOrderedBName("orderedB");
|
||||
|
||||
master.getReferenced().add(orderedA);
|
||||
master.getReferenced().add(orderedB);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.save(master);
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(5);
|
||||
// Some platforms insert ids and others don't need to...
|
||||
assertSql(trimId(sql, 1))
|
||||
.contains("insert into ordered_parent (order_master_inheritance_id, dtype, common_name, ordered_aname, sort_order) values");
|
||||
assertSql(trimId(sql, 3))
|
||||
.contains("insert into ordered_parent (order_master_inheritance_id, dtype, common_name, ordered_bname, sort_order) values");
|
||||
|
||||
OrderMasterInheritance result = Ebean.find(OrderMasterInheritance.class).findOne();
|
||||
assertThat(result.getReferenced())
|
||||
.extracting(OrderedParent::getCommonName)
|
||||
.containsExactly("commonOrderedA", "commonOrderedB");
|
||||
|
||||
// Swap the two
|
||||
result.getReferenced().add(0, result.getReferenced().remove(1));
|
||||
assertThat(result.getReferenced())
|
||||
.extracting(OrderedParent::getCommonName)
|
||||
.containsExactly("commonOrderedB", "commonOrderedA");
|
||||
|
||||
LoggedSql.start();
|
||||
Ebean.save(result);
|
||||
sql = LoggedSqlCollector.stop();
|
||||
assertThat(sql).hasSize(3);
|
||||
assertThat(sql.get(0)).contains("update ordered_parent set sort_order=? where id=?");
|
||||
|
||||
result = Ebean.find(OrderMasterInheritance.class).findOne();
|
||||
assertThat(result.getReferenced())
|
||||
.extracting(OrderedParent::getCommonName)
|
||||
.containsExactly("commonOrderedB", "commonOrderedA");
|
||||
}
|
||||
|
||||
private String trimId(List<String> sql, int i) {
|
||||
return sql.get(i).replace("(id, ", "(");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.tests.inheritance.order;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class OrderMasterInheritance {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
@OrderColumn(name = "sort_order")
|
||||
List<OrderedParent> referenced = new ArrayList<>();
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<OrderedParent> getReferenced() {
|
||||
return referenced;
|
||||
}
|
||||
|
||||
public void setReferenced(final List<OrderedParent> referenced) {
|
||||
this.referenced = referenced;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.tests.inheritance.order;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class OrderedA extends OrderedParent {
|
||||
|
||||
String orderedAName;
|
||||
|
||||
public String getOrderedAName() {
|
||||
return orderedAName;
|
||||
}
|
||||
|
||||
public void setOrderedAName(final String orderedAName) {
|
||||
this.orderedAName = orderedAName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.tests.inheritance.order;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class OrderedB extends OrderedParent {
|
||||
|
||||
String orderedBName;
|
||||
|
||||
public String getOrderedBName() {
|
||||
return orderedBName;
|
||||
}
|
||||
|
||||
public void setOrderedBName(final String orderedBName) {
|
||||
this.orderedBName = orderedBName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.tests.inheritance.order;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
|
||||
@Entity
|
||||
@Inheritance
|
||||
public abstract class OrderedParent {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
String commonName;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getCommonName() {
|
||||
return commonName;
|
||||
}
|
||||
|
||||
public void setCommonName(final String commonName) {
|
||||
this.commonName = commonName;
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import javax.persistence.UniqueConstraint;
|
||||
@UniqueConstraint(columnNames = "app_name")
|
||||
public class OCachedApp extends OCacheBase {
|
||||
|
||||
private final String appName;
|
||||
private String appName;
|
||||
|
||||
public OCachedApp(String appName) {
|
||||
this.appName = appName;
|
||||
@@ -19,4 +19,8 @@ public class OCachedApp extends OCacheBase {
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public void setAppName(String appName) {
|
||||
this.appName = appName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.tests.model.basic.cache;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestNatKeyCacheWhenNull extends BaseTestCase {
|
||||
|
||||
public static final String WILL_CHANGE_TO_NULL = "WillChangeToNull";
|
||||
|
||||
@Test
|
||||
public void updateToNull() {
|
||||
|
||||
OCachedApp app = setup();
|
||||
|
||||
// act
|
||||
app.setAppName(null);
|
||||
app.save();
|
||||
|
||||
final OCachedApp foundAfter = DB.find(OCachedApp.class)
|
||||
.where().eq("appName", WILL_CHANGE_TO_NULL)
|
||||
.findOne();
|
||||
|
||||
assertThat(foundAfter).isNull();
|
||||
app.delete();
|
||||
}
|
||||
|
||||
private OCachedApp setup() {
|
||||
OCachedApp app = new OCachedApp(WILL_CHANGE_TO_NULL);
|
||||
app.save();
|
||||
|
||||
final OCachedApp foundBefore = DB.find(OCachedApp.class)
|
||||
.where().eq("appName", WILL_CHANGE_TO_NULL)
|
||||
.findOne();
|
||||
|
||||
assertThat(foundBefore).isNotNull();
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.tests.model.version;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestVersionHierarchyModification extends BaseTestCase {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
final VersionParent parent = new VersionParent();
|
||||
parent.setName("vParent");
|
||||
|
||||
final VersionChild child1 = new VersionChild();
|
||||
child1.setName("vChild1");
|
||||
parent.getChildren().add(child1);
|
||||
|
||||
final VersionToy toy11 = new VersionToy();
|
||||
toy11.setName("vToy1.1");
|
||||
child1.getToys().add(toy11);
|
||||
|
||||
final VersionToy toy12 = new VersionToy();
|
||||
toy12.setName("vToy1.2");
|
||||
child1.getToys().add(toy12);
|
||||
|
||||
final VersionChild child2 = new VersionChild();
|
||||
child2.setName("vChild2");
|
||||
parent.getChildren().add(child2);
|
||||
|
||||
final VersionToy toy21 = new VersionToy();
|
||||
toy21.setName("vToy2.1");
|
||||
child2.getToys().add(toy21);
|
||||
|
||||
final VersionToy toy22 = new VersionToy();
|
||||
toy22.setName("vToy2.2");
|
||||
child2.getToys().add(toy22);
|
||||
|
||||
Ebean.save(parent);
|
||||
}
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
Ebean.find(VersionParent.class).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveDown() {
|
||||
VersionParent parent = Ebean.find(VersionParent.class).findOne();
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(parent.getChildren()).hasSize(2);
|
||||
|
||||
VersionChild firstChild = parent.getChildren().get(0);
|
||||
VersionChild secondChild = parent.getChildren().get(1);
|
||||
|
||||
assertThat(firstChild.getToys()).hasSize(2);
|
||||
assertThat(secondChild.getToys()).hasSize(2);
|
||||
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy1.2");
|
||||
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy2.2");
|
||||
|
||||
final VersionToy toyToMove = firstChild.getToys().get(0);
|
||||
firstChild.getToys().remove(toyToMove);
|
||||
toyToMove.setChild(secondChild);
|
||||
secondChild.getToys().add(1, toyToMove);
|
||||
|
||||
Ebean.save(parent);
|
||||
|
||||
parent = Ebean.find(VersionParent.class).findOne();
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(parent.getChildren()).hasSize(2);
|
||||
|
||||
firstChild = parent.getChildren().get(0);
|
||||
secondChild = parent.getChildren().get(1);
|
||||
|
||||
assertThat(firstChild.getToys()).hasSize(1);
|
||||
assertThat(secondChild.getToys()).hasSize(3);
|
||||
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.2");
|
||||
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy1.1", "vToy2.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMoveUp() {
|
||||
VersionParent parent = Ebean.find(VersionParent.class).findOne();
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(parent.getChildren()).hasSize(2);
|
||||
|
||||
VersionChild firstChild = parent.getChildren().get(0);
|
||||
VersionChild secondChild = parent.getChildren().get(1);
|
||||
|
||||
assertThat(firstChild.getToys()).hasSize(2);
|
||||
assertThat(secondChild.getToys()).hasSize(2);
|
||||
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy1.2");
|
||||
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.1", "vToy2.2");
|
||||
|
||||
final VersionToy toyToMove = secondChild.getToys().get(0);
|
||||
secondChild.getToys().remove(toyToMove);
|
||||
toyToMove.setChild(firstChild);
|
||||
firstChild.getToys().add(1, toyToMove);
|
||||
|
||||
Ebean.save(parent);
|
||||
|
||||
parent = Ebean.find(VersionParent.class).findOne();
|
||||
assertThat(parent).isNotNull();
|
||||
assertThat(parent.getChildren()).hasSize(2);
|
||||
|
||||
firstChild = parent.getChildren().get(0);
|
||||
secondChild = parent.getChildren().get(1);
|
||||
|
||||
assertThat(secondChild.getToys()).hasSize(1);
|
||||
assertThat(firstChild.getToys()).hasSize(3);
|
||||
assertThat(secondChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy2.2");
|
||||
assertThat(firstChild.getToys()).extracting(VersionToy::getName).containsExactly("vToy1.1", "vToy2.1", "vToy1.2");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.tests.model.version;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Version;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class VersionChild {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
String name;
|
||||
|
||||
@Version
|
||||
Integer version;
|
||||
|
||||
@OneToMany(mappedBy = "child", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@OrderColumn(name = "position")
|
||||
List<VersionToy> toys = new ArrayList<>();
|
||||
|
||||
@ManyToOne
|
||||
VersionParent parent;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public List<VersionToy> getToys() {
|
||||
return toys;
|
||||
}
|
||||
|
||||
public void setToys(final List<VersionToy> toys) {
|
||||
this.toys = toys;
|
||||
}
|
||||
|
||||
public VersionParent getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(final VersionParent parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package org.tests.model.version;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Version;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class VersionParent {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@Version
|
||||
Integer version;
|
||||
|
||||
String name;
|
||||
|
||||
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
@OrderColumn(name = "position")
|
||||
List<VersionChild> children = new ArrayList<>();
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<VersionChild> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(final List<VersionChild> children) {
|
||||
this.children = children;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.tests.model.version;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class VersionToy {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
String name;
|
||||
|
||||
@Version
|
||||
Integer version;
|
||||
|
||||
@ManyToOne
|
||||
VersionChild child;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final Integer version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public VersionChild getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
public void setChild(final VersionChild child) {
|
||||
this.child = child;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package org.tests.order;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderColumn;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("D")
|
||||
@@ -13,6 +17,10 @@ public class OrderReferencedChild extends OrderReferencedParent {
|
||||
@ManyToOne
|
||||
OrderMaster master;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "child", orphanRemoval = true)
|
||||
@OrderColumn(name = "sort_order")
|
||||
List<OrderToy> toys;
|
||||
|
||||
public OrderReferencedChild(final String name) {
|
||||
super(name);
|
||||
}
|
||||
@@ -32,4 +40,12 @@ public class OrderReferencedChild extends OrderReferencedParent {
|
||||
public void setMaster(final OrderMaster master) {
|
||||
this.master = master;
|
||||
}
|
||||
|
||||
public List<OrderToy> getToys() {
|
||||
return toys;
|
||||
}
|
||||
|
||||
public void setToys(final List<OrderToy> toys) {
|
||||
this.toys = toys;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.tests.order;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class OrderToy {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
String title;
|
||||
|
||||
@ManyToOne
|
||||
OrderReferencedChild child;
|
||||
|
||||
public OrderToy(final String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(final String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public OrderReferencedChild getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
public void setChild(final OrderReferencedChild child) {
|
||||
this.child = child;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,12 @@ package org.tests.order;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestOrderColumn extends TransactionalTestCase {
|
||||
@@ -28,4 +32,116 @@ public class TestOrderColumn extends TransactionalTestCase {
|
||||
assertThat(result.getChildren()).extracting(OrderReferencedChild::getChildName).containsExactly("c0", "c1", "c2", "c3", "c4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOrderColumnSortChange() {
|
||||
final OrderMaster master = new OrderMaster();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final OrderReferencedChild child = new OrderReferencedChild("p" + i);
|
||||
child.setChildName("c" + i);
|
||||
|
||||
master.getChildren().add(child);
|
||||
}
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
OrderMaster result = Ebean.find(OrderMaster.class).findOne();
|
||||
|
||||
assertThat(result.getChildren()).hasSize(5);
|
||||
assertThat(master.getChildren()).extracting(OrderReferencedChild::getName).containsExactly("p0", "p1", "p2", "p3", "p4");
|
||||
|
||||
master.getChildren().sort(Comparator.comparing(OrderReferencedChild::getName).reversed());
|
||||
assertThat(master.getChildren()).extracting(OrderReferencedChild::getName).containsExactly("p4", "p3", "p2", "p1", "p0");
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
result = Ebean.find(OrderMaster.class).findOne();
|
||||
|
||||
assertThat(result.getChildren()).hasSize(5);
|
||||
assertThat(result.getChildren()).extracting(OrderReferencedChild::getName).containsExactly("p4", "p3", "p2", "p1", "p0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testModifyTree() {
|
||||
final OrderMaster master = new OrderMaster();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final OrderReferencedChild child = new OrderReferencedChild("p" + i);
|
||||
child.setChildName("c" + i);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
final OrderToy toy = new OrderToy("t" + i + j);
|
||||
child.getToys().add(toy);
|
||||
}
|
||||
|
||||
master.getChildren().add(child);
|
||||
}
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
final OrderMaster result = Ebean.find(OrderMaster.class).findOne();
|
||||
|
||||
final List<OrderReferencedChild> children = result.getChildren();
|
||||
assertThat(children).hasSize(5);
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final List<OrderToy> toys = children.get(i).getToys();
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
final OrderToy toy = toys.get(j);
|
||||
assertThat(toy.getTitle()).isEqualTo("t" + i + j);
|
||||
}
|
||||
}
|
||||
|
||||
// modify two toys
|
||||
children.get(1).getToys().get(0).setTitle("tt10");
|
||||
children.get(3).getToys().get(2).setTitle("tt32");
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.save(result);
|
||||
final List<String> sql = LoggedSqlCollector.current();
|
||||
assertThat(sql).hasSize(3);
|
||||
|
||||
assertThat(sql.get(0)).contains("update order_toy set title=?, sort_order=? where id=?");
|
||||
assertThat(sql.get(1)).contains("bind(tt10");
|
||||
assertThat(sql.get(2)).contains("bind(tt32");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveElement() {
|
||||
final OrderMaster master = new OrderMaster();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final OrderReferencedChild child = new OrderReferencedChild("p" + i);
|
||||
child.setChildName("c" + i);
|
||||
|
||||
for (int j = 0; j < 3; j++) {
|
||||
final OrderToy toy = new OrderToy("t" + i + j);
|
||||
child.getToys().add(toy);
|
||||
}
|
||||
|
||||
master.getChildren().add(child);
|
||||
}
|
||||
|
||||
Ebean.save(master);
|
||||
|
||||
final OrderMaster result = Ebean.find(OrderMaster.class).findOne();
|
||||
|
||||
final List<OrderReferencedChild> children = result.getChildren();
|
||||
assertThat(children).hasSize(5);
|
||||
|
||||
final OrderReferencedChild child = children.get(0);
|
||||
|
||||
child.getToys().remove(1);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.save(result);
|
||||
final List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(sql).hasSize(4);
|
||||
assertSql(sql.get(0)).contains("delete from order_toy where id=?");
|
||||
assertSql(sql.get(2)).contains("update order_toy set sort_order=? where id=?");
|
||||
assertSql(sql.get(3)).contains("bind(2,");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package org.tests.text.csv;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import org.junit.Test;
|
||||
@@ -10,7 +10,6 @@ import org.tests.model.basic.ResetBasicData;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TestCsvReader extends TransactionalTestCase {
|
||||
|
||||
@@ -25,7 +24,7 @@ public class TestCsvReader extends TransactionalTestCase {
|
||||
|
||||
FileReader reader = new FileReader(f);
|
||||
|
||||
CsvReader<Customer> csvReader = Ebean.createCsvReader(Customer.class);
|
||||
CsvReader<Customer> csvReader = DB.getDefault().createCsvReader(Customer.class);
|
||||
|
||||
csvReader.setPersistBatchSize(2);
|
||||
|
||||
@@ -33,7 +32,7 @@ public class TestCsvReader extends TransactionalTestCase {
|
||||
// csvReader.addProperty("id");
|
||||
csvReader.addProperty("status");
|
||||
csvReader.addProperty("name");
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.GERMAN);
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
|
||||
csvReader.addProperty("billingAddress.line1");
|
||||
csvReader.addProperty("billingAddress.city");
|
||||
csvReader.addProperty("billingAddress.country.code");
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.tests.text.csv;
|
||||
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TransactionalTestCase;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.csv.DefaultCsvCallback;
|
||||
@@ -11,7 +10,6 @@ import org.tests.model.basic.Customer;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.net.URL;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -25,9 +23,7 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
|
||||
FileReader reader = new FileReader(f);
|
||||
|
||||
final EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
CsvReader<Customer> csvReader = server.createCsvReader(Customer.class);
|
||||
CsvReader<Customer> csvReader = DB.getDefault().createCsvReader(Customer.class);
|
||||
|
||||
csvReader.setPersistBatchSize(2);
|
||||
csvReader.setLogInfoFrequency(3);
|
||||
@@ -36,13 +32,13 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
// csvReader.addProperty("id");
|
||||
csvReader.addProperty("status");
|
||||
csvReader.addProperty("name");
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy", Locale.GERMAN);
|
||||
csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
|
||||
csvReader.addProperty("billingAddress.line1");
|
||||
csvReader.addProperty("billingAddress.city");
|
||||
// processor.addReference("billingAddress.country.code");
|
||||
csvReader.addProperty("billingAddress.country.code");
|
||||
|
||||
int before = Ebean.find(Customer.class).findCount();
|
||||
int before = DB.find(Customer.class).findCount();
|
||||
|
||||
csvReader.process(reader, new DefaultCsvCallback<Customer>() {
|
||||
|
||||
@@ -56,9 +52,8 @@ public class TestCsvReaderWithCallback extends TransactionalTestCase {
|
||||
|
||||
});
|
||||
|
||||
int after = Ebean.find(Customer.class).findCount();
|
||||
int after = DB.find(Customer.class).findCount();
|
||||
assertThat(after).isEqualTo(before + 9);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.avaje.config.Config;
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import io.ebean.datasource.DataSourcePool;
|
||||
import io.ebean.datasource.pool.ConnectionPool;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestAutoCommitDataSource extends BaseTestCase {
|
||||
|
||||
@ForPlatform({Platform.H2, Platform.POSTGRES})
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = Config.asProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings(properties, "h2autocommit");//"pg"
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
connection.close();
|
||||
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2autocommit");
|
||||
config.loadFromProperties();
|
||||
config.setDataSource(pool);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
|
||||
config.addClass(UTMaster.class);
|
||||
config.addClass(UTDetail.class);
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.setDdlExtra(false);
|
||||
|
||||
config.setAutoCommitMode(true);
|
||||
|
||||
Database database = DatabaseFactory.create(config);
|
||||
|
||||
Query<UTMaster> query = database.find(UTMaster.class);
|
||||
List<UTMaster> details = query.findList();
|
||||
assertEquals(0, details.size());
|
||||
|
||||
UTMaster bean1 = new UTMaster("one1");
|
||||
UTMaster bean2 = new UTMaster("two2");
|
||||
UTMaster bean3 = new UTMaster("three3");
|
||||
|
||||
// use a different transaction to do final query check
|
||||
try (Transaction otherTxn = database.createTransaction()) {
|
||||
try (Transaction txn = database.beginTransaction()) {
|
||||
assertTrue(txn.getConnection().getAutoCommit());
|
||||
database.save(bean1);
|
||||
database.save(bean2);
|
||||
|
||||
details = database.find(UTMaster.class)
|
||||
.usingTransaction(otherTxn)
|
||||
.findList();
|
||||
assertEquals(2, details.size());
|
||||
|
||||
database.save(bean3);
|
||||
txn.rollback();
|
||||
}
|
||||
|
||||
details = database.find(UTMaster.class)
|
||||
.usingTransaction(otherTxn)
|
||||
.findList();
|
||||
assertEquals(3, details.size());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.avaje.config.Config;
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.JsonConfig;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import io.ebean.datasource.DataSourcePool;
|
||||
import io.ebean.datasource.pool.ConnectionPool;
|
||||
import io.ebeaninternal.server.type.ScalarTypeLocalDate;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestExplicitTransactionMode extends BaseTestCase {
|
||||
|
||||
@ForPlatform(Platform.H2)
|
||||
@Test
|
||||
public void test() throws SQLException {
|
||||
|
||||
Properties properties = Config.asProperties();
|
||||
|
||||
DataSourceConfig dsConfig = new DataSourceConfig();
|
||||
dsConfig.loadSettings(properties, "h2autocommit2");
|
||||
dsConfig.setAutoCommit(true);
|
||||
|
||||
DataSourcePool pool = new ConnectionPool("h2autocommit2", dsConfig);
|
||||
|
||||
Connection connection = pool.getConnection();
|
||||
assertTrue(connection.getAutoCommit());
|
||||
connection.close();
|
||||
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2autocommit2");
|
||||
config.loadFromProperties();
|
||||
config.setDataSource(pool);
|
||||
config.setDefaultServer(false);
|
||||
config.setRegister(false);
|
||||
config.setExplicitTransactionBeginMode(true);
|
||||
|
||||
config.addClass(UTMaster.class);
|
||||
config.addClass(UTDetail.class);
|
||||
config.setDdlGenerate(true);
|
||||
config.setDdlRun(true);
|
||||
config.setDdlExtra(false);
|
||||
config.addClass(ScalarTypeLocalDateAsString.class);
|
||||
|
||||
Database database = DatabaseFactory.create(config);
|
||||
|
||||
testJsonScalarType(database);
|
||||
|
||||
Query<UTMaster> query = database.find(UTMaster.class);
|
||||
List<UTMaster> details = query.findList();
|
||||
assertEquals(0, details.size());
|
||||
|
||||
UTMaster bean0 = new UTMaster("one0");
|
||||
Transaction txn0 = database.beginTransaction();
|
||||
try {
|
||||
database.save(bean0);
|
||||
txn0.rollback();
|
||||
} finally {
|
||||
txn0.end();
|
||||
}
|
||||
|
||||
// rollback as expected
|
||||
assertEquals(0, database.find(UTMaster.class).findCount());
|
||||
|
||||
UTMaster bean1 = new UTMaster("one1");
|
||||
UTMaster bean2 = new UTMaster("two2");
|
||||
UTMaster bean3 = new UTMaster("three3");
|
||||
|
||||
// use a different transaction to do final query check
|
||||
try (Transaction otherTxn = database.createTransaction()) {
|
||||
|
||||
Transaction txn = database.beginTransaction();
|
||||
try {
|
||||
database.save(bean1);
|
||||
database.save(bean2);
|
||||
|
||||
// not visible in other transaction
|
||||
Query<UTMaster> query2 = database.find(UTMaster.class);
|
||||
details = database.extended().findList(query2, otherTxn);
|
||||
assertEquals(0, details.size());
|
||||
|
||||
database.save(bean3);
|
||||
|
||||
txn.commit();
|
||||
|
||||
} finally {
|
||||
txn.end();
|
||||
}
|
||||
|
||||
// commit as expected
|
||||
details = database.find(UTMaster.class)
|
||||
.usingTransaction(otherTxn)
|
||||
.findList();
|
||||
|
||||
assertEquals(3, details.size());
|
||||
}
|
||||
}
|
||||
|
||||
private void testJsonScalarType(Database ebeanServer) {
|
||||
UTMaster bean = new UTMaster("one1");
|
||||
bean.setEventDate(LocalDate.of(2019, 04, 20));
|
||||
|
||||
String json = ebeanServer.json().toJson(bean);
|
||||
assertThat(json).isEqualTo("{\"name\":\"one1\",\"eventDate\":\"2019-04-20\"}");
|
||||
UTMaster jsonMaster = ebeanServer.json().toBean(UTMaster.class, json);
|
||||
assertThat(jsonMaster.getEventDate()).isEqualTo(LocalDate.of(2019, 4, 20));
|
||||
}
|
||||
|
||||
public static class ScalarTypeLocalDateAsString extends ScalarTypeLocalDate {
|
||||
|
||||
public ScalarTypeLocalDateAsString() {
|
||||
super(JsonConfig.Date.ISO8601);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modelSaveWithTransaction() {
|
||||
|
||||
try (Transaction txn = DB.getDefault().createTransaction()) {
|
||||
|
||||
UTMaster bean1 = new UTMaster("otherSave");
|
||||
bean1.save(txn);
|
||||
assertThat(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherSave").findOne()).isNotNull();
|
||||
|
||||
bean1.deletePermanent(txn);
|
||||
assertThat(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherSave").findOne())
|
||||
.isNull();
|
||||
|
||||
UTMaster bean2 = new UTMaster("otherInsert");
|
||||
bean2.insert(txn);
|
||||
assertTrue(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherInsert").exists());
|
||||
|
||||
bean2.setDescription("changed description");
|
||||
bean2.update(txn);
|
||||
|
||||
assertThat(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherInsert").findOne())
|
||||
.isNotNull()
|
||||
.extracting(UTMaster::getDescription).contains("changed description");
|
||||
|
||||
UTMaster bean3 = new UTMaster("otherThree");
|
||||
bean3.save(txn);
|
||||
|
||||
assertThat(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherThree").findOne())
|
||||
.isNotNull();
|
||||
|
||||
bean3.delete(txn);
|
||||
|
||||
assertThat(DB.find(UTMaster.class).usingTransaction(txn)
|
||||
.where().eq("name", "otherThree").findOne())
|
||||
.isNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.tests.transaction;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.annotation.Transactional;
|
||||
import io.ebean.meta.MetaTimedMetric;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestTransactionalReadOnly extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test_readonly_datasource() {
|
||||
|
||||
resetAllMetrics();
|
||||
executeTransactionalUsingReadOnlyDataSource();
|
||||
|
||||
final List<MetaTimedMetric> timedMetrics = collectMetrics().getTimedMetrics();
|
||||
final Optional<MetaTimedMetric> txnReadOnly = metric(timedMetrics, "txn.readonly");
|
||||
assertThat(txnReadOnly.get().getCount()).isEqualTo(1);
|
||||
assertThat(metric(timedMetrics, "txn")).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_main_datasource() {
|
||||
|
||||
resetAllMetrics();
|
||||
executeTransactionalUsingMainDataSource();
|
||||
|
||||
final List<MetaTimedMetric> timedMetrics = collectMetrics().getTimedMetrics();
|
||||
final Optional<MetaTimedMetric> txnMain = metric(timedMetrics, "txn.main");
|
||||
assertThat(txnMain.get().getCount()).isEqualTo(1);
|
||||
assertThat(metric(timedMetrics, "txn.readonly")).isEmpty();
|
||||
}
|
||||
|
||||
private Optional<MetaTimedMetric> metric(List<MetaTimedMetric> timedMetrics, String name) {
|
||||
return timedMetrics.stream()
|
||||
.filter(metaTimedMetric -> metaTimedMetric.getName().equals(name))
|
||||
.findFirst();
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
private void executeTransactionalUsingReadOnlyDataSource() {
|
||||
DB.find(Customer.class).findCount();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private void executeTransactionalUsingMainDataSource() {
|
||||
DB.find(Customer.class).findCount();
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,16 @@
|
||||
-- Migrationscripts for ebean unittest
|
||||
-- apply changes
|
||||
create table migtest_ckey_assoc (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
assoc_one varchar2(255),
|
||||
constraint pk_migtest_ckey_assoc primary key (id)
|
||||
);
|
||||
create sequence migtest_ckey_assoc_seq;
|
||||
|
||||
create table migtest_ckey_detail (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
something varchar2(255),
|
||||
constraint pk_migtest_ckey_detail primary key (id)
|
||||
);
|
||||
create sequence migtest_ckey_detail_seq;
|
||||
|
||||
create table migtest_ckey_parent (
|
||||
one_key number(10) not null,
|
||||
@@ -23,47 +21,41 @@ create table migtest_ckey_parent (
|
||||
);
|
||||
|
||||
create table migtest_fk_cascade (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
one_id number(19),
|
||||
constraint pk_migtest_fk_cascade primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_cascade_seq;
|
||||
|
||||
create table migtest_fk_cascade_one (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
constraint pk_migtest_fk_cascade_one primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_cascade_one_seq;
|
||||
|
||||
create table migtest_fk_none (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
one_id number(19),
|
||||
constraint pk_migtest_fk_none primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_none_seq;
|
||||
|
||||
create table migtest_fk_none_via_join (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
one_id number(19),
|
||||
constraint pk_migtest_fk_none_via_join primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_none_via_join_seq;
|
||||
|
||||
create table migtest_fk_one (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
constraint pk_migtest_fk_one primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_one_seq;
|
||||
|
||||
create table migtest_fk_set_null (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
one_id number(19),
|
||||
constraint pk_migtest_fk_set_null primary key (id)
|
||||
);
|
||||
create sequence migtest_fk_set_null_seq;
|
||||
|
||||
create table migtest_e_basic (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
status varchar2(1),
|
||||
status2 varchar2(1) default 'N' not null,
|
||||
name varchar2(127),
|
||||
@@ -85,103 +77,89 @@ create table migtest_e_basic (
|
||||
constraint uq_migtest_e_basic_indextest6 unique (indextest6),
|
||||
constraint pk_migtest_e_basic primary key (id)
|
||||
);
|
||||
create sequence migtest_e_basic_seq;
|
||||
|
||||
create table migtest_e_enum (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_status varchar2(1),
|
||||
constraint ck_migtest_e_enum_test_status check ( test_status in ('N','A','I')),
|
||||
constraint pk_migtest_e_enum primary key (id)
|
||||
);
|
||||
create sequence migtest_e_enum_seq;
|
||||
|
||||
create table migtest_e_history (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_string varchar2(255),
|
||||
constraint pk_migtest_e_history primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history_seq;
|
||||
|
||||
create table migtest_e_history2 (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_string varchar2(255),
|
||||
obsolete_string1 varchar2(255),
|
||||
obsolete_string2 varchar2(255),
|
||||
constraint pk_migtest_e_history2 primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history2_seq;
|
||||
|
||||
create table migtest_e_history3 (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_string varchar2(255),
|
||||
constraint pk_migtest_e_history3 primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history3_seq;
|
||||
|
||||
create table migtest_e_history4 (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_number number(10),
|
||||
constraint pk_migtest_e_history4 primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history4_seq;
|
||||
|
||||
create table migtest_e_history5 (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_number number(10),
|
||||
constraint pk_migtest_e_history5 primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history5_seq;
|
||||
|
||||
create table migtest_e_history6 (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_number1 number(10),
|
||||
test_number2 number(10) not null,
|
||||
constraint pk_migtest_e_history6 primary key (id)
|
||||
);
|
||||
create sequence migtest_e_history6_seq;
|
||||
|
||||
create table migtest_e_ref (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
name varchar2(127) not null,
|
||||
constraint uq_migtest_e_ref_name unique (name),
|
||||
constraint pk_migtest_e_ref primary key (id)
|
||||
);
|
||||
create sequence migtest_e_ref_seq;
|
||||
|
||||
create table migtest_e_softdelete (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
test_string varchar2(255),
|
||||
constraint pk_migtest_e_softdelete primary key (id)
|
||||
);
|
||||
create sequence migtest_e_softdelete_seq;
|
||||
|
||||
create table migtest_mtm_c (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
name varchar2(255),
|
||||
constraint pk_migtest_mtm_c primary key (id)
|
||||
);
|
||||
create sequence migtest_mtm_c_seq;
|
||||
|
||||
create table migtest_mtm_m (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
name varchar2(255),
|
||||
constraint pk_migtest_mtm_m primary key (id)
|
||||
);
|
||||
create sequence migtest_mtm_m_seq;
|
||||
|
||||
create table migtest_oto_child (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
name varchar2(255),
|
||||
constraint pk_migtest_oto_child primary key (id)
|
||||
);
|
||||
create sequence migtest_oto_child_seq;
|
||||
|
||||
create table migtest_oto_master (
|
||||
id number(19) not null,
|
||||
id number(19) generated by default as identity not null,
|
||||
name varchar2(255),
|
||||
constraint pk_migtest_oto_master primary key (id)
|
||||
);
|
||||
create sequence migtest_oto_master_seq;
|
||||
|
||||
create index ix_migtest_e_basic_indextest1 on migtest_e_basic (indextest1);
|
||||
create index ix_migtest_e_basic_indextest5 on migtest_e_basic (indextest5);
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
-- Migrationscripts for ebean unittest
|
||||
-- apply changes
|
||||
create table migtest_e_user (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
constraint pk_migtest_e_user primary key (id)
|
||||
);
|
||||
create sequence migtest_e_user_seq;
|
||||
|
||||
create table migtest_mtm_c_migtest_mtm_m (
|
||||
migtest_mtm_c_id number(10) not null,
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
-- Migrationscripts for ebean unittest
|
||||
-- apply changes
|
||||
create table migtest_e_ref (
|
||||
id number(10) not null,
|
||||
id number(10) generated by default as identity not null,
|
||||
name varchar2(127) not null,
|
||||
constraint uq_migtest_e_ref_name unique (name),
|
||||
constraint pk_migtest_e_ref primary key (id)
|
||||
);
|
||||
create sequence migtest_e_ref_seq;
|
||||
|
||||
alter table migtest_ckey_detail drop constraint fk_migtest_ckey_detail_parent;
|
||||
alter table migtest_fk_cascade drop constraint fk_migtest_fk_cascade_one_id;
|
||||
|
||||
@@ -31,6 +31,7 @@ ebean.dumpMetricsOptions=sql,hash
|
||||
ebean.collectQueryPlans=true
|
||||
|
||||
ebean.autoReadOnlyDataSource=true
|
||||
#datasource.h2-ro.url=jdbc:h2:mem:tests
|
||||
|
||||
#ebean.persistBatch=NONE
|
||||
|
||||
@@ -71,8 +72,8 @@ datasource.db.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
datasource.h2.databaseUrl=jdbc:h2:mem:tests
|
||||
datasource.h2.databaseDriver=org.h2.Driver
|
||||
datasource.h2.url=jdbc:h2:mem:tests
|
||||
#datasource.h2.driver=org.h2.Driver
|
||||
datasource.h2.minConnections=1
|
||||
datasource.h2.maxConnections=25
|
||||
#datasource.h2.heartbeatsql=select 1
|
||||
@@ -86,61 +87,53 @@ datasource.h2.poolListener=org.tests.basic.MyTestDataSourcePoolListener
|
||||
datasource.h2multitenant.username=sa
|
||||
datasource.h2multitenant.password=
|
||||
datasource.h2multitenant.url=jdbc:h2:mem:h2multitenant
|
||||
datasource.h2multitenant.driver=org.h2.Driver
|
||||
|
||||
datasource.h2autocommit.autoCommit=true
|
||||
datasource.h2autocommit.username=sa
|
||||
datasource.h2autocommit.password=
|
||||
datasource.h2autocommit.databaseUrl=jdbc:h2:mem:autocommittests
|
||||
datasource.h2autocommit.databaseDriver=org.h2.Driver
|
||||
|
||||
datasource.h2autocommit2.autoCommit=true
|
||||
datasource.h2autocommit2.username=sa
|
||||
datasource.h2autocommit2.password=
|
||||
datasource.h2autocommit2.databaseUrl=jdbc:h2:mem:autocommit2tests
|
||||
datasource.h2autocommit2.databaseDriver=org.h2.Driver
|
||||
datasource.h2autocommit2.url=jdbc:h2:mem:autocommit2tests
|
||||
|
||||
datasource.h2other.username=sa
|
||||
datasource.h2other.password=
|
||||
datasource.h2other.databaseUrl=jdbc:h2:mem:h2other
|
||||
datasource.h2other.databaseDriver=org.h2.Driver
|
||||
datasource.h2other.url=jdbc:h2:mem:h2other
|
||||
|
||||
datasource.h2otherfind.username=sa
|
||||
datasource.h2otherfind.password=
|
||||
datasource.h2otherfind.databaseUrl=jdbc:h2:mem:h2otherfind
|
||||
datasource.h2otherfind.databaseDriver=org.h2.Driver
|
||||
datasource.h2otherfind.url=jdbc:h2:mem:h2otherfind
|
||||
|
||||
datasource.h2ebasicver.username=sa
|
||||
datasource.h2ebasicver.password=
|
||||
datasource.h2ebasicver.databaseUrl=jdbc:h2:mem:h2ebasicver
|
||||
datasource.h2ebasicver.databaseDriver=org.h2.Driver
|
||||
datasource.h2ebasicver.url=jdbc:h2:mem:h2ebasicver
|
||||
|
||||
datasource.h2ebasicver2.username=sa
|
||||
datasource.h2ebasicver2.password=
|
||||
datasource.h2ebasicver2.databaseUrl=jdbc:h2:mem:h2ebasicver
|
||||
datasource.h2ebasicver2.databaseDriver=org.h2.Driver
|
||||
datasource.h2ebasicver2.url=jdbc:h2:mem:h2ebasicver
|
||||
|
||||
datasource.sqlite.username=
|
||||
datasource.sqlite.password=
|
||||
datasource.sqlite.databaseUrl=jdbc:sqlite:mydb.db
|
||||
datasource.sqlite.databaseDriver=org.sqlite.JDBC
|
||||
datasource.sqlite.url=jdbc:sqlite:mydb.db
|
||||
datasource.sqlite.driver=org.sqlite.JDBC
|
||||
datasource.sqlite.isolationlevel=read_uncommitted
|
||||
|
||||
datasource.hsqldb.username=sa
|
||||
datasource.hsqldb.password=
|
||||
datasource.hsqldb.databaseUrl=jdbc:hsqldb:mem:tests
|
||||
datasource.hsqldb.databaseDriver=org.hsqldb.jdbcDriver
|
||||
datasource.hsqldb.url=jdbc:hsqldb:mem:tests
|
||||
|
||||
# Set caseSensitiveCollation to false when using
|
||||
# MySql with case insensitive collation
|
||||
#ebean.mysql.caseSensitiveCollation=false
|
||||
datasource.mysql.username=unit
|
||||
datasource.mysql.password=unit
|
||||
datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/unit
|
||||
datasource.mysql.url=jdbc:mysql://127.0.0.1:4306/unit
|
||||
#datasource.mysql.username=test_ebean
|
||||
#datasource.mysql.password=test
|
||||
#datasource.mysql.databaseUrl=jdbc:mysql://127.0.0.1:4306/test_ebean
|
||||
datasource.mysql.databaseDriver=com.mysql.cj.jdbc.Driver
|
||||
#datasource.mysql.url=jdbc:mysql://127.0.0.1:4306/test_ebean
|
||||
#datasource.mysql.driver=com.mysql.cj.jdbc.Driver
|
||||
|
||||
datasource.cockroach.username=root
|
||||
datasource.cockroach.password=
|
||||
@@ -149,23 +142,21 @@ datasource.cockroach.driver=org.postgresql.Driver
|
||||
|
||||
datasource.oracle.username=test_ebean
|
||||
datasource.oracle.password=test
|
||||
datasource.oracle.databaseUrl=jdbc:oracle:thin:@localhost:1521:XE
|
||||
datasource.oracle.databaseDriver=oracle.jdbc.driver.OracleDriver
|
||||
datasource.oracle.url=jdbc:oracle:thin:@localhost:1521:XE
|
||||
#datasource.oracle.driver=oracle.jdbc.driver.OracleDriver
|
||||
|
||||
## set this to use timestamp rather than timestamptz
|
||||
#ebean.postgres.timestamp=timestamp
|
||||
|
||||
datasource.pg.username=unit
|
||||
datasource.pg.password=unit
|
||||
datasource.pg.databaseUrl=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
datasource.pg.databaseDriver=org.postgresql.Driver
|
||||
datasource.pg.url=jdbc:postgresql://127.0.0.1:5432/unit
|
||||
#datasource.pg.capturestacktrace=true
|
||||
datasource.pg.maxStackTraceSize=50
|
||||
|
||||
datasource.pg9.username=unit
|
||||
datasource.pg9.password=unit
|
||||
datasource.pg9.databaseUrl=jdbc:postgresql://127.0.0.1:9432/unit
|
||||
datasource.pg9.databaseDriver=org.postgresql.Driver
|
||||
datasource.pg9.url=jdbc:postgresql://127.0.0.1:9432/unit
|
||||
|
||||
|
||||
#ebean.sqlserver.idType=SEQUENCE
|
||||
@@ -178,29 +169,28 @@ ebean.sqlserver.databasePlatformName=sqlserver17
|
||||
datasource.sqlserver.username=test_ebean
|
||||
datasource.sqlserver.password=SqlS3rv#r
|
||||
datasource.sqlserver.url=jdbc:sqlserver://localhost:1433;databaseName=test_ebean;sendTimeAsDateTime=false
|
||||
datasource.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
#datasource.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
|
||||
|
||||
datasource.nuodb.schema=test_user
|
||||
datasource.nuodb.username=test_user
|
||||
datasource.nuodb.password=test
|
||||
datasource.nuodb.url=jdbc:com.nuodb://localhost/testdb
|
||||
datasource.nuodb.driver=com.nuodb.jdbc.Driver
|
||||
#datasource.nuodb.driver=com.nuodb.jdbc.Driver
|
||||
|
||||
datasource.db2.username=db2admin
|
||||
datasource.db2.password=veryverysecret#1234
|
||||
datasource.db2.databaseUrl=jdbc:db2://127.0.0.1:50000/SAMPLE
|
||||
datasource.db2.databaseDriver=com.ibm.db2.jcc.DB2Driver
|
||||
datasource.db2.url=jdbc:db2://127.0.0.1:50000/SAMPLE
|
||||
#datasource.db2.driver=com.ibm.db2.jcc.DB2Driver
|
||||
|
||||
datasource.hana.username=EBEAN_TEST
|
||||
datasource.hana.password=Eb3an_test
|
||||
datasource.hana.databaseUrl=jdbc:sap://hxehost:39013/?databaseName=HXE
|
||||
datasource.hana.databaseDriver=com.sap.db.jdbc.Driver
|
||||
datasource.hana.url=jdbc:sap://hxehost:39013/?databaseName=HXE
|
||||
#datasource.hana.driver=com.sap.db.jdbc.Driver
|
||||
|
||||
# parameters for migration test
|
||||
datasource.migrationtest.username=SA
|
||||
datasource.migrationtest.password=SA
|
||||
datasource.migrationtest.databaseUrl=jdbc:h2:mem:migration
|
||||
datasource.migrationtest.databaseDriver=org.h2.Driver
|
||||
datasource.migrationtest.url=jdbc:h2:mem:migration
|
||||
ebean.migrationtest.applyPrefix=V
|
||||
ebean.migrationtest.ddl.generate=false
|
||||
ebean.migrationtest.ddl.run=false
|
||||
@@ -212,8 +202,7 @@ ebean.migrationtest.migration.strict=true
|
||||
# parameters for migration test
|
||||
datasource.migrationtest-history.username=SA
|
||||
datasource.migrationtest-history.password=SA
|
||||
datasource.migrationtest-history.databaseUrl=jdbc:h2:mem:migration
|
||||
datasource.migrationtest-history.databaseDriver=org.h2.Driver
|
||||
datasource.migrationtest-history.url=jdbc:h2:mem:migration
|
||||
ebean.migrationtest-history.applyPrefix=V
|
||||
ebean.migrationtest-history.ddl.generate=false
|
||||
ebean.migrationtest-history.ddl.run=false
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
10000,NEW,"Roland",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"Greg",14-FEB-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"Dan",29-SEP-2009,"14 someplace",Auckland,NZ
|
||||
,NEW,"ARob",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"BGreg",14-FEB-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"CDan",29-SEP-2009,"14 someplace",Auckland,NZ
|
||||
,NEW,"DRob",01-JAN-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"EGreg",14-FEB-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"FDan",29-SEP-2009,"14 someplace",Auckland,NZ
|
||||
10000,NEW,"Roland",01-Jan-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"Greg",14-Feb-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"Dan",29-Sep-2009,"14 someplace",Auckland,NZ
|
||||
,NEW,"ARob",01-Jan-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"BGreg",14-Feb-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"CDan",29-Sep-2009,"14 someplace",Auckland,NZ
|
||||
,NEW,"DRob",01-Jan-2009,"12 someplace",Auckland,NZ
|
||||
,ACTIVE,"EGreg",14-Feb-2009,"13 someplace",Sydney,AU
|
||||
,INACTIVE,"FDan",29-Sep-2009,"14 someplace",Auckland,NZ
|
||||
|
||||
|
Reference in New Issue
Block a user