Compare commits

..
Author SHA1 Message Date
rob bygrave d758590da4 [maven-release-plugin] prepare release ebean-12.3.2 2020-05-12 22:39:31 +12:00
rob bygrave 21a5efa9b9 Tidy tests - tidy up TestCsvReader and TestCsvReaderWithCallback 2020-05-12 21:28:31 +12:00
rob bygrave 55a2cb12bb #2007 - Encrypted fields unable to be mapped when using DtoQuery 2020-05-12 21:11:28 +12:00
rob bygrave 293700acc0 #2007 - Encrypted fields unable to be mapped when using DtoQuery 2020-05-12 20:25:56 +12:00
rob bygrave 8980a3b6fd No functional change - tidy DbEncrypt, AbstractDbEncrypt 2020-05-12 16:34:08 +12:00
rob bygrave 72efc5d7d6 #2005 - Mark Ebean as deprecated - migrate to io.ebean.Database (EbeanServer -> Database) 2020-05-11 23:15:02 +12:00
rob bygrave 84589fcce6 Bump the versions of ebean-maven-plugin and maven-surefire-plugin 2020-05-11 23:09:24 +12:00
rob bygrave a0e44aedf3 Fix IllegalStateException to use correct dependency io.ebean:ebean-elastic in error message 2020-05-11 20:29:58 +12:00
rob bygrave 41102aca35 Add clearBatch() on BatchedPstmt construction 2020-05-08 23:32:24 +12:00
rob bygrave 548cea432e Fix test UpdateQueryTest for PG 2020-05-08 23:22:23 +12:00
rob bygrave 592cb37693 Reset test default to H2 2020-05-08 23:01:59 +12:00
rob bygrave f2178bf0a6 #2003 - Bump ebean-datasource to 4.9.2 with optional driver 2020-05-04 12:41:14 +12:00
rob bygrave 5cae425b09 #2002 - Support maxRows with delete query 2020-05-04 12:28:52 +12:00
rob bygrave 94b78f1c2d [maven-release-plugin] prepare for next development iteration 2020-04-30 23:41:07 +12:00
rob bygrave 561affef0f [maven-release-plugin] prepare release ebean-12.3.1 2020-04-30 23:40:56 +12:00
Rob BygraveandGitHub 3310d2186d Remove autoCommitMode and explicitTransactionBeginMode (#1993)
These are legacy options that we don't want anyone using going forward.
2020-04-30 23:36:24 +12:00
Rob BygraveandGitHub 02bdace144 Change OraclePlatform to default to use Identity (rather than sequence) (#1976)
* Change OraclePlatform to default to use Identity

- Keep Oracle11Platform to default to Sequence
- Refactor rename Oracle10Ddl to OracleDdl

* Change OraclePlatform to default to use Identity

- DDL review changes in src/test

* Bump ebean-test-docker for StartOracle
2020-04-30 23:35:20 +12:00
rob bygrave 7c17098f17 Bump pom version to 12.3.1-SNAPSHOT 2020-04-30 23:34:13 +12:00
rob bygrave 6f194ce95d #2001 - Add convenient alternative to set read-only url (on the main DataSourceConfig) 2020-04-30 23:19:08 +12:00
rob bygrave dbe473d5a1 #1996 - Fix for MySQLSyntaxErrorException when update in bulk using idIn(). 2020-04-30 21:33:02 +12:00
rob bygrave ed0e9e7006 #1999 - Additionally support empty string for read only url with config.isAutoReadOnlyDataSource() 2020-04-29 22:15:15 +12:00
rob bygrave 2a03198393 #1999 - Additionally support "none" for read only url
"none" can then be used as a special literal value in configuration for "no read-only jdbc url"
2020-04-29 22:07:27 +12:00
rob bygrave 6f1472abe0 #2000 - Tests only - bump sql server to 2019-GA-ubuntu-16.04 2020-04-28 22:13:57 +12:00
rob bygrave 6dea4f0890 #1996 - MySQLSyntaxErrorException when update in bulk. 2020-04-28 21:24:25 +12:00
rob bygrave 4a4ec42cdc #1999 - Refactor read-only DataSource initialisation 2020-04-28 21:10:43 +12:00
rob bygrave 92ea8e3738 #1998 - Refactor internals rename createQueryTransaction() to createReadOnlyTransaction() 2020-04-25 17:38:54 +12:00
rob bygrave c349832d35 #1997 - Modify @Transactional(readOnly=true) to use the read only DataSource 2020-04-25 17:33:33 +12:00
rob bygrave 90493ad57d #1995 - Fix for DatabaseConfig.isLocalOnlyL2Cache() ... to set localL2Caching = true
This has the effect that the l2 cache notification occurs in the foreground when isLocalOnlyL2Cache is true (not background)
2020-04-23 13:11:20 +12:00
rob bygrave 5012f59371 [maven-release-plugin] prepare for next development iteration 2020-04-21 23:01:48 +12:00
rob bygrave 149e63a272 [maven-release-plugin] prepare release ebean-12.2.6 2020-04-21 23:01:37 +12:00
rob bygrave d52a00a8fb #1995 - ENH: Add DatabaseConfig.isLocalOnlyL2Cache() ... to support disabling l2 cache plugins 2020-04-21 23:00:13 +12:00
rob bygrave f0dcec95dd [maven-release-plugin] prepare for next development iteration 2020-04-21 22:00:29 +12:00
rob bygrave 2653931881 [maven-release-plugin] prepare release ebean-12.2.5 2020-04-21 22:00:18 +12:00
rob bygrave 85207086e6 #1995 - ENH: Add DatabaseConfig.isLocalOnlyL2Cache() ... to support disabling l2 cache plugins 2020-04-21 21:55:51 +12:00
rob bygrave d0b0b02d6a [maven-release-plugin] prepare for next development iteration 2020-04-15 08:47:38 +12:00
rob bygrave 34fa1def77 [maven-release-plugin] prepare release ebean-12.2.4 2020-04-15 08:47:26 +12:00
rob bygrave 9f1aa958fc Bump ebean-maven-plugin 2020-04-15 08:35:24 +12:00
rob bygrave cdc5eefc69 EntityBeanIntercept.isOrphanDelete() - Additional refactor for #1988 2020-04-14 23:17:56 +12:00
Jonas PöhlerandGitHub c9588586c9 Removing elements with @OrderColumn with a tree depth > 1 doesn't work (#1988)
* ADD: failing testcase for orderColumn when tree depth > 1

* FIX: no update with @OrderColumn on treeDepth > 1 and avoid needless updates

* ADD: failing testcase for removing models in oneToMany relation with @OrderColumn

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* ADD: failing test for faulty element reordering in a entityBean tree with version

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* FIX: incorrect behaviour when reordering or removing elements from collection with @OrderColumn.

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-14 23:07:00 +12:00
rob bygrave 52735179d9 Bump maven plugin 2020-04-14 22:44:46 +12:00
rob bygrave cef1fb9e80 #1992 - IllegalArgumentException: Expecting only yaml or properties file but got [ort] 2020-04-14 22:42:26 +12:00
rob bygrave c7e1964aae #1991 - NPE in MCompoundUniqueConstraint.<init>(MCompoundUniqueConstraint.java:66) 2020-04-14 21:28:03 +12:00
rob bygrave 6d43883f77 #1990 - NPE with @Cache and setting naturalKey to null 2020-04-14 20:57:42 +12:00
rob bygrave f06f99dfc3 Refactor remove unnecessary BeanDescriptorManager.setProfileIds() method
As it is no longer necessary (profileIds no longer used)
2020-04-12 17:13:54 +12:00
rob bygrave 41e600be45 Merge branch 'bugfix/order_column_l1_cache' of https://github.com/FOCONIS/ebean into FOCONIS-bugfix/order_column_l1_cache 2020-04-12 16:37:00 +12:00
Rob BygraveandGitHub 62a81c531a Merge pull request #1986 from FOCONIS/bugfix/order_column_reference_abstract
@OrderColumn is ignored on relations referencing a abstract inheritance-model
2020-04-12 16:32:15 +12:00
Rob BygraveandGitHub 2cb1a626c4 Merge pull request #1985 from FOCONIS/bugfix/order_column_tree_depth
Update is missing for relations with @OrderColumn from a tree depth > 1
2020-04-12 16:19:01 +12:00
Jonas Pöhler (JPo) 18cde36b9d FIX: cache not being cleared in persistence context on reorder with @OrderColumn
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-08 16:05:09 +02:00
Jonas Pöhler (JPo) e05b6b78ad ADD: failing testcase for not cleared beancache in persistence context on reorder with @OrderColumn
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-08 16:04:49 +02:00
rob bygrave 58c49deb06 [maven-release-plugin] prepare for next development iteration 2020-04-08 14:59:42 +12:00
rob bygrave 4a41e88162 [maven-release-plugin] prepare release ebean-12.2.3 2020-04-08 14:59:30 +12:00
rob bygrave 2e5becf48c Refactor rename to MySqlDataTimeZone and OracleDataTimeZone 2020-04-08 14:57:58 +12:00
rob bygrave 4094339407 #1984 - ENH: Add DB.script() ... to access ScriptRunner from DB 2020-04-08 14:13:57 +12:00
rob bygrave bf24949efb #1982 - conflict with eureka config generate StringIndexOutOfBoundsException with 12.2.1 version 2020-04-08 13:49:13 +12:00
Jonas Pöhler (JPo) 3b4549a7ee FIX: @OrderColumn not working when referencing the parent of a inheritance structure 2020-04-06 16:22:33 +02:00
Jonas Pöhler (JPo) f194fdb132 ADD: failing testcase for @OrderColumn working when referencing the parent of a inheritance structure 2020-04-06 16:08:21 +02:00
Jonas Pöhler (JPo) 2d274c46fa FIX: no update with @OrderColumn on treeDepth > 1 and avoid needless updates 2020-04-06 15:34:43 +02:00
Jonas Pöhler (JPo) b61e9af750 ADD: failing testcase for orderColumn when tree depth > 1 2020-04-06 15:14:23 +02:00
rob bygrave a01362abad #1980 Remove the volatile that was added for NPE in EntityBeanIntercept 2020-03-25 22:03:52 +13:00
Rob BygraveandGitHub 4387c662b6 Merge pull request #1981 from tobias-/issue_1980_NPE
Use temp variable to avoid NPE race
2020-03-25 21:06:00 +13:00
Tobias ecdd027b3e Use temp variable to avoid NPE race
resolve #1980
2020-03-25 07:01:32 +01:00
rob bygrave 2b0f572f4d [maven-release-plugin] prepare for next development iteration 2020-03-25 16:15:44 +13:00
89 changed files with 1827 additions and 1898 deletions
+7 -7
View File
@@ -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>
+16
View File
@@ -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>
+2 -1
View File
@@ -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);
+2
View File
@@ -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);
+24 -51
View File
@@ -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.
@@ -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,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;
}
}
@@ -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 {
@@ -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);
}
@@ -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,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);
@@ -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());
}
}
+1 -1
View File
@@ -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;
}
}
+5 -1
View File
@@ -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;
+26 -37
View File
@@ -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
+9 -9
View File
@@ -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
1 10000 NEW Roland 01-JAN-2009 01-Jan-2009 12 someplace Auckland NZ
2 ACTIVE Greg 14-FEB-2009 14-Feb-2009 13 someplace Sydney AU
3 INACTIVE Dan 29-SEP-2009 29-Sep-2009 14 someplace Auckland NZ
4 NEW ARob 01-JAN-2009 01-Jan-2009 12 someplace Auckland NZ
5 ACTIVE BGreg 14-FEB-2009 14-Feb-2009 13 someplace Sydney AU
6 INACTIVE CDan 29-SEP-2009 29-Sep-2009 14 someplace Auckland NZ
7 NEW DRob 01-JAN-2009 01-Jan-2009 12 someplace Auckland NZ
8 ACTIVE EGreg 14-FEB-2009 14-Feb-2009 13 someplace Sydney AU
9 INACTIVE FDan 29-SEP-2009 29-Sep-2009 14 someplace Auckland NZ