mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08d241d946 | ||
|
|
1c24ebf6dc |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.2.2</version>
|
||||
<version>12.1.14-SNAPSHOT</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>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -72,22 +72,22 @@
|
||||
to assist with IDE auto-completion with Ebean API
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-jsr305</artifactId>
|
||||
<version>1.0</version>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jsr305</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>2.2.4</version>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>6.11</version>
|
||||
<version>6.9</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -292,7 +292,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>12.2.2</version>
|
||||
<version>12.1.12</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -313,7 +313,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* <h3>getGeneratedKeys</h3>
|
||||
* <p>
|
||||
* Often with large batch inserts we want to turn off getGeneratedKeys. We do
|
||||
* this via {@link #setGetGeneratedKeys(boolean)}.
|
||||
* this via {@link #setBatchGetGeneratedKeys(boolean)}.
|
||||
* Also note that some JDBC drivers do not support getGeneratedKeys in JDBC batch mode.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
@@ -342,7 +342,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* </p>
|
||||
* <p>
|
||||
* We use {@link #flush()} to explicitly flush the batch and we can use
|
||||
* {@link #setFlushOnQuery(boolean)} and {@link #setFlushOnMixed(boolean)}
|
||||
* {@link #setBatchFlushOnQuery(boolean)} and {@link #setBatchFlushOnMixed(boolean)}
|
||||
* to control the automatic flushing behaviour.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -432,15 +432,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* number of objects and you don't care about getting back the ids.
|
||||
* </p>
|
||||
*/
|
||||
void setGetGeneratedKeys(boolean getGeneratedKeys);
|
||||
|
||||
/**
|
||||
* Deprecated renamed to setGetGeneratedKeys().
|
||||
*/
|
||||
@Deprecated
|
||||
default void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
setGetGeneratedKeys(getGeneratedKeys);
|
||||
}
|
||||
void setBatchGetGeneratedKeys(boolean getGeneratedKeys);
|
||||
|
||||
/**
|
||||
* By default when mixing UpdateSql (or CallableSql) with Beans the batch is
|
||||
@@ -457,15 +449,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* have a 2 step process (delayed binding).
|
||||
* </p>
|
||||
*/
|
||||
void setFlushOnMixed(boolean batchFlushOnMixed);
|
||||
|
||||
/**
|
||||
* Deprecated renamed to setFlushOnMixed().
|
||||
*/
|
||||
@Deprecated
|
||||
default void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
setFlushOnMixed(batchFlushOnMixed);
|
||||
}
|
||||
void setBatchFlushOnMixed(boolean batchFlushOnMixed);
|
||||
|
||||
/**
|
||||
* By default executing a query will automatically flush any batched
|
||||
@@ -475,15 +459,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* execute a query and the batch will not be automatically flushed.
|
||||
* </p>
|
||||
*/
|
||||
void setFlushOnQuery(boolean batchFlushOnQuery);
|
||||
|
||||
/**
|
||||
* Deprecated renamed to setFlushOnQuery().
|
||||
*/
|
||||
@Deprecated
|
||||
default void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
setFlushOnQuery(batchFlushOnQuery);
|
||||
}
|
||||
void setBatchFlushOnQuery(boolean batchFlushOnQuery);
|
||||
|
||||
/**
|
||||
* Return true if the batch (of persisted beans or executed UpdateSql etc)
|
||||
@@ -492,15 +468,7 @@ public interface Transaction extends AutoCloseable {
|
||||
* The default is for this to be true.
|
||||
* </p>
|
||||
*/
|
||||
boolean isFlushOnQuery();
|
||||
|
||||
/**
|
||||
* Deprecated renamed to isFlushOnQuery().
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean isBatchFlushOnQuery() {
|
||||
return isFlushOnQuery();
|
||||
}
|
||||
boolean isBatchFlushOnQuery();
|
||||
|
||||
/**
|
||||
* The batch will be flushing automatically but you can use this to explicitly
|
||||
|
||||
@@ -36,7 +36,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
private transient BeanLoader beanLoader;
|
||||
|
||||
private volatile transient PreGetterCallback preGetterCallback;
|
||||
private transient PreGetterCallback preGetterCallback;
|
||||
|
||||
private String ebeanServerName;
|
||||
|
||||
|
||||
@@ -222,8 +222,8 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Return true if this class is part of entity inheritance.
|
||||
*/
|
||||
protected boolean hasInheritance(Class<?> supCls) {
|
||||
return AnnotationUtil.typeHas(supCls, Inheritance.class)
|
||||
|| AnnotationUtil.has(supCls, DiscriminatorValue.class);
|
||||
return AnnotationUtil.findAnnotationRecursive(supCls, Inheritance.class) != null
|
||||
|| AnnotationUtil.findAnnotation(supCls, DiscriminatorValue.class) != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -255,12 +255,16 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Gets the table name from annotation.
|
||||
*/
|
||||
protected TableName getTableNameFromAnnotation(Class<?> beanClass) {
|
||||
final Table table = AnnotationUtil.typeGet(beanClass, Table.class);
|
||||
if (table != null && !isEmpty(table.name())) {
|
||||
|
||||
final Table t = AnnotationUtil.findAnnotationRecursive(beanClass, Table.class);
|
||||
|
||||
// Take the annotation if defined
|
||||
if (t != null && !isEmpty(t.name())) {
|
||||
// Note: empty catalog and schema are converted to null
|
||||
// Only need to convert quoted identifiers from annotations
|
||||
return new TableName(quoteIdentifiers(table.catalog()), quoteIdentifiers(table.schema()), quoteIdentifiers(table.name()));
|
||||
return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name()));
|
||||
}
|
||||
|
||||
// No annotation
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -34,11 +34,6 @@ public class PlatformConfig {
|
||||
*/
|
||||
private String databaseBooleanFalse;
|
||||
|
||||
/**
|
||||
* For DB's using sequences this is the number of sequence values prefetched.
|
||||
*/
|
||||
private int databaseSequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* Set for DB's that support both Sequence and Identity (and the default choice is not desired).
|
||||
*/
|
||||
@@ -79,7 +74,6 @@ public class PlatformConfig {
|
||||
public PlatformConfig(PlatformConfig platformConfig) {
|
||||
this.databaseBooleanFalse = platformConfig.databaseBooleanFalse;
|
||||
this.databaseBooleanTrue = platformConfig.databaseBooleanTrue;
|
||||
this.databaseSequenceBatchSize = platformConfig.databaseSequenceBatchSize;
|
||||
this.idType = platformConfig.idType;
|
||||
this.geometrySRID = platformConfig.geometrySRID;
|
||||
this.dbUuid = platformConfig.dbUuid;
|
||||
@@ -173,20 +167,6 @@ public class PlatformConfig {
|
||||
this.databaseBooleanFalse = databaseBooleanFalse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of DB sequence values that should be preallocated.
|
||||
*/
|
||||
public int getDatabaseSequenceBatchSize() {
|
||||
return databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of DB sequence values that should be preallocated.
|
||||
*/
|
||||
public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
|
||||
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Geometry SRID.
|
||||
*/
|
||||
@@ -294,7 +274,6 @@ public class PlatformConfig {
|
||||
public void loadSettings(PropertiesWrapper p) {
|
||||
|
||||
idType = p.getEnum(IdType.class, "idType", idType);
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class ServerConfig {
|
||||
* Having this on and registering entity classes means we don't need to manually
|
||||
* write that code or use classpath scanning to find entity classes.
|
||||
*/
|
||||
private boolean loadModuleInfo = true;
|
||||
private boolean loadModuleInfo;
|
||||
|
||||
/**
|
||||
* List of interesting classes such as entities, embedded, ScalarTypes,
|
||||
@@ -1050,18 +1050,6 @@ public class ServerConfig {
|
||||
this.lazyLoadBatchSize = lazyLoadBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of sequences to fetch/preallocate when using DB sequences.
|
||||
* <p>
|
||||
* This is a performance optimisation to reduce the number times Ebean
|
||||
* requests a sequence to be used as an Id for a bean (aka reduce network
|
||||
* chatter).
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
|
||||
platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default JDBC fetchSize hint for findList queries.
|
||||
*/
|
||||
@@ -1828,32 +1816,6 @@ public class ServerConfig {
|
||||
this.platformConfig.setDatabaseBooleanFalse(databaseFalse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of DB sequence values that should be preallocated.
|
||||
*/
|
||||
public int getDatabaseSequenceBatchSize() {
|
||||
return platformConfig.getDatabaseSequenceBatchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of DB sequence values that should be preallocated and cached
|
||||
* by Ebean.
|
||||
* <p>
|
||||
* This is only used for DB's that use sequences and is a performance
|
||||
* optimisation. This reduces the number of times Ebean needs to get a
|
||||
* sequence value from the Database reducing network chatter.
|
||||
* </p>
|
||||
* <p>
|
||||
* By default this value is 10 so when we need another Id (and don't have one
|
||||
* in our cache) Ebean will fetch 10 id's from the database. Note that when
|
||||
* the cache drops to have full (which is 5 by default) Ebean will fetch
|
||||
* another batch of Id's in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public void setDatabaseSequenceBatch(int databaseSequenceBatchSize) {
|
||||
this.platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database platform name (can be null).
|
||||
* <p>
|
||||
@@ -3298,17 +3260,6 @@ public class ServerConfig {
|
||||
return loadModuleInfo && classes.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set false to turn off automatic registration of entity beans.
|
||||
* <p>
|
||||
* When using query beans that also generates a module info class that
|
||||
* can register the entity bean classes (to avoid classpath scanning).
|
||||
* This is on by default and setting this to false turns it off.
|
||||
*/
|
||||
public void setLoadModuleInfo(boolean loadModuleInfo) {
|
||||
this.loadModuleInfo = loadModuleInfo;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -110,10 +110,6 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected DbIdentity dbIdentity = new DbIdentity();
|
||||
|
||||
protected boolean sequenceBatchMode = true;
|
||||
|
||||
protected int sequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* The history support for this database platform.
|
||||
*/
|
||||
@@ -146,7 +142,7 @@ public class DatabasePlatform {
|
||||
|
||||
protected String truncateTable = "truncate table %s";
|
||||
|
||||
protected String columnAliasPrefix;
|
||||
protected String columnAliasPrefix = "c";
|
||||
|
||||
/**
|
||||
* Use a BackTick ` at the beginning and end of table or column names that you
|
||||
@@ -235,7 +231,6 @@ public class DatabasePlatform {
|
||||
* Configure the platform given the server configuration.
|
||||
*/
|
||||
public void configure(PlatformConfig config) {
|
||||
this.sequenceBatchSize = config.getDatabaseSequenceBatchSize();
|
||||
this.caseSensitiveCollation = config.isCaseSensitiveCollation();
|
||||
configureIdType(config.getIdType());
|
||||
configure(config, config.isAllQuotedIdentifiers());
|
||||
@@ -298,20 +293,6 @@ public class DatabasePlatform {
|
||||
return platform.name().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are using Sequence batch mode rather than STEP.
|
||||
*/
|
||||
public boolean isSequenceBatchMode() {
|
||||
return sequenceBatchMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false to not use sequence batch mode but instead STEP mode.
|
||||
*/
|
||||
public void setSequenceBatchMode(boolean sequenceBatchMode) {
|
||||
this.sequenceBatchMode = sequenceBatchMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this database platform supports native ILIKE expression.
|
||||
*/
|
||||
@@ -381,13 +362,13 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return a DB Sequence based IdGenerator.
|
||||
*
|
||||
* @param be the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds the DataSource
|
||||
* @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
|
||||
* @param seqName the name of the sequence
|
||||
* @param be the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds the DataSource
|
||||
* @param increment the sequence allocation size as defined by mapping (defaults to 50)
|
||||
* @param seqName the name of the sequence
|
||||
*/
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ public class DbPlatformTypeMapping {
|
||||
|
||||
} else {
|
||||
put(DbType.VARCHAR, new DbPlatformType("varchar", 255));
|
||||
put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3));
|
||||
put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
|
||||
put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
|
||||
put(DbType.BINARY, new DbPlatformType("binary", 255));
|
||||
put(DbType.CHAR, new DbPlatformType("char", 1));
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Database sequence based IdGenerator using Sequence Step 1 but batch fetch many sequence values.
|
||||
*/
|
||||
public abstract class SequenceBatchIdGenerator extends SequenceIdGenerator {
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*
|
||||
*/
|
||||
public SequenceBatchIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* If allocateSize is large load some sequences in a background thread.
|
||||
* <p>
|
||||
* For example, when inserting a bean with a cascade on a OneToMany with many
|
||||
* beans Ebean can call this to ensure .
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void preAllocateIds(int requestSize) {
|
||||
if (allocationSize > 1 && requestSize > allocationSize) {
|
||||
// only bother if allocateSize is bigger than
|
||||
// the normal loading batchSize
|
||||
if (requestSize > 100) {
|
||||
// max out at 100 for now
|
||||
requestSize = 100;
|
||||
}
|
||||
loadInBackground(requestSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the next set of Ids as the next value plus all the following numbers up to the step size.
|
||||
*/
|
||||
@Override
|
||||
protected List<Long> readIds(ResultSet resultSet, int loadSize) throws SQLException {
|
||||
|
||||
List<Long> newIds = new ArrayList<>(loadSize);
|
||||
while (resultSet.next()) {
|
||||
newIds.add(resultSet.getLong(1));
|
||||
}
|
||||
return newIds;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
this.allocationSize = allocationSize;
|
||||
}
|
||||
|
||||
public abstract String getSql(int batchSize);
|
||||
public abstract String getSql();
|
||||
|
||||
/**
|
||||
* Returns the sequence name.
|
||||
@@ -102,7 +102,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
if (size > 0) {
|
||||
maybeLoadMoreInBackground(size);
|
||||
} else {
|
||||
loadMore(allocationSize);
|
||||
loadMore();
|
||||
}
|
||||
return idList.pollFirst();
|
||||
}
|
||||
@@ -116,8 +116,8 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadMore(int requestSize) {
|
||||
List<Long> newIds = getMoreIds(requestSize);
|
||||
private void loadMore() {
|
||||
List<Long> newIds = getMoreIds();
|
||||
synchronized (monitor) {
|
||||
idList.addAll(newIds);
|
||||
}
|
||||
@@ -139,7 +139,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
currentlyBackgroundLoading = true;
|
||||
|
||||
backgroundExecutor.execute(() -> {
|
||||
loadMore(requestSize);
|
||||
loadMore();
|
||||
synchronized (backgroundLoadMonitor) {
|
||||
currentlyBackgroundLoading = false;
|
||||
}
|
||||
@@ -150,14 +150,14 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
/**
|
||||
* Read the resultSet returning the list of Id values.
|
||||
*/
|
||||
protected abstract List<Long> readIds(ResultSet resultSet, int loadSize) throws SQLException;
|
||||
protected abstract List<Long> readIds(ResultSet resultSet) throws SQLException;
|
||||
|
||||
/**
|
||||
* Get more Id's by executing a query and reading the Id's returned.
|
||||
*/
|
||||
protected List<Long> getMoreIds(int requestSize) {
|
||||
protected List<Long> getMoreIds() {
|
||||
|
||||
String sql = getSql(requestSize);
|
||||
String sql = getSql();
|
||||
|
||||
Connection connection = null;
|
||||
PreparedStatement statement = null;
|
||||
@@ -168,7 +168,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
statement = connection.prepareStatement(sql);
|
||||
resultSet = statement.executeQuery();
|
||||
|
||||
List<Long> newIds = readIds(resultSet, requestSize);
|
||||
List<Long> newIds = readIds(resultSet);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("seq:{} loaded:{} sql:{}", seqName, newIds.size(), sql);
|
||||
}
|
||||
|
||||
@@ -13,19 +13,25 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class SequenceStepIdGenerator extends SequenceIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
/**
|
||||
* Construct with stepSize (typically 50).
|
||||
*/
|
||||
protected SequenceStepIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
protected SequenceStepIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int stepSize, String nextSql) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = nextSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return nextSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the next set of Ids as the next value plus all the following numbers up to the step size.
|
||||
*/
|
||||
@Override
|
||||
protected List<Long> readIds(ResultSet resultSet, int ignoreRequestSize) throws SQLException {
|
||||
|
||||
protected List<Long> readIds(ResultSet resultSet) throws SQLException {
|
||||
List<Long> newIds = new ArrayList<>(allocationSize);
|
||||
if (resultSet.next()) {
|
||||
long start = resultSet.getLong(1);
|
||||
|
||||
@@ -16,8 +16,10 @@ public class ClickHousePlatform extends DatabasePlatform {
|
||||
//this.dbEncrypt =
|
||||
//this.historySupport =
|
||||
//this.exceptionTranslator =
|
||||
|
||||
this.nativeUuidType = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
this.columnAliasPrefix = null;
|
||||
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
@@ -32,7 +34,7 @@ public class ClickHousePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("UInt16", false));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("UInt32", false));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("UInt64", false));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("Decimal", 16, 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("Decimal", 16,4));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("Float64", false));
|
||||
|
||||
dbTypeMap.put(DbType.DATE, new DbPlatformType("Date", false));
|
||||
|
||||
@@ -42,7 +42,8 @@ public class DB2Platform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("bigint", false));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("real"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 15));
|
||||
|
||||
persistBatchOnCascade = PersistBatch.NONE;
|
||||
}
|
||||
|
||||
@@ -51,9 +52,8 @@ public class DB2Platform extends DatabasePlatform {
|
||||
* sequence values.
|
||||
*/
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
|
||||
return new DB2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new DB2Sequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* DB2 specific sequence Id Generator.
|
||||
*/
|
||||
class DB2Sequence extends SequenceStepIdGenerator {
|
||||
|
||||
DB2Sequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "values nextval for " + seqName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* DB2 specific sequence Id Generator.
|
||||
*/
|
||||
public class DB2SequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
|
||||
private final String baseSql;
|
||||
private final String unionBaseSql;
|
||||
|
||||
/**
|
||||
* Construct given a dataSource and sql to return the next sequence value.
|
||||
*/
|
||||
public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "values nextval for " + seqName;
|
||||
this.unionBaseSql = " union " + baseSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseSql);
|
||||
for (int i = 1; i < batchSize; i++) {
|
||||
sb.append(unionBaseSql);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebean.config.dbplatform.h2;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
class H2DbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
H2DbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "select " + seqName + ".nextval");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ public class H2Platform extends DatabasePlatform {
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
this.columnAliasPrefix = null;
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("50200","HYT00")
|
||||
@@ -41,13 +42,9 @@ public class H2Platform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a H2 specific sequence IdGenerator that supports batch fetching
|
||||
* sequence values.
|
||||
*/
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new H2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new H2DbSequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.ebean.config.dbplatform.h2;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* H2 specific sequence Id Generator.
|
||||
*/
|
||||
public class H2SequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
|
||||
private final String baseSql;
|
||||
private final String unionBaseSql;
|
||||
|
||||
/**
|
||||
* Construct given a dataSource and sql to return the next sequence value.
|
||||
*/
|
||||
public H2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "select " + seqName + ".nextval";
|
||||
this.unionBaseSql = " union " + baseSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseSql);
|
||||
for (int i = 1; i < batchSize; i++) {
|
||||
sb.append(unionBaseSql);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ public class HanaPlatform extends DatabasePlatform {
|
||||
this.sqlLimiter = new HanaSqlLimiter();
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.supportsResultSetConcurrencyModeUpdatable = false;
|
||||
this.columnAliasPrefix = null;
|
||||
this.historySupport = new HanaHistorySupport();
|
||||
this.basicSqlLimiter = new HanaBasicSqlLimiter();
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
package io.ebean.config.dbplatform.hsqldb;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.h2.H2DbEncrypt;
|
||||
import io.ebean.config.dbplatform.h2.H2SequenceIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* H2 specific platform.
|
||||
*/
|
||||
public class HsqldbPlatform extends DatabasePlatform {
|
||||
|
||||
public HsqldbPlatform() {
|
||||
super();
|
||||
this.platform = Platform.HSQLDB;
|
||||
this.dbEncrypt = new H2DbEncrypt();
|
||||
this.truncateTable = "delete from %s";
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new H2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Hsqldb specific support.
|
||||
*/
|
||||
package io.ebean.config.dbplatform.hsqldb;
|
||||
@@ -31,6 +31,7 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
this.inlineSqlUpdateLimit = true;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
this.historySupport = new MySqlHistorySupport();
|
||||
this.columnAliasPrefix = null;
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
@@ -23,6 +23,7 @@ public class NuoDbPlatform extends DatabasePlatform {
|
||||
this.idInExpandedForm = true;
|
||||
this.supportsResultSetConcurrencyModeUpdatable = false;
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.columnAliasPrefix = null;
|
||||
this.likeClauseRaw = "like ?";
|
||||
this.historySupport = new NuoDbHistorySupport();
|
||||
//this.dbEncrypt = ...
|
||||
@@ -43,8 +44,8 @@ public class NuoDbPlatform extends DatabasePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new NuoDbSequence(be, ds, seqName, stepSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new NuoDbSequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,20 +5,10 @@ import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public class NuoDbSequence extends SequenceStepIdGenerator {
|
||||
class NuoDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*/
|
||||
public NuoDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = "select next value for " + seqName + " from dual";
|
||||
NuoDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "select next value for " + seqName + " from dual");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return nextSql;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
class OracleDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
OracleDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "select " + seqName + ".nextval from dual");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,7 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
public OraclePlatform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE;
|
||||
this.columnAliasPrefix = null;
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.maxTableNameLength = 30;
|
||||
this.maxConstraintNameLength = 30;
|
||||
@@ -62,7 +63,8 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("number", 19, 4));
|
||||
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("number", 5));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("number", 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 16, 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 38));
|
||||
|
||||
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("varchar2", 255));
|
||||
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("blob"));
|
||||
@@ -74,8 +76,8 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new OracleSequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new OracleDbSequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Oracle specific sequence Id Generator.
|
||||
*/
|
||||
public class OracleSequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
|
||||
private final String baseSql;
|
||||
|
||||
/**
|
||||
* Construct given a dataSource and sql to return the next sequence value.
|
||||
*/
|
||||
public OracleSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "select " + seqName + ".nextval, a from (select level as a FROM dual CONNECT BY level <= ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return baseSql + batchSize + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebean.config.dbplatform.postgres;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
class PostgresDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
PostgresDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "select nextval('" + seqName + "')");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,6 +34,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
this.blobDbType = Types.LONGVARBINARY;
|
||||
this.clobDbType = Types.VARCHAR;
|
||||
this.nativeUuidType = true;
|
||||
this.columnAliasPrefix = null;
|
||||
this.truncateTable = "truncate table %s cascade";
|
||||
this.dbEncrypt = new PostgresDbEncrypt();
|
||||
this.historySupport = new PostgresHistorySupport();
|
||||
@@ -70,6 +71,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("timestamptz"));
|
||||
|
||||
dbTypeMap.put(DbType.BINARY, dbBytea);
|
||||
@@ -107,9 +109,8 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
* Create a Postgres specific sequence IdGenerator.
|
||||
*/
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
|
||||
return new PostgresSequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new PostgresDbSequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.ebean.config.dbplatform.postgres;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* Postgres specific sequence Id Generator.
|
||||
*/
|
||||
public class PostgresSequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
|
||||
private final String baseSql;
|
||||
|
||||
/**
|
||||
* Construct given a dataSource and sql to return the next sequence value.
|
||||
*/
|
||||
public PostgresSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "select nextval('" + seqName + "'), s.generate_series from (select generate_series from generate_series(1,";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return baseSql + batchSize + ") ) as s";
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,8 @@ public class SqlAnywherePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 16, 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
|
||||
|
||||
dbTypeMap.put(DbType.BLOB, new DbPlatformType("binary(4500)"));
|
||||
dbTypeMap.put(DbType.CLOB, new DbPlatformType("long varchar"));
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("long binary"));
|
||||
|
||||
@@ -12,6 +12,7 @@ public class SqlServer17Platform extends SqlServerBasePlatform {
|
||||
public SqlServer17Platform() {
|
||||
super();
|
||||
this.platform = Platform.SQLSERVER17;
|
||||
this.columnAliasPrefix = null;
|
||||
this.nativeUuidType = true;
|
||||
this.dbTypeMap.put(DbType.UUID, new DbPlatformType("uniqueidentifier", false));
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
this.sequenceBatchMode = false;
|
||||
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
@@ -62,7 +61,9 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 16, 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
|
||||
|
||||
|
||||
dbTypeMap.put(DbType.DATE, new DbPlatformType("date"));
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("time"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime2"));
|
||||
@@ -93,12 +94,9 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
sb.append('[').append(ch).append(']');
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Postgres specific sequence IdGenerator.
|
||||
*/
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new SqlServerStepSequence(be, ds, seqName, stepSize);
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int increment, String seqName) {
|
||||
return new SqlServerDbSequence(be, ds, seqName, increment);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.ebean.config.dbplatform.sqlserver;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
class SqlServerDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
SqlServerDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize, "select next value for " + seqName);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.ebean.config.dbplatform.sqlserver;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public class SqlServerStepSequence extends SequenceStepIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*/
|
||||
public SqlServerStepSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = "select next value for "+seqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return nextSql;
|
||||
}
|
||||
}
|
||||
@@ -171,7 +171,7 @@ public class DefaultCsvCallback<T> implements CsvCallback<T> {
|
||||
logger.info("Creating transaction, batchSize[" + persistBatchSize + "]");
|
||||
transaction.setBatchMode(true);
|
||||
transaction.setBatchSize(persistBatchSize);
|
||||
transaction.setGetGeneratedKeys(false);
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
} else {
|
||||
// explicitly turn off JDBC batching in case
|
||||
|
||||
@@ -1,98 +1,304 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import io.ebean.annotation.Formula;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.Where;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Annotation utility methods to find annotations.
|
||||
* Annotation utility methods to find annotations recursively - taken from the spring framework.
|
||||
*/
|
||||
public class AnnotationUtil {
|
||||
|
||||
/**
|
||||
* Determine if the supplied {@link Annotation} is defined in the core JDK {@code java.lang.annotation} package.
|
||||
*/
|
||||
public static boolean notJavaLang(Annotation annotation) {
|
||||
return !annotation.annotationType().getName().startsWith("java.lang.annotation");
|
||||
public static boolean isInJavaLangAnnotationPackage(Annotation annotation) {
|
||||
return annotation.annotationType().getName().startsWith("java.lang.annotation");
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple get on field or method with no meta-annotations or platform filtering.
|
||||
* Find a single {@link Annotation} of {@code annotationType} on the supplied {@link AnnotatedElement}.
|
||||
* <p>
|
||||
* Meta-annotations will be searched if the annotation is not <em>directly present</em> on the supplied element.
|
||||
* <p>
|
||||
* <strong>Warning</strong>: this method operates generically on annotated elements. In other words, this method
|
||||
* does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
|
||||
* It also does not filter out platform dependent annotations!
|
||||
*/
|
||||
public static <A extends Annotation> A get(AnnotatedElement element, Class<A> annotation) {
|
||||
return element.getAnnotation(annotation);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
// check if directly present, if not, start search for meta-annotations.
|
||||
Annotation[] anns = annotatedElement.getAnnotations();
|
||||
if (anns.length == 0) {
|
||||
return null; // no annotations present, so searching for meta annotations not required
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple has with no meta-annotations or platform filtering.
|
||||
*/
|
||||
public static <A extends Annotation> boolean has(AnnotatedElement element, Class<A> annotation) {
|
||||
return get(element, annotation) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* On class get the annotation - includes inheritance.
|
||||
*/
|
||||
public static <A extends Annotation> A typeGet(Class<?> clazz, Class<A> annotationType) {
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
final A val = clazz.getAnnotation(annotationType);
|
||||
if (val != null) {
|
||||
return val;
|
||||
// As we need the anns array anyway, we iterate over this instead
|
||||
// of using annotatedElement.getAnnotation(...) which is synchronized internally
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
|
||||
return findAnnotation(anns, annotationType, new HashSet<>());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a single {@link Annotation} of {@code annotationType} on the supplied class.
|
||||
* <p>Meta-annotations will be searched if the annotation is not directly present on
|
||||
* the supplied element.
|
||||
* <p><strong>Note</strong>: this method searches for annotations at class & superClass(es)!
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <A extends Annotation> A findAnnotationRecursive(Class<?> clazz, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
// check if directly present, if not, start search for meta-annotations.
|
||||
Annotation[] anns = clazz.getAnnotations();
|
||||
if (anns.length != 0) {
|
||||
for (Annotation ann : anns) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
|
||||
A ann = findAnnotation(anns, annotationType, new HashSet<>());
|
||||
if (ann != null) {
|
||||
return ann;
|
||||
}
|
||||
}
|
||||
// no meta-annotation present at this class - traverse to superclass
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first annotation of a type for this platform. (if annotation is platform specific, otherwise first
|
||||
* found annotation is returned)
|
||||
*/
|
||||
public static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType, Platform platform) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
Set<A> anns = findAnnotations(annotatedElement, annotationType);
|
||||
return getPlatformMatchingAnnotation(anns, platform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all annotations recusively for a class and its superclasses or interfaces.
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> findAnnotationsRecursive(Class<?> clazz, Class<A> annotationType) {
|
||||
Objects.requireNonNull(annotationType);
|
||||
Set<A> ret = new LinkedHashSet<>();
|
||||
Set<Annotation> visited = new HashSet<>();
|
||||
Set<Class<?>> visitedInterfaces = new HashSet<>();
|
||||
while (clazz != null && !clazz.getName().startsWith("java.lang.")) {
|
||||
findMetaAnnotationsRecursive(clazz, annotationType, ret, visited, visitedInterfaces);
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the interfaces for annotations.
|
||||
*/
|
||||
private static <A extends Annotation> void findMetaAnnotationsRecursive(Class<?> clazz,
|
||||
Class<A> annotationType, Set<A> ret,
|
||||
Set<Annotation> visited, Set<Class<?>> visitedInterfaces) {
|
||||
findMetaAnnotations(clazz, annotationType, ret, visited);
|
||||
for (Class<?> iface : clazz.getInterfaces()) {
|
||||
if (!iface.getName().startsWith("java.lang.") && visitedInterfaces.add(iface)) {
|
||||
findMetaAnnotationsRecursive(iface, annotationType, ret, visited, visitedInterfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the search algorithm avoiding endless recursion by tracking which
|
||||
* annotations have already been visited.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <A extends Annotation> A findAnnotation(Annotation[] anns, Class<A> annotationType, Set<Annotation> visited) {
|
||||
|
||||
|
||||
for (Annotation ann : anns) {
|
||||
if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
|
||||
Annotation[] metaAnns = ann.annotationType().getAnnotations();
|
||||
for (Annotation metaAnn : metaAnns) {
|
||||
if (metaAnn.annotationType() == annotationType) {
|
||||
return (A) metaAnn;
|
||||
}
|
||||
}
|
||||
if (metaAnns.length > 0) {
|
||||
A annotation = findAnnotation(metaAnns, annotationType, visited);
|
||||
if (annotation != null) {
|
||||
return annotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* On class get all the annotations - includes inheritance.
|
||||
* Find all {@link Annotation}s of {@code annotationType} on the supplied {@link AnnotatedElement}.
|
||||
* <p>
|
||||
* Meta-annotations will be searched if the annotation is not <em>directly present</em> on the supplied element.
|
||||
* <p>
|
||||
* <strong>Warning</strong>: this method operates generically on annotated elements. In other words, this method
|
||||
* does not execute specialized search algorithms for classes or methods. It only traverses through Annotations!
|
||||
*/
|
||||
public static <A extends Annotation> Set<A> typeGetAll(Class<?> clazz, Class<A> annotationType) {
|
||||
Set<A> result = new LinkedHashSet<>();
|
||||
typeGetAllCollect(clazz, annotationType, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static <A extends Annotation> void typeGetAllCollect(Class<?> clazz, Class<A> annotationType, Set<A> result) {
|
||||
while (clazz != null && clazz != Object.class) {
|
||||
final A val = clazz.getAnnotation(annotationType);
|
||||
if (val != null) {
|
||||
result.add(val);
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
public static <A extends Annotation> Set<A> findAnnotations(AnnotatedElement annotatedElement, Class<A> annotationType) {
|
||||
if (annotationType == null) {
|
||||
return null;
|
||||
}
|
||||
Set<A> ret = new LinkedHashSet<>();
|
||||
findMetaAnnotations(annotatedElement, annotationType, ret, new HashSet<>());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* On class simple check for annotation - includes inheritance.
|
||||
* Perform the search algorithm avoiding endless recursion by tracking which
|
||||
* annotations have already been visited.
|
||||
*/
|
||||
public static <A extends Annotation> boolean typeHas(Class<?> clazz, Class<A> annotation) {
|
||||
return typeGet(clazz, annotation) != null;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <A extends Annotation> void findMetaAnnotations(AnnotatedElement annotatedElement, Class<A> annotationType, Set<A> ret, Set<Annotation> visited) {
|
||||
|
||||
/**
|
||||
* Find all the annotations for the filter searching meta-annotations.
|
||||
*/
|
||||
public static Set<Annotation> metaFindAllFor(AnnotatedElement element, Set<Class<?>> filter) {
|
||||
Set<Annotation> visited = new HashSet<>();
|
||||
Set<Annotation> result = new LinkedHashSet<>();
|
||||
for (Annotation ann : element.getAnnotations()) {
|
||||
metaAdd(ann, filter, visited, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void metaAdd(Annotation ann, Set<Class<?>> filter, Set<Annotation> visited, Set<Annotation> result) {
|
||||
if (notJavaLang(ann) && visited.add(ann)) {
|
||||
if (filter.contains(ann.annotationType())) {
|
||||
result.add(ann);
|
||||
} else {
|
||||
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
|
||||
metaAdd(metaAnn, filter, visited, result);
|
||||
Annotation[] anns = annotatedElement.getAnnotations();
|
||||
for (Annotation ann : anns) {
|
||||
if (!isInJavaLangAnnotationPackage(ann) && visited.add(ann)) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
ret.add((A) ann);
|
||||
} else {
|
||||
Method repeatableValueMethod = getRepeatableValueMethod(ann, annotationType);
|
||||
if (repeatableValueMethod != null) {
|
||||
try {
|
||||
A[] repeatedAnns = (A[]) repeatableValueMethod.invoke(ann);
|
||||
for (Annotation repeatedAnn : repeatedAnns) {
|
||||
ret.add((A) repeatedAnn);
|
||||
findMetaAnnotations(repeatedAnn.annotationType(), annotationType, ret, visited);
|
||||
}
|
||||
} catch (Exception e) { // catch all exceptions (thrown by invoke)
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
findMetaAnnotations(ann.annotationType(), annotationType, ret, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// caches for getRepeatableValueMethod
|
||||
private static Method getNullMethod() {
|
||||
try {
|
||||
return AnnotationUtil.class.getDeclaredMethod("getNullMethod");
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static final ConcurrentMap<Annotation, Method> valueMethods = new ConcurrentHashMap<>();
|
||||
// only a non-null-marker the valueMethods - Cache
|
||||
private static final Method nullMethod = getNullMethod();
|
||||
|
||||
|
||||
/**
|
||||
* Returns the <code>value()</code> method for a possible containerAnnotation.
|
||||
* Method is retuned only, if its signature is <code>array of containingType</code>.
|
||||
*/
|
||||
private static <A extends Annotation> Method getRepeatableValueMethod(
|
||||
Annotation containerAnnotation, Class<A> containingType) {
|
||||
|
||||
Method method = valueMethods.get(containerAnnotation);
|
||||
if (method == null) {
|
||||
try {
|
||||
method = containerAnnotation.annotationType().getMethod("value");
|
||||
} catch (NoSuchMethodException e) {
|
||||
method = nullMethod;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
Method prev = valueMethods.putIfAbsent(containerAnnotation, method);
|
||||
method = prev == null ? method : prev;
|
||||
}
|
||||
if (method != nullMethod) {
|
||||
Class<?> retType = method.getReturnType();
|
||||
if (retType.isArray() && retType.getComponentType() == containingType) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds a suitable annotation from <code>Set<T> anns</code> for this platform.
|
||||
* To distinguish between platforms, annotation type <code>T</code> must define
|
||||
* a method withthis signature:
|
||||
* <p>
|
||||
* <code>Class<? extends DatabasePlatform>[] platforms() default {};</code>
|
||||
* </p>
|
||||
* The finding rules are:
|
||||
* <ol>
|
||||
* <li>Check if T has method "platforms" if not, return <code>ann[0]</code></code>
|
||||
* <li>find the annotation that is defined for <code>databasePlatform</code></li>
|
||||
* <li>otherwise return the annotation for default platform (platforms = {})</li>
|
||||
* <li>return null
|
||||
* </ol>
|
||||
* (This mechanism is currently used by {@link Where} and {@link Formula})
|
||||
*/
|
||||
public static <T extends Annotation> T getPlatformMatchingAnnotation(Set<T> anns, Platform matchPlatform) {
|
||||
if (anns.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Method getPlatformsMethod = null;
|
||||
T fallback = null;
|
||||
for (T ann : anns) {
|
||||
try {
|
||||
if (getPlatformsMethod == null) {
|
||||
getPlatformsMethod = ann.getClass().getMethod("platforms");
|
||||
}
|
||||
if (!Platform[].class.isAssignableFrom(getPlatformsMethod.getReturnType())) {
|
||||
return ann;
|
||||
}
|
||||
Platform[] platforms = (Platform[]) getPlatformsMethod.invoke(ann);
|
||||
if (platforms.length == 0) {
|
||||
fallback = ann;
|
||||
} else {
|
||||
for (Platform platform : platforms) {
|
||||
if (matchPlatform == platform) {
|
||||
return ann;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
return ann; // not platform specific - return first one
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,13 +71,13 @@ public class ScopeTrans {
|
||||
restoreBatchOnCascade = transaction.isBatchOnCascade();
|
||||
restoreBatchSize = transaction.getBatchSize();
|
||||
restoreBatchGeneratedKeys = transaction.getBatchGetGeneratedKeys();
|
||||
restoreBatchFlushOnQuery = transaction.isFlushOnQuery();
|
||||
restoreBatchFlushOnQuery = transaction.isBatchFlushOnQuery();
|
||||
}
|
||||
if (txScope.isBatchSet()) {
|
||||
transaction.setBatchMode(txScope.isBatchMode());
|
||||
}
|
||||
if (!txScope.isFlushOnQuery()) {
|
||||
transaction.setFlushOnQuery(false);
|
||||
transaction.setBatchFlushOnQuery(false);
|
||||
}
|
||||
if (txScope.isBatchOnCascadeSet()) {
|
||||
transaction.setBatchOnCascade(txScope.isBatchOnCascade());
|
||||
@@ -86,7 +86,7 @@ public class ScopeTrans {
|
||||
transaction.setBatchSize(txScope.getBatchSize());
|
||||
}
|
||||
if (txScope.isSkipGeneratedKeys()) {
|
||||
transaction.setGetGeneratedKeys(false);
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ public class ScopeTrans {
|
||||
transaction.commit();
|
||||
} else {
|
||||
nestedCommit = true;
|
||||
transaction.setFlushOnQuery(restoreBatchFlushOnQuery);
|
||||
transaction.setBatchFlushOnQuery(restoreBatchFlushOnQuery);
|
||||
if (restoreBatch != null) {
|
||||
transaction.setBatchMode(restoreBatch);
|
||||
}
|
||||
@@ -147,7 +147,7 @@ public class ScopeTrans {
|
||||
transaction.setBatchSize(restoreBatchSize);
|
||||
}
|
||||
if (restoreBatchGeneratedKeys != null) {
|
||||
transaction.setGetGeneratedKeys(restoreBatchGeneratedKeys);
|
||||
transaction.setBatchGetGeneratedKeys(restoreBatchGeneratedKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,8 +269,8 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
transaction.setGetGeneratedKeys(getGeneratedKeys);
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
transaction.setBatchGetGeneratedKeys(getGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,18 +279,18 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
transaction.setFlushOnMixed(batchFlushOnMixed);
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
transaction.setBatchFlushOnMixed(batchFlushOnMixed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
transaction.setFlushOnQuery(batchFlushOnQuery);
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
transaction.setBatchFlushOnQuery(batchFlushOnQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlushOnQuery() {
|
||||
return transaction.isFlushOnQuery();
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return transaction.isBatchFlushOnQuery();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,7 +14,6 @@ import io.ebean.config.dbplatform.cockroach.CockroachPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2Platform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
@@ -814,8 +813,6 @@ public class DefaultDbMigration implements DbMigration {
|
||||
switch (platform) {
|
||||
case H2:
|
||||
return new H2Platform();
|
||||
case HSQLDB:
|
||||
return new HsqldbPlatform();
|
||||
case POSTGRES9:
|
||||
return new Postgres9Platform();
|
||||
case POSTGRES:
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class PlatformTypeConverter {
|
||||
} else {
|
||||
// scale - varchar(10)
|
||||
int scale = Integer.parseInt(columnDefinition.substring(open + 1, close));
|
||||
return dbType.renderType(scale, -1) + suffix;
|
||||
return dbType.renderType(scale, 0) + suffix;
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
package io.ebeaninternal.server.cache;
|
||||
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
|
||||
/**
|
||||
* Bean Id value plus discriminator type.
|
||||
* <p>
|
||||
* Put into L2 cache such that we know the type of a bean with inheritance.
|
||||
*/
|
||||
public class CachedBeanId implements Externalizable {
|
||||
|
||||
private String discValue;
|
||||
private Object id;
|
||||
|
||||
public CachedBeanId(String discValue, Object id) {
|
||||
this.discValue = discValue;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct from serialisation.
|
||||
*/
|
||||
public CachedBeanId() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeExternal(ObjectOutput out) throws IOException {
|
||||
out.writeUTF(discValue);
|
||||
out.writeObject(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
|
||||
discValue = in.readUTF();
|
||||
id = in.readObject();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return discValue + ":" + id;
|
||||
}
|
||||
|
||||
public String getDiscValue() {
|
||||
return discValue;
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,7 +134,7 @@ class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getQueryOptions(Class<?> cls) {
|
||||
CacheQueryTuning tuning = AnnotationUtil.get(cls, CacheQueryTuning.class);
|
||||
CacheQueryTuning tuning = AnnotationUtil.findAnnotation(cls, CacheQueryTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(tuning).applyDefaults(queryDefault);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class DefaultChangeLogRegister implements ChangeLogRegister {
|
||||
* Find and return the ChangeLog annotation in the inheritance hierarchy.
|
||||
*/
|
||||
private ChangeLog getChangeLog(Class<?> beanType) {
|
||||
return AnnotationUtil.typeGet(beanType, ChangeLog.class);
|
||||
return AnnotationUtil.findAnnotationRecursive(beanType, ChangeLog.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@ import io.ebean.config.dbplatform.cockroach.CockroachPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2Platform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
@@ -164,8 +163,6 @@ public class DatabasePlatformFactory {
|
||||
return mysqlVersion(majorVersion, minorVersion);
|
||||
} else if (dbProductName.contains("h2")) {
|
||||
return new H2Platform();
|
||||
} else if (dbProductName.contains("hsql database engine")) {
|
||||
return new HsqldbPlatform();
|
||||
} else if (dbProductName.contains("postgres")) {
|
||||
return readPostgres(connection, majorVersion);
|
||||
} else if (dbProductName.contains("nuo")) {
|
||||
|
||||
@@ -699,7 +699,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Create and return a new reference bean matching this beans Id value.
|
||||
*/
|
||||
public T createReference() {
|
||||
return beanDescriptor.createRef(getBeanId(), null);
|
||||
return beanDescriptor.createReference(getBeanId(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -473,6 +473,6 @@ public class BootupClasses implements ClassFilter {
|
||||
* Returns true if this class has the annotation (or meta annotation). Does not search recursively.
|
||||
*/
|
||||
private boolean has(Class<?> cls, Class<? extends Annotation> ann) {
|
||||
return AnnotationUtil.has(cls, ann);
|
||||
return AnnotationUtil.findAnnotation(cls, ann) != null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2053,16 +2053,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Create a non read only reference bean without checking cacheSharableBeans.
|
||||
*/
|
||||
public T createReference(Object id, PersistenceContext pc) {
|
||||
if (inheritInfo != null && !inheritInfo.isConcrete()) {
|
||||
return findReferenceBean(id, pc);
|
||||
}
|
||||
return createRef(id, pc);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createRef(Object id, PersistenceContext pc) {
|
||||
public T createReference(Object id, PersistenceContext pc) {
|
||||
|
||||
try {
|
||||
if (inheritInfo != null && !inheritInfo.isConcrete()) {
|
||||
return findReferenceBean(id, pc);
|
||||
}
|
||||
|
||||
EntityBean eb = createEntityBean();
|
||||
id = convertSetId(id, eb);
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
@@ -2073,6 +2071,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
ebi.setPersistenceContext(pc);
|
||||
}
|
||||
return (T) eb;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
|
||||
@@ -1002,7 +1002,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
orderProperty.setDbInsertable(orderColumn.isInsertable());
|
||||
orderProperty.setDbUpdateable(orderColumn.isUpdatable());
|
||||
orderProperty.setDbRead(true);
|
||||
orderProperty.setOwningType(targetDesc.getBeanType());
|
||||
|
||||
targetDesc.setOrderColumn(orderProperty);
|
||||
}
|
||||
@@ -1402,13 +1401,13 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
String primaryKeyColumn = desc.getSinglePrimaryKeyColumn();
|
||||
seqName = namingConvention.getSequenceName(desc.getBaseTable(), primaryKeyColumn);
|
||||
}
|
||||
int stepSize = desc.setIdentitySequenceBatchMode(databasePlatform.isSequenceBatchMode());
|
||||
desc.setIdGenerator(createSequenceIdGenerator(seqName, stepSize));
|
||||
int increment = desc.setIdentitySequenceDefaultIncrement();
|
||||
desc.setIdGenerator(createSequenceIdGenerator(seqName, increment));
|
||||
}
|
||||
}
|
||||
|
||||
private PlatformIdGenerator createSequenceIdGenerator(String seqName, int stepSize) {
|
||||
return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSource, stepSize, seqName);
|
||||
private PlatformIdGenerator createSequenceIdGenerator(String seqName, int increment) {
|
||||
return databasePlatform.createSequenceIdGenerator(backgroundExecutor, dataSource, increment, seqName);
|
||||
}
|
||||
|
||||
private void createByteCode(DeployBeanDescriptor<?> deploy) {
|
||||
@@ -1592,7 +1591,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private boolean isMappedSuperWithNoProperties(Class<?> beanClass) {
|
||||
// do not search recursive here
|
||||
MappedSuperclass annotation = AnnotationUtil.get(beanClass, MappedSuperclass.class);
|
||||
MappedSuperclass annotation = AnnotationUtil.findAnnotation(beanClass, MappedSuperclass.class);
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import io.ebeaninternal.api.json.SpiJsonReader;
|
||||
import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
import io.ebeaninternal.server.cache.CacheChangeSet;
|
||||
import io.ebeaninternal.server.cache.CachedBeanData;
|
||||
import io.ebeaninternal.server.cache.CachedBeanId;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.deploy.id.ImportedId;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
@@ -434,19 +433,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
}
|
||||
if (embedded) {
|
||||
return targetDescriptor.cacheEmbeddedBeanExtract((EntityBean) ap);
|
||||
} else if (targetInheritInfo != null) {
|
||||
return createCacheBeanId(ap);
|
||||
} else {
|
||||
return targetDescriptor.getIdProperty().getCacheDataValue((EntityBean) ap);
|
||||
}
|
||||
}
|
||||
|
||||
private Object createCacheBeanId(Object bean) {
|
||||
final BeanDescriptor<?> desc = targetDescriptor.descOf(bean.getClass());
|
||||
final Object id = desc.getIdProperty().getCacheDataValue((EntityBean) bean);
|
||||
return new CachedBeanId(desc.getDiscValue(), id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(Object value) {
|
||||
return targetDescriptor.getIdBinder().cacheKey(value);
|
||||
@@ -460,31 +451,19 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
if (embedded) {
|
||||
setValue(bean, targetDescriptor.cacheEmbeddedBeanLoad((CachedBeanData) cacheData, context));
|
||||
} else {
|
||||
if (cacheData instanceof CachedBeanId) {
|
||||
setValue(bean, refInheritBean((CachedBeanId) cacheData, context));
|
||||
} else {
|
||||
setValue(bean, refBean(targetDescriptor, cacheData, context));
|
||||
if (cacheData instanceof String) {
|
||||
cacheData = targetDescriptor.getIdProperty().scalarType.parse((String) cacheData);
|
||||
}
|
||||
// cacheData is the id value, maybe already in persistence context
|
||||
Object assocBean = targetDescriptor.contextGet(context, cacheData);
|
||||
if (assocBean == null) {
|
||||
assocBean = targetDescriptor.createReference(cacheData, context);
|
||||
}
|
||||
setValue(bean, assocBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object refInheritBean(CachedBeanId cacheId, PersistenceContext context) {
|
||||
final InheritInfo rowInheritInfo = targetInheritInfo.readType(cacheId.getDiscValue());
|
||||
return refBean(rowInheritInfo.desc(), cacheId.getId(), context);
|
||||
}
|
||||
|
||||
private Object refBean(BeanDescriptor<?> desc, Object id, PersistenceContext context) {
|
||||
if (id instanceof String) {
|
||||
id = desc.getIdProperty().scalarType.parse((String) id);
|
||||
}
|
||||
Object bean = desc.contextGet(context, id);
|
||||
if (bean == null) {
|
||||
bean = desc.createRef(id, context);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarDataReader<?> getIdReader() {
|
||||
return targetDescriptor.getIdProperty();
|
||||
@@ -661,12 +640,14 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
|
||||
@Override
|
||||
public void addTenant(SpiQuery<?> query, Object tenantId) {
|
||||
query.where().eq(name, targetDescriptor.createRef(tenantId, null));
|
||||
T refBean = targetDescriptor.createReference(tenantId, null);
|
||||
query.where().eq(name, refBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTenantValue(EntityBean entityBean, Object tenantId) {
|
||||
setValue(entityBean, targetDescriptor.createRef(tenantId, null));
|
||||
T refBean = targetDescriptor.createReference(tenantId, null);
|
||||
setValue(entityBean, refBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -407,11 +407,8 @@ public class DeployBeanDescriptor<T> {
|
||||
identityMode.setSequenceGenerator(genName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sequence increment to use given sequence batch mode.
|
||||
*/
|
||||
public int setIdentitySequenceBatchMode(boolean sequenceBatchMode) {
|
||||
return identityMode.setSequenceBatchMode(sequenceBatchMode);
|
||||
public int setIdentitySequenceDefaultIncrement() {
|
||||
return identityMode.setSequenceDefaultIncrement();
|
||||
}
|
||||
|
||||
public void setIdentityType(IdType type) {
|
||||
|
||||
@@ -4,13 +4,10 @@ import io.ebean.annotation.CreatedTimestamp;
|
||||
import io.ebean.annotation.DocCode;
|
||||
import io.ebean.annotation.DocProperty;
|
||||
import io.ebean.annotation.DocSortable;
|
||||
import io.ebean.annotation.Formula;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.SoftDelete;
|
||||
import io.ebean.annotation.UpdatedTimestamp;
|
||||
import io.ebean.annotation.WhenCreated;
|
||||
import io.ebean.annotation.WhenModified;
|
||||
import io.ebean.annotation.Where;
|
||||
import io.ebean.annotation.WhoCreated;
|
||||
import io.ebean.annotation.WhoModified;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
@@ -34,13 +31,11 @@ import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -195,6 +190,11 @@ public class DeployBeanProperty {
|
||||
|
||||
private final DeployDocPropertyOptions docMapping = new DeployDocPropertyOptions();
|
||||
|
||||
/**
|
||||
* The method used to read the property.
|
||||
*/
|
||||
private Method readMethod;
|
||||
|
||||
private int propertyIndex;
|
||||
|
||||
private BeanPropertyGetter getter;
|
||||
@@ -232,8 +232,6 @@ public class DeployBeanProperty {
|
||||
|
||||
private List<DbMigrationInfo> dbMigrationInfos;
|
||||
|
||||
private Set<Annotation> metaAnnotations;
|
||||
|
||||
public DeployBeanProperty(DeployBeanDescriptor<?> desc, Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
|
||||
this.desc = desc;
|
||||
this.propertyType = propertyType;
|
||||
@@ -263,29 +261,29 @@ public class DeployBeanProperty {
|
||||
if (field == null) {
|
||||
return 0;
|
||||
}
|
||||
if (AnnotationUtil.get(field, Id.class) != null) {
|
||||
if (AnnotationUtil.findAnnotation(field, Id.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (AnnotationUtil.get(field, EmbeddedId.class) != null) {
|
||||
} else if (AnnotationUtil.findAnnotation(field, EmbeddedId.class) != null) {
|
||||
return ID_ORDER;
|
||||
} else if (undirectionalShadow) {
|
||||
return UNIDIRECTIONAL_ORDER;
|
||||
} else if (isAuditProperty()) {
|
||||
return AUDITCOLUMN_ORDER;
|
||||
} else if (AnnotationUtil.get(field, Version.class) != null) {
|
||||
} else if (AnnotationUtil.findAnnotation(field, Version.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
} else if (AnnotationUtil.get(field, SoftDelete.class) != null) {
|
||||
} else if (AnnotationUtil.findAnnotation(field, SoftDelete.class) != null) {
|
||||
return VERSIONCOLUMN_ORDER;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private boolean isAuditProperty() {
|
||||
return (AnnotationUtil.has(field, WhenCreated.class)
|
||||
|| AnnotationUtil.has(field, WhenModified.class)
|
||||
|| AnnotationUtil.has(field, WhoModified.class)
|
||||
|| AnnotationUtil.has(field, WhoCreated.class)
|
||||
|| AnnotationUtil.has(field, UpdatedTimestamp.class)
|
||||
|| AnnotationUtil.has(field, CreatedTimestamp.class));
|
||||
return (AnnotationUtil.findAnnotation(field, WhenCreated.class) != null
|
||||
|| AnnotationUtil.findAnnotation(field, WhenModified.class) != null
|
||||
|| AnnotationUtil.findAnnotation(field, WhoModified.class) != null
|
||||
|| AnnotationUtil.findAnnotation(field, WhoCreated.class) != null
|
||||
|| AnnotationUtil.findAnnotation(field, UpdatedTimestamp.class) != null
|
||||
|| AnnotationUtil.findAnnotation(field, CreatedTimestamp.class) != null);
|
||||
}
|
||||
|
||||
public String getFullBeanName() {
|
||||
@@ -455,6 +453,13 @@ public class DeployBeanProperty {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the getter method.
|
||||
*/
|
||||
public Method getReadMethod() {
|
||||
return readMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to the owning type form a Inheritance heirarchy.
|
||||
*/
|
||||
@@ -667,7 +672,7 @@ public class DeployBeanProperty {
|
||||
*/
|
||||
private String aggregationJoin(int pos, String dbColumn) {
|
||||
String p0 = aggregation.substring(0, pos + 1);
|
||||
aggregationParsed = p0 + "${ta}." + dbColumn + aggregation.substring(aggregation.length() - 1);
|
||||
aggregationParsed = p0 + "${ta}." + dbColumn + aggregation.substring(aggregation.length() - 1);
|
||||
return aggregationParsed;
|
||||
}
|
||||
|
||||
@@ -901,6 +906,17 @@ public class DeployBeanProperty {
|
||||
this.isTransient = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean read method.
|
||||
* <p>
|
||||
* NB: That a BeanReflectGetter is used to actually perform the getting of
|
||||
* property values from a bean. This is due to performance considerations.
|
||||
* </p>
|
||||
*/
|
||||
public void setReadMethod(Method readMethod) {
|
||||
this.readMethod = readMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property type.
|
||||
*/
|
||||
@@ -1106,7 +1122,7 @@ public class DeployBeanProperty {
|
||||
*/
|
||||
public Object /*AnnotatedField*/ getJacksonField() {
|
||||
com.fasterxml.jackson.databind.introspect.AnnotatedClass jac =
|
||||
(com.fasterxml.jackson.databind.introspect.AnnotatedClass) getDesc().getJacksonAnnotatedClass();
|
||||
(com.fasterxml.jackson.databind.introspect.AnnotatedClass) getDesc().getJacksonAnnotatedClass();
|
||||
for (com.fasterxml.jackson.databind.introspect.AnnotatedField candidate : jac.fields()) {
|
||||
if (candidate.getName().equals(getName())) {
|
||||
return candidate;
|
||||
@@ -1114,102 +1130,4 @@ public class DeployBeanProperty {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void initMetaAnnotations(Set<Class<?>> metaAnnotationsFilter) {
|
||||
metaAnnotations = AnnotationUtil.metaFindAllFor(field, metaAnnotationsFilter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> A getMetaAnnotation(Class<A> annotationType) {
|
||||
for (Annotation ann : metaAnnotations) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
return (A) ann;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <A extends Annotation> List<A> getMetaAnnotations(Class<A> annotationType) {
|
||||
List<A> result = new ArrayList<>();
|
||||
for (Annotation ann : metaAnnotations) {
|
||||
if (ann.annotationType() == annotationType) {
|
||||
result.add((A) ann);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Size> getMetaAnnotationSize() {
|
||||
final List<Size> size = getMetaAnnotations(Size.class);
|
||||
final List<Size.List> lists = getMetaAnnotations(Size.List.class);
|
||||
for (Size.List list : lists) {
|
||||
Collections.addAll(size, list.value());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public Formula getMetaAnnotationFormula(Platform platform) {
|
||||
Formula fallback = null;
|
||||
for (Annotation ann : metaAnnotations) {
|
||||
if (ann.annotationType() == Formula.class) {
|
||||
Formula formula = (Formula) ann;
|
||||
final Platform[] platforms = formula.platforms();
|
||||
if (platforms.length == 0) {
|
||||
fallback = formula;
|
||||
} else if (matchPlatform(platforms, platform)) {
|
||||
return formula;
|
||||
}
|
||||
|
||||
} else if (ann.annotationType() == Formula.List.class) {
|
||||
Formula.List formulaList = (Formula.List) ann;
|
||||
for (Formula formula : formulaList.value()) {
|
||||
final Platform[] platforms = formula.platforms();
|
||||
if (platforms.length == 0) {
|
||||
fallback = formula;
|
||||
} else if (matchPlatform(platforms, platform)) {
|
||||
return formula;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
public Where getMetaAnnotationWhere(Platform platform) {
|
||||
Where fallback = null;
|
||||
for (Annotation ann : metaAnnotations) {
|
||||
if (ann.annotationType() == Where.class) {
|
||||
Where where = (Where) ann;
|
||||
final Platform[] platforms = where.platforms();
|
||||
if (platforms.length == 0) {
|
||||
fallback = where;
|
||||
} else if (matchPlatform(where.platforms(), platform)) {
|
||||
return where;
|
||||
}
|
||||
|
||||
} else if (ann.annotationType() == Where.List.class) {
|
||||
Where.List whereList = (Where.List) ann;
|
||||
for (Where where : whereList.value()) {
|
||||
final Platform[] platforms = where.platforms();
|
||||
if (platforms.length == 0) {
|
||||
fallback = where;
|
||||
} else if (matchPlatform(where.platforms(), platform)) {
|
||||
return where;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private boolean matchPlatform(Platform[] platforms, Platform match) {
|
||||
for (Platform platform : platforms) {
|
||||
if (platform == match) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -54,11 +54,8 @@ public class DeployIdentityMode {
|
||||
}
|
||||
}
|
||||
|
||||
public int setSequenceBatchMode(boolean sequenceBatchMode) {
|
||||
if (sequenceBatchMode) {
|
||||
// Ebean batch fetching multiple sequence values
|
||||
increment = 1;
|
||||
} else if (increment == 0) {
|
||||
public int setSequenceDefaultIncrement() {
|
||||
if (increment == 0) {
|
||||
// Use JPA default of 50
|
||||
increment = 50;
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
prop.setMapKey(mapKey.name());
|
||||
}
|
||||
|
||||
Where where = prop.getMetaAnnotationWhere(platform);
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
@@ -138,8 +138,8 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
|
||||
Set<JoinColumn> joinColumns = annotationJoinColumns(prop);
|
||||
if (!joinColumns.isEmpty()) {
|
||||
Set<JoinColumn> joinColumns = getAll(prop, JoinColumn.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(util, true, joinColumns, beanTable);
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
if (!elementCollection.targetClass().equals(void.class)) {
|
||||
prop.setTargetType(elementCollection.targetClass());
|
||||
}
|
||||
Column column = prop.getMetaAnnotation(Column.class);
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null) {
|
||||
prop.setDbColumn(column.name());
|
||||
prop.setDbLength(column.length());
|
||||
|
||||
@@ -82,7 +82,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
prop.setId();
|
||||
prop.setNullable(false);
|
||||
}
|
||||
Column column = prop.getMetaAnnotation(Column.class);
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null && !isEmpty(column.name())) {
|
||||
// have this in for AssocOnes used on
|
||||
// Sql based beans...
|
||||
@@ -100,7 +100,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
prop.setForeignKey(new PropertyForeignKey(dbForeignKey));
|
||||
}
|
||||
|
||||
Where where = prop.getMetaAnnotationWhere(platform);
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
// not expecting this to be used on assoc one properties
|
||||
prop.setExtraWhere(where.clause());
|
||||
@@ -131,11 +131,12 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
for (JoinColumn joinColumn : annotationJoinColumns(prop)) {
|
||||
for (JoinColumn joinColumn : getAll(prop, JoinColumn.class)) {
|
||||
setFromJoinColumn(prop, beanTable, joinColumn);
|
||||
checkForNoConstraint(prop, joinColumn);
|
||||
}
|
||||
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
for (JoinColumn joinColumn : joinTable.joinColumns()) {
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.Aggregation;
|
||||
import io.ebean.annotation.Avg;
|
||||
import io.ebean.annotation.DbMigration;
|
||||
import io.ebean.annotation.Index;
|
||||
import io.ebean.annotation.Indices;
|
||||
import io.ebean.annotation.Max;
|
||||
import io.ebean.annotation.Min;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.Sum;
|
||||
import io.ebean.config.NamingConvention;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -52,7 +41,7 @@ import java.util.Set;
|
||||
abstract class AnnotationBase {
|
||||
|
||||
final DatabasePlatform databasePlatform;
|
||||
protected final Platform platform;
|
||||
private final Platform platform;
|
||||
final NamingConvention namingConvention;
|
||||
final DeployUtil util;
|
||||
|
||||
@@ -75,43 +64,68 @@ abstract class AnnotationBase {
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the annotation for the property.
|
||||
* <p>
|
||||
* Looks first at the field and then at the getter method. It searches for meta-annotations, but not
|
||||
* recursively in the class hierarchy.
|
||||
* </p>
|
||||
* <p>
|
||||
* If a <code>repeatable</code> annotation class is specified and the annotation is platform
|
||||
* specific then the platform specific annotation is returned. Otherwise the first annotation
|
||||
* is returned. Note that you need no longer handle "java 1.6 repeatable containers"
|
||||
* like {@link JoinColumn} / {@link JoinColumns} yourself.
|
||||
* </p>
|
||||
* <p>
|
||||
*/
|
||||
<T extends Annotation> T get(DeployBeanProperty prop, Class<T> annClass) {
|
||||
return AnnotationUtil.get(prop.getField(), annClass);
|
||||
}
|
||||
|
||||
<T extends Annotation> boolean has(DeployBeanProperty prop, Class<T> annClass) {
|
||||
return AnnotationUtil.has(prop.getField(), annClass);
|
||||
}
|
||||
|
||||
Set<JoinColumn> annotationJoinColumns(DeployBeanProperty prop) {
|
||||
return AnnotationFind.joinColumns(prop.getField());
|
||||
}
|
||||
|
||||
Set<AttributeOverride> annotationAttributeOverrides(DeployBeanProperty prop) {
|
||||
return AnnotationFind.attributeOverrides(prop.getField());
|
||||
}
|
||||
|
||||
Set<Index> annotationIndexes(DeployBeanProperty prop) {
|
||||
return AnnotationFind.indexes(prop.getField());
|
||||
}
|
||||
|
||||
Set<DbMigration> annotationDbMigrations(DeployBeanProperty prop) {
|
||||
return AnnotationFind.dbMigrations(prop.getField());
|
||||
}
|
||||
|
||||
Set<Index> annotationClassIndexes(Class<?> cls) {
|
||||
Set<Index> result = AnnotationUtil.typeGetAll(cls, Index.class);
|
||||
for (Indices index : AnnotationUtil.typeGetAll(cls, Indices.class)) {
|
||||
Collections.addAll(result, index.value());
|
||||
T a = null;
|
||||
Field field = prop.getField();
|
||||
if (field != null) {
|
||||
a = AnnotationUtil.findAnnotation(field, annClass, platform);
|
||||
}
|
||||
return result;
|
||||
if (a == null) {
|
||||
Method method = prop.getReadMethod();
|
||||
if (method != null) {
|
||||
a = AnnotationUtil.findAnnotation(method, annClass, platform);
|
||||
}
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
Set<NamedQuery> annotationClassNamedQuery(Class<?> cls) {
|
||||
Set<NamedQuery> result = AnnotationUtil.typeGetAll(cls, NamedQuery.class);
|
||||
for (NamedQueries queries : AnnotationUtil.typeGetAll(cls, NamedQueries.class)) {
|
||||
Collections.addAll(result, queries.value());
|
||||
/**
|
||||
* Return all annotations for this property. Annotations are not filtered by platfrom and you'll get
|
||||
* really all annotations that are directly, indirectly or meta-present.
|
||||
*/
|
||||
<T extends Annotation> Set<T> getAll(DeployBeanProperty prop, Class<T> annClass) {
|
||||
Set<T> ret = null;
|
||||
Field field = prop.getField();
|
||||
if (field != null) {
|
||||
ret = AnnotationUtil.findAnnotations(field, annClass);
|
||||
}
|
||||
return result;
|
||||
Method method = prop.getReadMethod();
|
||||
if (method != null) {
|
||||
if (ret != null) {
|
||||
ret.addAll(AnnotationUtil.findAnnotations(method, annClass));
|
||||
} else {
|
||||
ret = AnnotationUtil.findAnnotations(method, annClass);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the annotation for the property.
|
||||
* <p>
|
||||
* Looks first at the field and then at the getter method. then at class level.
|
||||
* (This is used for SequenceGenerator e.g.)
|
||||
* </p>
|
||||
*/
|
||||
<T extends Annotation> T find(DeployBeanProperty prop, Class<T> annClass) {
|
||||
T a = get(prop, annClass);
|
||||
if (a == null) {
|
||||
a = AnnotationUtil.findAnnotation(prop.getOwningType(), annClass, platform);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import static io.ebean.util.AnnotationUtil.typeGet;
|
||||
import static io.ebean.util.AnnotationUtil.findAnnotationRecursive;
|
||||
import static io.ebean.util.AnnotationUtil.findAnnotationsRecursive;
|
||||
|
||||
/**
|
||||
* Read the class level deployment annotations.
|
||||
@@ -61,8 +62,9 @@ public class AnnotationClass extends AnnotationParser {
|
||||
* Parse any AttributeOverride set on the class.
|
||||
*/
|
||||
void parseAttributeOverride() {
|
||||
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
AttributeOverride override = typeGet(cls, AttributeOverride.class);
|
||||
AttributeOverride override = findAnnotationRecursive(cls, AttributeOverride.class);
|
||||
if (override != null) {
|
||||
String propertyName = override.name();
|
||||
Column column = override.column();
|
||||
@@ -102,15 +104,16 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
// maybe doc store only so check for this before @Entity
|
||||
DocStore docStore = typeGet(cls, DocStore.class);
|
||||
DocStore docStore = findAnnotationRecursive(cls, DocStore.class);
|
||||
if (docStore != null) {
|
||||
descriptor.readDocStore(docStore);
|
||||
descriptor.setEntityType(EntityType.DOC);
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
}
|
||||
|
||||
Entity entity = typeGet(cls, Entity.class);
|
||||
Entity entity = findAnnotationRecursive(cls, Entity.class);
|
||||
if (entity != null) {
|
||||
descriptor.setEntityType(EntityType.ORM);
|
||||
if (entity.name().isEmpty()) {
|
||||
@@ -120,37 +123,37 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Identity identity = typeGet(cls, Identity.class);
|
||||
Identity identity = findAnnotationRecursive(cls, Identity.class);
|
||||
if (identity != null) {
|
||||
descriptor.setIdentityMode(identity);
|
||||
}
|
||||
|
||||
IdClass idClass = typeGet(cls, IdClass.class);
|
||||
IdClass idClass = findAnnotationRecursive(cls, IdClass.class);
|
||||
if (idClass != null) {
|
||||
descriptor.setIdClass(idClass.value());
|
||||
}
|
||||
|
||||
Embeddable embeddable = typeGet(cls, Embeddable.class);
|
||||
Embeddable embeddable = findAnnotationRecursive(cls, Embeddable.class);
|
||||
if (embeddable != null) {
|
||||
descriptor.setEntityType(EntityType.EMBEDDED);
|
||||
descriptor.setName("Embeddable:" + cls.getSimpleName());
|
||||
}
|
||||
|
||||
for (Index index : annotationClassIndexes(cls)) {
|
||||
for (Index index : findAnnotationsRecursive(cls, Index.class)) {
|
||||
descriptor.addIndex(new IndexDefinition(convertColumnNames(index.columnNames()), index.name(),
|
||||
index.unique(), index.platforms(), index.concurrent(), index.definition()));
|
||||
}
|
||||
|
||||
UniqueConstraint uc = typeGet(cls, UniqueConstraint.class);
|
||||
UniqueConstraint uc = findAnnotationRecursive(cls, UniqueConstraint.class);
|
||||
if (uc != null) {
|
||||
descriptor.addIndex(new IndexDefinition(convertColumnNames(uc.columnNames())));
|
||||
}
|
||||
|
||||
View view = typeGet(cls, View.class);
|
||||
View view = findAnnotationRecursive(cls, View.class);
|
||||
if (view != null) {
|
||||
descriptor.setView(view.name(), view.dependentTables());
|
||||
}
|
||||
Table table = typeGet(cls, Table.class);
|
||||
Table table = findAnnotationRecursive(cls, Table.class);
|
||||
if (table != null) {
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
@@ -158,54 +161,54 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
StorageEngine storage = typeGet(cls, StorageEngine.class);
|
||||
StorageEngine storage = findAnnotationRecursive(cls, StorageEngine.class);
|
||||
if (storage != null) {
|
||||
descriptor.setStorageEngine(storage.value());
|
||||
}
|
||||
|
||||
DbPartition partition = typeGet(cls, DbPartition.class);
|
||||
DbPartition partition = findAnnotationRecursive(cls, DbPartition.class);
|
||||
if (partition != null) {
|
||||
descriptor.setPartitionMeta(new PartitionMeta(partition.mode(), partition.property()));
|
||||
}
|
||||
|
||||
Draftable draftable = typeGet(cls, Draftable.class);
|
||||
Draftable draftable = findAnnotationRecursive(cls, Draftable.class);
|
||||
if (draftable != null) {
|
||||
descriptor.setDraftable();
|
||||
}
|
||||
|
||||
DraftableElement draftableElement = typeGet(cls, DraftableElement.class);
|
||||
DraftableElement draftableElement = findAnnotationRecursive(cls, DraftableElement.class);
|
||||
if (draftableElement != null) {
|
||||
descriptor.setDraftableElement();
|
||||
}
|
||||
|
||||
ReadAudit readAudit = typeGet(cls, ReadAudit.class);
|
||||
ReadAudit readAudit = findAnnotationRecursive(cls, ReadAudit.class);
|
||||
if (readAudit != null) {
|
||||
descriptor.setReadAuditing();
|
||||
}
|
||||
|
||||
History history = typeGet(cls, History.class);
|
||||
History history = findAnnotationRecursive(cls, History.class);
|
||||
if (history != null) {
|
||||
descriptor.setHistorySupport();
|
||||
}
|
||||
|
||||
DbComment comment = typeGet(cls, DbComment.class);
|
||||
DbComment comment = findAnnotationRecursive(cls, DbComment.class);
|
||||
if (comment != null) {
|
||||
descriptor.setDbComment(comment.value());
|
||||
}
|
||||
|
||||
if (!disableL2Cache) {
|
||||
Cache cache = typeGet(cls, Cache.class);
|
||||
Cache cache = findAnnotationRecursive(cls, Cache.class);
|
||||
if (cache != null) {
|
||||
descriptor.setCache(cache);
|
||||
} else {
|
||||
InvalidateQueryCache invalidateQueryCache = typeGet(cls, InvalidateQueryCache.class);
|
||||
InvalidateQueryCache invalidateQueryCache = findAnnotationRecursive(cls, InvalidateQueryCache.class);
|
||||
if (invalidateQueryCache != null) {
|
||||
descriptor.setInvalidateQueryCache(invalidateQueryCache.region());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (NamedQuery namedQuery : annotationClassNamedQuery(cls)) {
|
||||
for (NamedQuery namedQuery : findAnnotationsRecursive(cls, NamedQuery.class)) {
|
||||
descriptor.addNamedQuery(namedQuery.name(), namedQuery.query());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,8 +106,8 @@ public class AnnotationFields extends AnnotationParser {
|
||||
*/
|
||||
@Override
|
||||
public void parse() {
|
||||
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
prop.initMetaAnnotations(readConfig.getMetaAnnotations());
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?>) {
|
||||
readAssocOne((DeployBeanPropertyAssoc<?>) prop);
|
||||
} else {
|
||||
@@ -123,11 +123,13 @@ public class AnnotationFields extends AnnotationParser {
|
||||
|
||||
readJsonAnnotations(prop);
|
||||
|
||||
if (has(prop, Id.class)) {
|
||||
Id id = get(prop, Id.class);
|
||||
if (id != null) {
|
||||
readIdAssocOne(prop);
|
||||
}
|
||||
|
||||
if (has(prop, EmbeddedId.class)) {
|
||||
EmbeddedId embeddedId = get(prop, EmbeddedId.class);
|
||||
if (embeddedId != null) {
|
||||
prop.setId();
|
||||
prop.setNullable(false);
|
||||
prop.setEmbedded();
|
||||
@@ -138,7 +140,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (docEmbedded != null) {
|
||||
prop.setDocStoreEmbedded(docEmbedded.doc());
|
||||
if (descriptor.isDocStoreOnly()) {
|
||||
if (has(prop, ManyToOne.class)) {
|
||||
if (get(prop, ManyToOne.class) == null) {
|
||||
prop.setEmbedded();
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
@@ -153,20 +155,20 @@ public class AnnotationFields extends AnnotationParser {
|
||||
readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop);
|
||||
}
|
||||
|
||||
Formula formula = prop.getMetaAnnotationFormula(platform);
|
||||
Formula formula = get(prop, Formula.class);
|
||||
if (formula != null) {
|
||||
prop.setSqlFormula(formula.select(), formula.join());
|
||||
}
|
||||
|
||||
initWhoProperties(prop);
|
||||
initDbMigration(prop);
|
||||
readDbMigration(prop);
|
||||
}
|
||||
|
||||
private void initWhoProperties(DeployBeanProperty prop) {
|
||||
if (has(prop, WhoModified.class)) {
|
||||
if (get(prop, WhoModified.class) != null) {
|
||||
generatedPropFactory.setWhoModified(prop);
|
||||
}
|
||||
if (has(prop, WhoCreated.class)) {
|
||||
if (get(prop, WhoCreated.class) != null) {
|
||||
generatedPropFactory.setWhoCreated(prop);
|
||||
}
|
||||
}
|
||||
@@ -186,7 +188,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setDbInsertable(true);
|
||||
prop.setDbUpdateable(true);
|
||||
|
||||
Column column = prop.getMetaAnnotation(Column.class);
|
||||
Column column = get(prop, Column.class);
|
||||
if (column != null) {
|
||||
readColumn(column, prop);
|
||||
}
|
||||
@@ -198,32 +200,6 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setDbColumn(namingConvention.getColumnFromProperty(beanType, prop.getName()));
|
||||
}
|
||||
|
||||
initIdentity(prop);
|
||||
initTenantId(prop);
|
||||
initDbJson(prop);
|
||||
initFormula(prop);
|
||||
initVersion(prop);
|
||||
initWhen(prop);
|
||||
initWhoProperties(prop);
|
||||
initDbMigration(prop);
|
||||
|
||||
// Want to process last so we can use with @Formula
|
||||
if (has(prop, Transient.class)) {
|
||||
// it is not a persistent property.
|
||||
prop.setDbRead(false);
|
||||
prop.setDbInsertable(false);
|
||||
prop.setDbUpdateable(false);
|
||||
prop.setTransient();
|
||||
}
|
||||
|
||||
initEncrypt(prop);
|
||||
|
||||
for (Index index : annotationIndexes(prop)) {
|
||||
addIndex(prop, index);
|
||||
}
|
||||
}
|
||||
|
||||
private void initIdentity(DeployBeanProperty prop) {
|
||||
Id id = get(prop, Id.class);
|
||||
GeneratedValue gen = get(prop, GeneratedValue.class);
|
||||
if (gen != null) {
|
||||
@@ -243,7 +219,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (temporal != null) {
|
||||
readTemporal(temporal, prop);
|
||||
|
||||
} else if (has(prop, Lob.class)) {
|
||||
} else if (get(prop, Lob.class) != null) {
|
||||
util.setLobType(prop);
|
||||
}
|
||||
|
||||
@@ -252,58 +228,53 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setDbLength(length.value());
|
||||
}
|
||||
|
||||
if (has(prop, io.ebean.annotation.NotNull.class)) {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void initValidation(DeployBeanProperty prop) {
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
|
||||
// Not null on all validation groups so enable
|
||||
// DDL generation of Not Null Constraint
|
||||
io.ebean.annotation.NotNull nonNull = get(prop, io.ebean.annotation.NotNull.class);
|
||||
if (nonNull != null) {
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
if (!prop.isLob()) {
|
||||
// take the max size of all @Size annotations
|
||||
int maxSize = -1;
|
||||
for (Size size : prop.getMetaAnnotationSize()) {
|
||||
if (size.max() < Integer.MAX_VALUE) {
|
||||
maxSize = Math.max(maxSize, size.max());
|
||||
if (validationAnnotations) {
|
||||
NotNull notNull = get(prop, NotNull.class);
|
||||
if (notNull != null && isEbeanValidationGroups(notNull.groups())) {
|
||||
// Not null on all validation groups so enable
|
||||
// DDL generation of Not Null Constraint
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
if (!prop.isLob()) {
|
||||
// take the max size of all @Size annotations
|
||||
int maxSize = -1;
|
||||
for (Size size : getAll(prop, Size.class)) {
|
||||
if (size.max() < Integer.MAX_VALUE) {
|
||||
maxSize = Math.max(maxSize, size.max());
|
||||
}
|
||||
}
|
||||
if (maxSize != -1) {
|
||||
prop.setDbLength(maxSize);
|
||||
}
|
||||
}
|
||||
if (maxSize != -1) {
|
||||
prop.setDbLength(maxSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initTenantId(DeployBeanProperty prop) {
|
||||
if (validationAnnotations) {
|
||||
initValidation(prop);
|
||||
}
|
||||
if (has(prop, TenantId.class)) {
|
||||
if (get(prop, TenantId.class) != null) {
|
||||
prop.setTenantId();
|
||||
}
|
||||
if (has(prop, Draft.class)) {
|
||||
if (get(prop, Draft.class) != null) {
|
||||
prop.setDraft();
|
||||
}
|
||||
if (has(prop, DraftOnly.class)) {
|
||||
if (get(prop, DraftOnly.class) != null) {
|
||||
prop.setDraftOnly();
|
||||
}
|
||||
if (has(prop, DraftDirty.class)) {
|
||||
if (get(prop, DraftDirty.class) != null) {
|
||||
prop.setDraftDirty();
|
||||
}
|
||||
if (has(prop, DraftReset.class)) {
|
||||
if (get(prop, DraftReset.class) != null) {
|
||||
prop.setDraftReset();
|
||||
}
|
||||
if (has(prop, SoftDelete.class)) {
|
||||
SoftDelete softDelete = get(prop, SoftDelete.class);
|
||||
if (softDelete != null) {
|
||||
prop.setSoftDelete();
|
||||
}
|
||||
}
|
||||
|
||||
private void initDbJson(DeployBeanProperty prop) {
|
||||
DbComment comment = get(prop, DbComment.class);
|
||||
if (comment != null) {
|
||||
prop.setDbComment(comment.value());
|
||||
@@ -325,9 +296,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (dbArray != null) {
|
||||
util.setDbArray(prop, dbArray);
|
||||
}
|
||||
}
|
||||
|
||||
private void initFormula(DeployBeanProperty prop) {
|
||||
DocCode docCode = get(prop, DocCode.class);
|
||||
if (docCode != null) {
|
||||
prop.setDocCode(docCode);
|
||||
@@ -340,19 +309,19 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (docProperty != null) {
|
||||
prop.setDocProperty(docProperty);
|
||||
}
|
||||
Formula formula = prop.getMetaAnnotationFormula(platform);
|
||||
|
||||
Formula formula = get(prop, Formula.class);
|
||||
if (formula != null) {
|
||||
prop.setSqlFormula(formula.select(), formula.join());
|
||||
}
|
||||
|
||||
final Aggregation aggregation = prop.getMetaAnnotation(Aggregation.class);
|
||||
Aggregation aggregation = get(prop, Aggregation.class);
|
||||
if (aggregation != null) {
|
||||
prop.setAggregation(aggregation.value().replace("$1", prop.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void initVersion(DeployBeanProperty prop) {
|
||||
if (has(prop, Version.class)) {
|
||||
Version version = get(prop, Version.class);
|
||||
if (version != null) {
|
||||
// explicitly specify a version column
|
||||
prop.setVersionColumn();
|
||||
generatedPropFactory.setVersion(prop);
|
||||
@@ -368,19 +337,35 @@ public class AnnotationFields extends AnnotationParser {
|
||||
// use the default Lob fetchType
|
||||
prop.setFetchType(defaultLobFetchType);
|
||||
}
|
||||
}
|
||||
|
||||
private void initWhen(DeployBeanProperty prop) {
|
||||
if (has(prop, WhenCreated.class) || has(prop, CreatedTimestamp.class)) {
|
||||
if (get(prop, WhenCreated.class) != null || get(prop, CreatedTimestamp.class) != null) {
|
||||
generatedPropFactory.setInsertTimestamp(prop);
|
||||
}
|
||||
if (has(prop, WhenModified.class) || has(prop, UpdatedTimestamp.class)) {
|
||||
|
||||
if (get(prop, WhenModified.class) != null || get(prop, UpdatedTimestamp.class) != null) {
|
||||
generatedPropFactory.setUpdateTimestamp(prop);
|
||||
}
|
||||
}
|
||||
|
||||
private void initEncrypt(DeployBeanProperty prop) {
|
||||
initWhoProperties(prop);
|
||||
|
||||
if (get(prop, HistoryExclude.class) != null) {
|
||||
prop.setExcludedFromHistory();
|
||||
}
|
||||
|
||||
readDbMigration(prop);
|
||||
|
||||
// Want to process last so we can use with @Formula
|
||||
Transient t = get(prop, Transient.class);
|
||||
if (t != null) {
|
||||
// it is not a persistent property.
|
||||
prop.setDbRead(false);
|
||||
prop.setDbInsertable(false);
|
||||
prop.setDbUpdateable(false);
|
||||
prop.setTransient();
|
||||
}
|
||||
|
||||
if (!prop.isTransient()) {
|
||||
|
||||
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
|
||||
if (encryptDeploy == null || encryptDeploy.getMode() == Mode.MODE_ANNOTATION) {
|
||||
Encrypted encrypted = get(prop, Encrypted.class);
|
||||
@@ -391,22 +376,24 @@ public class AnnotationFields extends AnnotationParser {
|
||||
setEncryption(prop, encryptDeploy.isDbEncrypt(), encryptDeploy.getDbLength());
|
||||
}
|
||||
}
|
||||
|
||||
Set<Index> indices = getAll(prop, Index.class);
|
||||
for (Index index : indices) {
|
||||
addIndex(prop, index);
|
||||
}
|
||||
}
|
||||
|
||||
private void readIdentity(Identity identity) {
|
||||
descriptor.setIdentityMode(identity);
|
||||
}
|
||||
|
||||
private void initDbMigration(DeployBeanProperty prop) {
|
||||
if (has(prop, HistoryExclude.class)) {
|
||||
prop.setExcludedFromHistory();
|
||||
}
|
||||
private void readDbMigration(DeployBeanProperty prop) {
|
||||
DbDefault dbDefault = get(prop, DbDefault.class);
|
||||
if (dbDefault != null) {
|
||||
prop.setDbColumnDefault(dbDefault.value());
|
||||
}
|
||||
|
||||
Set<DbMigration> dbMigration = annotationDbMigrations(prop);
|
||||
Set<DbMigration> dbMigration = getAll(prop, DbMigration.class);
|
||||
dbMigration.forEach(ann -> prop.addDbMigrationInfo(
|
||||
new DbMigrationInfo(ann.preAdd(), ann.postAdd(), ann.preAlter(), ann.postAlter(), ann.platforms())));
|
||||
}
|
||||
@@ -458,13 +445,15 @@ public class AnnotationFields extends AnnotationParser {
|
||||
prop.setJsonSerialize(jsonIgnore.serialize());
|
||||
prop.setJsonDeserialize(jsonIgnore.deserialize());
|
||||
}
|
||||
if (has(prop, UnmappedJson.class)) {
|
||||
if (get(prop, UnmappedJson.class) != null) {
|
||||
prop.setUnmappedJson();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasRelationshipItem(DeployBeanProperty prop) {
|
||||
return has(prop, OneToMany.class) || has(prop, ManyToOne.class) || has(prop, OneToOne.class);
|
||||
return get(prop, OneToMany.class) != null ||
|
||||
get(prop, ManyToOne.class) != null ||
|
||||
get(prop, OneToOne.class) != null;
|
||||
}
|
||||
|
||||
private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) {
|
||||
@@ -539,7 +528,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
}
|
||||
descriptor.setIdGeneratedValue();
|
||||
|
||||
SequenceGenerator seq = get(prop, SequenceGenerator.class);
|
||||
SequenceGenerator seq = find(prop, SequenceGenerator.class);
|
||||
if (seq != null) {
|
||||
String seqName = seq.sequenceName();
|
||||
if (seqName.isEmpty()) {
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.DbMigration;
|
||||
import io.ebean.annotation.Index;
|
||||
import io.ebean.annotation.Indices;
|
||||
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.ebean.util.AnnotationUtil.get;
|
||||
|
||||
public class AnnotationFind {
|
||||
|
||||
public static Set<JoinColumn> joinColumns(Field field) {
|
||||
final JoinColumn col = get(field, JoinColumn.class);
|
||||
if (col != null) {
|
||||
return Collections.singleton(col);
|
||||
}
|
||||
final JoinColumns cols = get(field, JoinColumns.class);
|
||||
if (cols != null) {
|
||||
Set<JoinColumn> result = new LinkedHashSet<>();
|
||||
Collections.addAll(result, cols.value());
|
||||
return result;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public static Set<AttributeOverride> attributeOverrides(Field field) {
|
||||
final AttributeOverride ann = get(field, AttributeOverride.class);
|
||||
if (ann != null) {
|
||||
return Collections.singleton(ann);
|
||||
}
|
||||
final AttributeOverrides collection = get(field, AttributeOverrides.class);
|
||||
if (collection != null) {
|
||||
Set<AttributeOverride> result = new LinkedHashSet<>();
|
||||
Collections.addAll(result, collection.value());
|
||||
return result;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public static Set<Index> indexes(Field field) {
|
||||
final Index ann = get(field, Index.class);
|
||||
if (ann != null) {
|
||||
return Collections.singleton(ann);
|
||||
}
|
||||
final Indices collection = get(field, Indices.class);
|
||||
if (collection != null) {
|
||||
Set<Index> result = new LinkedHashSet<>();
|
||||
Collections.addAll(result, collection.value());
|
||||
return result;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public static Set<DbMigration> dbMigrations(Field field) {
|
||||
final DbMigration ann = get(field, DbMigration.class);
|
||||
if (ann != null) {
|
||||
return Collections.singleton(ann);
|
||||
}
|
||||
final DbMigration.List collection = get(field, DbMigration.List.class);
|
||||
if (collection != null) {
|
||||
Set<DbMigration> result = new LinkedHashSet<>();
|
||||
Collections.addAll(result, collection.value());
|
||||
return result;
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public abstract class AnnotationParser extends AnnotationBase {
|
||||
*/
|
||||
void readEmbeddedAttributeOverrides(DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
Set<AttributeOverride> attrOverrides = annotationAttributeOverrides(prop);
|
||||
Set<AttributeOverride> attrOverrides = getAll(prop, AttributeOverride.class);
|
||||
if (!attrOverrides.isEmpty()) {
|
||||
HashMap<String, String> propMap = new HashMap<>(attrOverrides.size());
|
||||
for (AttributeOverride attrOverride : attrOverrides) {
|
||||
@@ -95,6 +95,7 @@ public abstract class AnnotationParser extends AnnotationBase {
|
||||
}
|
||||
prop.getDeployEmbedded().putAll(propMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void readColumn(Column columnAnn, DeployBeanProperty prop) {
|
||||
|
||||
@@ -16,7 +16,8 @@ class AnnotationSql extends AnnotationParser {
|
||||
@Override
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
if (AnnotationUtil.typeHas(cls, Sql.class)) {
|
||||
Sql sql = AnnotationUtil.findAnnotationRecursive(cls, Sql.class);
|
||||
if (sql != null) {
|
||||
descriptor.setEntityType(BeanDescriptor.EntityType.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.persistence.ManyToOne;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
@@ -52,6 +53,7 @@ public class DeployCreateProperties {
|
||||
* Create the appropriate properties for a bean.
|
||||
*/
|
||||
public void createProperties(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
createProperties(desc, desc.getBeanType(), 0);
|
||||
desc.sortProperties();
|
||||
}
|
||||
@@ -87,14 +89,22 @@ public class DeployCreateProperties {
|
||||
// ignore all fields on model (_$dbName)
|
||||
return;
|
||||
}
|
||||
boolean scalaObject = desc.isScalaObject();
|
||||
|
||||
try {
|
||||
Method[] declaredMethods = beanType.getDeclaredMethods();
|
||||
Field[] fields = beanType.getDeclaredFields();
|
||||
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
|
||||
Field field = fields[i];
|
||||
if (!ignoreField(field)) {
|
||||
DeployBeanProperty prop = createProp(desc, field, beanType);
|
||||
String fieldName = getFieldName(field, beanType);
|
||||
String initFieldName = initCap(fieldName);
|
||||
|
||||
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
|
||||
|
||||
DeployBeanProperty prop = createProp(desc, field, beanType, getter);
|
||||
if (prop != null) {
|
||||
// set a order that gives priority to inherited properties
|
||||
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
|
||||
@@ -127,6 +137,68 @@ public class DeployCreateProperties {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the first letter of the string upper case.
|
||||
*/
|
||||
private String initCap(String str) {
|
||||
if (str.length() > 1) {
|
||||
return Character.toUpperCase(str.charAt(0)) + str.substring(1);
|
||||
} else {
|
||||
// only a single char
|
||||
return str.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean spec field name (trim of "is" from boolean types)
|
||||
*/
|
||||
private String getFieldName(Field field, Class<?> beanType) {
|
||||
|
||||
String name = field.getName();
|
||||
|
||||
if ((Boolean.class.equals(field.getType()) || boolean.class.equals(field.getType()))
|
||||
&& name.startsWith("is") && name.length() > 2) {
|
||||
|
||||
// it is a boolean type field starting with "is"
|
||||
char c = name.charAt(2);
|
||||
if (Character.isUpperCase(c)) {
|
||||
String msg = "trimming off 'is' from boolean field name " + name + " in class " + beanType.getName();
|
||||
logger.info(msg);
|
||||
|
||||
return name.substring(2);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a public non-static getter method that matches this field (according to bean-spec rules).
|
||||
*/
|
||||
private Method findGetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject) {
|
||||
|
||||
String methGetName = "get" + initFieldName;
|
||||
String methIsName = "is" + initFieldName;
|
||||
String scalaGet = field.getName();
|
||||
|
||||
for (Method m : declaredMethods) {
|
||||
if ((scalaObject && m.getName().equals(scalaGet)) || m.getName().equals(methGetName)
|
||||
|| m.getName().equals(methIsName)) {
|
||||
|
||||
Class<?>[] params = m.getParameterTypes();
|
||||
if (params.length == 0) {
|
||||
if (field.getType().equals(m.getReturnType())) {
|
||||
int modifiers = m.getModifiers();
|
||||
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
|
||||
// we find it...
|
||||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
|
||||
@@ -146,7 +218,7 @@ public class DeployCreateProperties {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
|
||||
ManyToOne manyToOne = AnnotationUtil.get(field, ManyToOne.class);
|
||||
ManyToOne manyToOne = AnnotationUtil.findAnnotation(field, ManyToOne.class);
|
||||
if (manyToOne != null) {
|
||||
Class<?> tt = manyToOne.targetEntity();
|
||||
if (!tt.equals(void.class)) {
|
||||
@@ -163,7 +235,8 @@ public class DeployCreateProperties {
|
||||
// List, Set or Map based object
|
||||
Class<?> targetType = determineTargetType(field);
|
||||
if (targetType == null) {
|
||||
if (AnnotationUtil.has(field, Transient.class)) {
|
||||
Transient transAnnotation = AnnotationUtil.findAnnotation(field, Transient.class);
|
||||
if (transAnnotation != null) {
|
||||
// not supporting this field (generic type used)
|
||||
return null;
|
||||
}
|
||||
@@ -198,18 +271,21 @@ public class DeployCreateProperties {
|
||||
* Return true if the field has one of the special mappings.
|
||||
*/
|
||||
private boolean isSpecialScalarType(Field field) {
|
||||
return (AnnotationUtil.has(field, DbJson.class))
|
||||
|| (AnnotationUtil.has(field, DbJsonB.class))
|
||||
|| (AnnotationUtil.has(field, DbArray.class))
|
||||
|| (AnnotationUtil.has(field, DbMap.class))
|
||||
|| (AnnotationUtil.has(field, UnmappedJson.class));
|
||||
return (AnnotationUtil.findAnnotation(field, DbJson.class) != null)
|
||||
|| (AnnotationUtil.findAnnotation(field, DbJsonB.class) != null)
|
||||
|| (AnnotationUtil.findAnnotation(field, DbArray.class) != null)
|
||||
|| (AnnotationUtil.findAnnotation(field, DbMap.class) != null)
|
||||
|| (AnnotationUtil.findAnnotation(field, UnmappedJson.class) != null);
|
||||
}
|
||||
|
||||
private boolean isTransientField(Field field) {
|
||||
return AnnotationUtil.has(field, Transient.class);
|
||||
|
||||
Transient t = AnnotationUtil.findAnnotation(field, Transient.class);
|
||||
return (t != null);
|
||||
}
|
||||
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field, Class<?> beanType) {
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter) {
|
||||
|
||||
DeployBeanProperty prop = createProp(desc, field);
|
||||
if (prop == null) {
|
||||
// transient annotation on unsupported type
|
||||
@@ -217,6 +293,9 @@ public class DeployCreateProperties {
|
||||
} else {
|
||||
prop.setOwningType(beanType);
|
||||
prop.setName(field.getName());
|
||||
|
||||
// interested in the getter for reading annotations
|
||||
prop.setReadMethod(getter);
|
||||
prop.setField(field);
|
||||
return prop;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -109,11 +110,11 @@ public class DeployInherit {
|
||||
info.setParent(parent);
|
||||
}
|
||||
|
||||
Inheritance ia = AnnotationUtil.typeGet(cls, Inheritance.class);
|
||||
Inheritance ia = AnnotationUtil.findAnnotationRecursive(cls, Inheritance.class);
|
||||
if (ia != null) {
|
||||
ia.strategy();
|
||||
}
|
||||
DiscriminatorColumn da = AnnotationUtil.typeGet(cls, DiscriminatorColumn.class);
|
||||
DiscriminatorColumn da = AnnotationUtil.findAnnotationRecursive(cls, DiscriminatorColumn.class);
|
||||
if (da != null) {
|
||||
// lowercase the discriminator column for RawSql and JSON
|
||||
info.setColumnName(da.name().toLowerCase());
|
||||
@@ -123,7 +124,7 @@ public class DeployInherit {
|
||||
}
|
||||
|
||||
if (!info.isAbstract()) {
|
||||
DiscriminatorValue dv = AnnotationUtil.get(cls, DiscriminatorValue.class); // do not search recursive
|
||||
DiscriminatorValue dv = AnnotationUtil.findAnnotation(cls, DiscriminatorValue.class); // do not search recursive
|
||||
if (dv != null) {
|
||||
info.setDiscriminatorValue(dv.value());
|
||||
} else {
|
||||
@@ -143,7 +144,17 @@ public class DeployInherit {
|
||||
}
|
||||
|
||||
private boolean isInheritanceClass(Class<?> cls) {
|
||||
return AnnotationUtil.typeHas(cls, Inheritance.class);
|
||||
while (true) {
|
||||
if (cls.equals(Object.class)) {
|
||||
return false;
|
||||
}
|
||||
Annotation a = AnnotationUtil.findAnnotationRecursive(cls, Inheritance.class);
|
||||
if (a != null) {
|
||||
return true;
|
||||
}
|
||||
// search up the inheritance heirarchy
|
||||
cls = cls.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
class InitMetaJacksonAnnotation {
|
||||
|
||||
static void init(ReadAnnotationConfig readConfig) {
|
||||
readConfig.addMetaAnnotation(com.fasterxml.jackson.annotation.JacksonAnnotation.class);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
class InitMetaValidationAnnotation {
|
||||
|
||||
static void init(ReadAnnotationConfig readConfig) {
|
||||
readConfig.addMetaAnnotation(Size.class);
|
||||
readConfig.addMetaAnnotation(Size.List.class);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,8 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.Aggregation;
|
||||
import io.ebean.annotation.Formula;
|
||||
import io.ebean.annotation.Where;
|
||||
import io.ebean.config.ServerConfig;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Configuration used when reading the deployment annotations.
|
||||
*/
|
||||
@@ -24,8 +17,6 @@ class ReadAnnotationConfig {
|
||||
private final boolean jacksonAnnotations;
|
||||
private final boolean idGeneratorAutomatic;
|
||||
|
||||
private final Set<Class<?>> metaAnnotations = new HashSet<>();
|
||||
|
||||
ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, ServerConfig serverConfig) {
|
||||
|
||||
this.generatedPropFactory = generatedPropFactory;
|
||||
@@ -37,16 +28,6 @@ class ReadAnnotationConfig {
|
||||
|
||||
this.javaxValidationAnnotations = generatedPropFactory.getClassLoadConfig().isJavaxValidationAnnotationsPresent();
|
||||
this.jacksonAnnotations = generatedPropFactory.getClassLoadConfig().isJacksonAnnotationsPresent();
|
||||
this.metaAnnotations.add(Column.class);
|
||||
this.metaAnnotations.add(Formula.class);
|
||||
this.metaAnnotations.add(Formula.List.class);
|
||||
this.metaAnnotations.add(Where.class);
|
||||
this.metaAnnotations.add(Where.List.class);
|
||||
this.metaAnnotations.add(Aggregation.class);
|
||||
}
|
||||
|
||||
public void addMetaAnnotation(Class<?> annotation) {
|
||||
metaAnnotations.add(annotation);
|
||||
}
|
||||
|
||||
GeneratedPropertyFactory getGeneratedPropFactory() {
|
||||
@@ -80,8 +61,4 @@ class ReadAnnotationConfig {
|
||||
boolean isJacksonAnnotations() {
|
||||
return jacksonAnnotations;
|
||||
}
|
||||
|
||||
public Set<Class<?>> getMetaAnnotations() {
|
||||
return metaAnnotations;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,12 +14,6 @@ public class ReadAnnotations {
|
||||
|
||||
public ReadAnnotations(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, ServerConfig serverConfig) {
|
||||
this.readConfig = new ReadAnnotationConfig(generatedPropFactory, asOfViewSuffix, versionsBetweenSuffix, serverConfig);
|
||||
if (readConfig.isJavaxValidationAnnotations()) {
|
||||
InitMetaValidationAnnotation.init(readConfig);
|
||||
}
|
||||
if (readConfig.isJacksonAnnotations()) {
|
||||
InitMetaJacksonAnnotation.init(readConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
@@ -45,10 +44,7 @@ final class InsertMeta {
|
||||
|
||||
private final String[] identityDbColumns;
|
||||
|
||||
private final Platform platform;
|
||||
|
||||
InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) {
|
||||
this.platform = dbPlatform.getPlatform();
|
||||
this.discriminator = getDiscriminator(desc);
|
||||
this.id = id;
|
||||
this.all = all;
|
||||
@@ -166,11 +162,7 @@ final class InsertMeta {
|
||||
|
||||
request.append("insert into ").append(table);
|
||||
if (nullId && noColumnsForInsert(draftTable)) {
|
||||
if (this.platform.base() == Platform.MYSQL) {
|
||||
request.append(" values (default)");
|
||||
} else {
|
||||
request.append(" default values");
|
||||
}
|
||||
request.append(" default values");
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
private <T> void flushJdbcBatchOnQuery(OrmQueryRequest<T> request) {
|
||||
|
||||
SpiTransaction t = request.getTransaction();
|
||||
if (t.isFlushOnQuery()) {
|
||||
if (t.isBatchFlushOnQuery()) {
|
||||
// before we perform a query, we need to flush any
|
||||
// previous persist requests that are queued/batched.
|
||||
// The query may read data affected by those requests.
|
||||
|
||||
@@ -302,11 +302,11 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,12 +325,12 @@ class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEventCode
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlushOnQuery() {
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -589,7 +589,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
this.batchGetGeneratedKeys = getGeneratedKeys;
|
||||
if (batchControl != null) {
|
||||
batchControl.setGetGeneratedKeys(getGeneratedKeys);
|
||||
@@ -597,7 +597,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
this.batchFlushOnMixed = batchFlushOnMixed;
|
||||
if (batchControl != null) {
|
||||
batchControl.setBatchFlushOnMixed(batchFlushOnMixed);
|
||||
@@ -624,12 +624,12 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlushOnQuery() {
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return batchFlushOnQuery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
this.batchFlushOnQuery = batchFlushOnQuery;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,19 +233,19 @@ class NoTransaction implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
public void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
public void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
public void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlushOnQuery() {
|
||||
public boolean isBatchFlushOnQuery() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -459,7 +459,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
* are annotated with the @JacksonAnnotation meta annotation. So detection is easy.
|
||||
*/
|
||||
private boolean checkJacksonAnnotations(DeployBeanProperty prop) {
|
||||
return prop.getMetaAnnotation(com.fasterxml.jackson.annotation.JacksonAnnotation.class) != null;
|
||||
return AnnotationUtil.findAnnotation(prop.getField(), com.fasterxml.jackson.annotation.JacksonAnnotation.class) != null;
|
||||
}
|
||||
|
||||
private DocPropertyType getDocType(Type genericType) {
|
||||
@@ -606,7 +606,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
Field[] fields = enumType.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
EnumValue enumValue = AnnotationUtil.get(field, EnumValue.class);
|
||||
EnumValue enumValue = AnnotationUtil.findAnnotation(field, EnumValue.class);
|
||||
if (enumValue != null) {
|
||||
nameValueMap.put(field.getName(), enumValue.value());
|
||||
if (integerType && !isIntegerType(enumValue.value())) {
|
||||
@@ -680,7 +680,7 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
|
||||
Method[] methods = enumType.getMethods();
|
||||
for (Method method : methods) {
|
||||
DbEnumValue dbValue = AnnotationUtil.get(method, DbEnumValue.class);
|
||||
DbEnumValue dbValue = AnnotationUtil.findAnnotation(method, DbEnumValue.class);
|
||||
if (dbValue != null) {
|
||||
boolean integerValues = DbEnumType.INTEGER == dbValue.storage();
|
||||
return createEnumScalarTypeDbValue(enumType, method, integerValues, dbValue.length());
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:18:31.280668Z
|
||||
-- Generated by ebean unknown at 2020-03-04T11:25:28.198394Z
|
||||
create table asimple_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
name varchar(255),
|
||||
@@ -275,7 +275,7 @@ create table drel_booking (
|
||||
constraint uq_drel_booking_client_invoice unique (client_invoice),
|
||||
constraint pk_drel_booking primary key (id)
|
||||
);
|
||||
create sequence drel_booking_seq increment by 1;
|
||||
create sequence drel_booking_seq increment by 50;
|
||||
|
||||
create table bw_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -396,7 +396,7 @@ create table sp_car_car (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_car primary key (id)
|
||||
);
|
||||
create sequence sp_car_car_seq increment by 1;
|
||||
create sequence sp_car_car_seq increment by 50;
|
||||
|
||||
create table sp_car_car_wheels (
|
||||
car bigint not null,
|
||||
@@ -417,7 +417,7 @@ create table sa_car (
|
||||
version integer not null,
|
||||
constraint pk_sa_car primary key (id)
|
||||
);
|
||||
create sequence sa_car_seq increment by 1;
|
||||
create sequence sa_car_seq increment by 50;
|
||||
|
||||
create table car_accessory (
|
||||
id integer generated by default as identity not null,
|
||||
@@ -864,7 +864,7 @@ create table sp_car_door (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_door primary key (id)
|
||||
);
|
||||
create sequence sp_car_door_seq increment by 1;
|
||||
create sequence sp_car_door_seq increment by 50;
|
||||
|
||||
create table earray_bean (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -1801,7 +1801,7 @@ create table gen_key_sequence (
|
||||
description varchar(255),
|
||||
constraint pk_gen_key_sequence primary key (id)
|
||||
);
|
||||
create sequence SEQ start with 1 increment by 1;
|
||||
create sequence SEQ start with 1 increment by 50;
|
||||
|
||||
create table gen_key_table (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -2018,7 +2018,7 @@ create table drel_invoice (
|
||||
version integer not null,
|
||||
constraint pk_drel_invoice primary key (id)
|
||||
);
|
||||
create sequence drel_invoice_seq increment by 1;
|
||||
create sequence drel_invoice_seq increment by 50;
|
||||
|
||||
create table item (
|
||||
customer integer not null,
|
||||
@@ -3614,7 +3614,7 @@ create table t_detail_with_other_namexxxyy (
|
||||
constraint uq_t_detail_with_other_namexxxyy_some_unique_value unique (some_unique_value),
|
||||
constraint pk_t_detail_with_other_namexxxyy primary key (id)
|
||||
);
|
||||
create sequence t_atable_detail_seq increment by 1;
|
||||
create sequence t_atable_detail_seq increment by 50;
|
||||
|
||||
create table t_atable_thatisrelatively (
|
||||
id integer not null,
|
||||
@@ -3623,7 +3623,7 @@ create table t_atable_thatisrelatively (
|
||||
active boolean default false not null,
|
||||
constraint pk_t_atable_thatisrelatively primary key (id)
|
||||
);
|
||||
create sequence t_atable_master_seq increment by 1;
|
||||
create sequence t_atable_master_seq increment by 50;
|
||||
|
||||
create table ttruck_holder (
|
||||
id bigint generated by default as identity not null,
|
||||
@@ -3692,14 +3692,14 @@ create table tire (
|
||||
constraint uq_tire_wheel unique (wheel),
|
||||
constraint pk_tire primary key (id)
|
||||
);
|
||||
create sequence tire_seq increment by 1;
|
||||
create sequence tire_seq increment by 50;
|
||||
|
||||
create table sa_tire (
|
||||
id bigint not null,
|
||||
version integer not null,
|
||||
constraint pk_sa_tire primary key (id)
|
||||
);
|
||||
create sequence sa_tire_seq increment by 1;
|
||||
create sequence sa_tire_seq increment by 50;
|
||||
|
||||
create table tree_entity (
|
||||
id integer generated by default as identity not null,
|
||||
@@ -3924,7 +3924,7 @@ create table wheel (
|
||||
version integer not null,
|
||||
constraint pk_wheel primary key (id)
|
||||
);
|
||||
create sequence wheel_seq increment by 1;
|
||||
create sequence wheel_seq increment by 50;
|
||||
|
||||
create table sa_wheel (
|
||||
id bigint not null,
|
||||
@@ -3933,7 +3933,7 @@ create table sa_wheel (
|
||||
version integer not null,
|
||||
constraint pk_sa_wheel primary key (id)
|
||||
);
|
||||
create sequence sa_wheel_seq increment by 1;
|
||||
create sequence sa_wheel_seq increment by 50;
|
||||
|
||||
create table sp_car_wheel (
|
||||
id bigint not null,
|
||||
@@ -3941,7 +3941,7 @@ create table sp_car_wheel (
|
||||
version integer not null,
|
||||
constraint pk_sp_car_wheel primary key (id)
|
||||
);
|
||||
create sequence sp_car_wheel_seq increment by 1;
|
||||
create sequence sp_car_wheel_seq increment by 50;
|
||||
|
||||
create table g_who_props_otm (
|
||||
id bigint generated by default as identity not null,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- Generated by ebean unknown at 2020-03-04T11:18:31.280668Z
|
||||
-- Generated by ebean unknown at 2020-03-04T11:25:28.198394Z
|
||||
alter table if exists bar drop constraint if exists fk_bar_foo_id;
|
||||
drop index if exists ix_bar_foo_id;
|
||||
|
||||
|
||||
@@ -138,11 +138,8 @@ public class ServerConfigTest {
|
||||
assertEquals(JsonConfig.DateTime.ISO8601, serverConfig.getJsonDateTime());
|
||||
assertEquals(JsonConfig.Date.ISO8601, serverConfig.getJsonDate());
|
||||
assertTrue(serverConfig.getPlatformConfig().isCaseSensitiveCollation());
|
||||
assertTrue(serverConfig.isAutoLoadModuleInfo());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
|
||||
serverConfig.setLoadModuleInfo(false);
|
||||
assertFalse(serverConfig.isAutoLoadModuleInfo());
|
||||
assertEquals(Long.MAX_VALUE, serverConfig.getCollectQueryPlanThresholdMicros());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -49,7 +49,7 @@ public class DatabasePlatformTest {
|
||||
public void defaultTypesForDecimalAndVarchar() {
|
||||
|
||||
DatabasePlatform dbPlatform = new DatabasePlatform();
|
||||
assertEquals(defaultDecimalDefn(dbPlatform), "decimal(16,3)");
|
||||
assertEquals(defaultDecimalDefn(dbPlatform), "decimal(38)");
|
||||
assertEquals(defaultDefn(DbType.VARCHAR, dbPlatform), "varchar(255)");
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ public class H2PlatformTest {
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("varchar(20)");
|
||||
assertThat(ddl.convert("decimal(10)")).isEqualTo("decimal(10)");
|
||||
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("decimal(8,4)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("decimal(16,3)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("boolean");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("bit");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ public class HanaPlatformTest {
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("nvarchar(20)");
|
||||
assertThat(ddl.convert("decimal(10)")).isEqualTo("decimal(10)");
|
||||
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("decimal(8,4)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("decimal(16,3)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("boolean");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("smallint");
|
||||
assertThat(ddl.convert("tinyint")).isEqualTo("smallint");
|
||||
|
||||
@@ -21,7 +21,6 @@ public class MySqlPlatformTest {
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("varchar(20)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("tinyint(1)");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("tinyint(1)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("decimal(16,3)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,7 +26,6 @@ public class OraclePlatformTest {
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("varchar2(20)");
|
||||
assertThat(ddl.convert("decimal(10)")).isEqualTo("number(10)");
|
||||
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("number(8,4)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("number(16,3)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("number(1)");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("bit");
|
||||
assertThat(ddl.convert("tinyint")).isEqualTo("number(3)");
|
||||
|
||||
@@ -26,11 +26,11 @@ public class PostgresPlatformTest {
|
||||
assertThat(ddl.convert("tinyint")).isEqualTo("smallint");
|
||||
assertThat(ddl.convert("double")).isEqualTo("float");
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("varchar(20)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("decimal(16,3)");
|
||||
assertThat(ddl.convert("decimal(10)")).isEqualTo("decimal(10)");
|
||||
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("decimal(8,4)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("boolean");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("bit");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -39,18 +39,18 @@ public class SequenceBatchIdGeneratorTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
public String getSql() {
|
||||
return "not used";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Long> readIds(ResultSet resultSet, int loadSize) {
|
||||
protected List<Long> readIds(ResultSet resultSet) {
|
||||
// do nothing
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Long> getMoreIds(int requestSize) {
|
||||
protected List<Long> getMoreIds() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ public class SqlserverPlatformTest {
|
||||
assertThat(ddl.convert("varchar(20)")).isEqualTo("nvarchar(20)");
|
||||
assertThat(ddl.convert("decimal(10)")).isEqualTo("numeric(10)");
|
||||
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("numeric(8,4)");
|
||||
assertThat(ddl.convert("decimal")).isEqualTo("numeric(16,3)");
|
||||
assertThat(ddl.convert("boolean")).isEqualTo("bit");
|
||||
assertThat(ddl.convert("bit")).isEqualTo("bit");
|
||||
assertThat(ddl.convert("tinyint")).isEqualTo("smallint");
|
||||
|
||||
+3
-3
@@ -13,9 +13,9 @@ import javax.sql.DataSource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class SqlServerStepSequenceTest extends BaseTestCase {
|
||||
public class SqlServerDbSequenceTest extends BaseTestCase {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SqlServerStepSequenceTest.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(SqlServerDbSequenceTest.class);
|
||||
|
||||
@Ignore
|
||||
@ForPlatform(Platform.SQLSERVER)
|
||||
@@ -29,7 +29,7 @@ public class SqlServerStepSequenceTest extends BaseTestCase {
|
||||
BackgroundExecutor be = server().getBackgroundExecutor();
|
||||
DataSource ds = server().getPluginApi().getDataSource();
|
||||
|
||||
SqlServerStepSequence s = new SqlServerStepSequence(be, ds, "sqls_testseq_9876", 50);
|
||||
SqlServerDbSequence s = new SqlServerDbSequence(be, ds, "sqls_testseq_9876", 50);
|
||||
|
||||
Object id = s.nextId(null);
|
||||
assertThat(id).isEqualTo(1L);
|
||||
@@ -48,7 +48,6 @@ public class DbMigrationGenerateTest {
|
||||
// migration.addPlatform(Platform.SQLANYWHERE, "sqlanywhere"); and sqlanywhere
|
||||
migration.addPlatform(Platform.DB2, "db2");
|
||||
migration.addPlatform(Platform.H2, "h2");
|
||||
migration.addPlatform(Platform.HSQLDB, "hsqldb");
|
||||
migration.addPlatform(Platform.MYSQL, "mysql");
|
||||
migration.addPlatform(Platform.MYSQL55, "mysql55");
|
||||
migration.addPlatform(Platform.POSTGRES, "postgres");
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.annotation.Index;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.Where;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.ValidationGroupSomething;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.lang.annotation.ElementType;
|
||||
@@ -20,11 +17,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.ebean.annotation.Platform.H2;
|
||||
import static io.ebean.annotation.Platform.POSTGRES;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -32,41 +25,27 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class TestAnnotationBase extends BaseTestCase {
|
||||
|
||||
private final Set<Class<?>> metaAnnotationsFilter = new HashSet<>();
|
||||
|
||||
public TestAnnotationBase() {
|
||||
metaAnnotationsFilter.add(Where.class);
|
||||
metaAnnotationsFilter.add(Where.List.class);
|
||||
}
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Where(clause = "SELECT 'mysql' from 1", platforms = Platform.MYSQL)
|
||||
@Where(clause = "SELECT 'h2' from 1", platforms = H2)
|
||||
@Where(clause = "SELECT 'h2' from 1", platforms = Platform.H2)
|
||||
@Where(clause = "SELECT 'other' from 1")
|
||||
public @interface MetaTest {
|
||||
|
||||
}
|
||||
|
||||
@Index(name = "ano_1", columnNames = "direct", platforms = {H2, POSTGRES})
|
||||
@Index(name = "ano_2", columnNames = "direct", platforms = {H2, POSTGRES})
|
||||
@MappedSuperclass
|
||||
public static class MappedBaseEntity {
|
||||
|
||||
}
|
||||
|
||||
@Index(name = "ano_3", columnNames = "direct")
|
||||
@Entity
|
||||
public static class TestAnnotationBaseEntity extends MappedBaseEntity {
|
||||
public static class TestAnnotationBaseEntity {
|
||||
|
||||
@Where(clause = "SELECT 'mysql' from 1", platforms = Platform.MYSQL)
|
||||
@Where(clause = "SELECT 'h2' from 1", platforms = H2)
|
||||
@Where(clause = "SELECT 'h2' from 1", platforms = Platform.H2)
|
||||
@Where(clause = "SELECT 'other' from 1")
|
||||
private String direct;
|
||||
|
||||
@MetaTest
|
||||
private String meta;
|
||||
|
||||
|
||||
@MetaTest
|
||||
@Where(clause = "SELECT 'oracle' from 1", platforms = Platform.ORACLE)
|
||||
private String mixed;
|
||||
@@ -152,13 +131,6 @@ public class TestAnnotationBase extends BaseTestCase {
|
||||
assertEquals(40, bp.getDbLength());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void annotationClassIndexes() throws SecurityException {
|
||||
BeanDescriptor<TestAnnotationBaseEntity> descriptor = spiEbeanServer().getBeanDescriptor(TestAnnotationBaseEntity.class);
|
||||
final IndexDefinition[] indexDefinitions = descriptor.getIndexDefinitions();
|
||||
assertEquals(3, indexDefinitions.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotNullWithGroup() throws SecurityException {
|
||||
BeanDescriptor<TestAnnotationBaseEntity> descriptor = spiEbeanServer().getBeanDescriptor(TestAnnotationBaseEntity.class);
|
||||
@@ -175,41 +147,45 @@ public class TestAnnotationBase extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testFindAnnotation() throws NoSuchFieldException, SecurityException {
|
||||
Field fld = TestAnnotationBaseEntity.class.getDeclaredField("direct");
|
||||
String s;
|
||||
|
||||
Field directFld = TestAnnotationBaseEntity.class.getDeclaredField("direct");
|
||||
final DeployBeanProperty direct = createProperty(directFld);
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.MYSQL).clause();
|
||||
assertEquals("SELECT 'mysql' from 1", s);
|
||||
|
||||
assertEquals("SELECT 'mysql' from 1", where(direct, Platform.MYSQL));
|
||||
assertEquals("SELECT 'h2' from 1", where(direct, H2));
|
||||
assertEquals("SELECT 'other' from 1", where(direct, Platform.POSTGRES));
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.H2).clause();
|
||||
assertEquals("SELECT 'h2' from 1", s);
|
||||
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.POSTGRES).clause();
|
||||
assertEquals("SELECT 'other' from 1", s);
|
||||
|
||||
// meta
|
||||
Field metaFld = TestAnnotationBaseEntity.class.getDeclaredField("meta");
|
||||
final DeployBeanProperty meta = createProperty(metaFld);
|
||||
fld = TestAnnotationBaseEntity.class.getDeclaredField("meta");
|
||||
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.MYSQL).clause();
|
||||
assertEquals("SELECT 'mysql' from 1", s);
|
||||
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.H2).clause();
|
||||
assertEquals("SELECT 'h2' from 1", s);
|
||||
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.POSTGRES).clause();
|
||||
assertEquals("SELECT 'other' from 1", s);
|
||||
|
||||
assertEquals("SELECT 'mysql' from 1", where(meta, Platform.MYSQL));
|
||||
assertEquals("SELECT 'h2' from 1", where(meta, H2));
|
||||
assertEquals("SELECT 'other' from 1", where(meta, Platform.POSTGRES));
|
||||
|
||||
// mixed
|
||||
Field mixedFld = TestAnnotationBaseEntity.class.getDeclaredField("mixed");
|
||||
final DeployBeanProperty mixed = createProperty(mixedFld);
|
||||
fld = TestAnnotationBaseEntity.class.getDeclaredField("mixed");
|
||||
|
||||
assertEquals("SELECT 'mysql' from 1", where(mixed, Platform.MYSQL));
|
||||
assertEquals("SELECT 'h2' from 1", where(mixed, H2));
|
||||
assertEquals("SELECT 'other' from 1", where(mixed, Platform.POSTGRES));
|
||||
assertEquals("SELECT 'oracle' from 1", where(mixed, Platform.ORACLE));
|
||||
}
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.MYSQL).clause();
|
||||
assertEquals("SELECT 'mysql' from 1", s);
|
||||
|
||||
private String where(DeployBeanProperty property, Platform platform) {
|
||||
return property.getMetaAnnotationWhere(platform).clause();
|
||||
}
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.H2).clause();
|
||||
assertEquals("SELECT 'h2' from 1", s);
|
||||
|
||||
private DeployBeanProperty createProperty(Field fld) {
|
||||
DeployBeanProperty directProperty = new DeployBeanProperty(null, null, null);
|
||||
directProperty.setField(fld);
|
||||
directProperty.initMetaAnnotations(metaAnnotationsFilter);
|
||||
return directProperty;
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.POSTGRES).clause();
|
||||
assertEquals("SELECT 'other' from 1", s);
|
||||
|
||||
s = AnnotationUtil.findAnnotation(fld, Where.class, Platform.ORACLE).clause();
|
||||
assertEquals("SELECT 'oracle' from 1", s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestWhereAnnotation extends TransactionalTestCase {
|
||||
|
||||
@Test
|
||||
@@ -31,6 +29,6 @@ public class TestWhereAnnotation extends TransactionalTestCase {
|
||||
|
||||
q1.findOne();
|
||||
String s1 = q1.getGeneratedSql();
|
||||
assertThat(s1).contains("t1.order_date is not null");
|
||||
Assert.assertTrue(s1.contains("t1.order_date is not null"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
transaction.setBatchOnCascade(true);
|
||||
transaction.setBatchSize(30);
|
||||
// setBatchGetGeneratedKeys MUST be turned off for MS SQL Server because :(
|
||||
transaction.setGetGeneratedKeys(false);
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
for (int i = 0; i < numOfMasters; i++) {
|
||||
UTMaster master = createMasterAndDetails(i, 20);
|
||||
@@ -108,7 +108,7 @@ public class TestBatchInsertSimple extends BaseTestCase {
|
||||
transaction.setBatchOnCascade(true);
|
||||
transaction.setBatchSize(30);
|
||||
// setBatchGetGeneratedKeys MUST be turned off for MS SQL Server because :(
|
||||
transaction.setGetGeneratedKeys(false);
|
||||
transaction.setBatchGetGeneratedKeys(false);
|
||||
|
||||
for (int i = 0; i < numOfMasters; i++) {
|
||||
UTMaster master = createMaster(i);
|
||||
|
||||
+9
-12
@@ -95,10 +95,8 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
@Entity
|
||||
@Table(name = "em_user")
|
||||
public static class User {
|
||||
@Id
|
||||
private Long id;
|
||||
private String name;
|
||||
@OneToMany(cascade = CascadeType.REMOVE)
|
||||
private Set<UserRole> userRoles;
|
||||
|
||||
public User() {
|
||||
@@ -109,6 +107,7 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -125,6 +124,7 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@OneToMany(cascade = CascadeType.REMOVE)
|
||||
public Set<UserRole> getUserRoles() {
|
||||
return userRoles;
|
||||
}
|
||||
@@ -138,18 +138,11 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
@Table(name = "em_user_role")
|
||||
public static class UserRole implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@EmbeddedId
|
||||
private UserRolePK pk;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
|
||||
private User user;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "role_id", nullable = false, insertable = false, updatable = false)
|
||||
private Role role;
|
||||
|
||||
@EmbeddedId
|
||||
public UserRolePK getPk() {
|
||||
return pk;
|
||||
}
|
||||
@@ -158,6 +151,8 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false)
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
@@ -166,6 +161,8 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "role_id", nullable = false, insertable = false, updatable = false)
|
||||
public Role getRole() {
|
||||
return role;
|
||||
}
|
||||
@@ -216,12 +213,11 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
@Entity
|
||||
@Table(name = "em_role")
|
||||
public static class Role {
|
||||
@Id
|
||||
private Long id;
|
||||
private String name;
|
||||
@OneToMany(cascade = CascadeType.REMOVE)
|
||||
private Set<UserRole> userRoles;
|
||||
|
||||
@Id
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -238,6 +234,7 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@OneToMany(cascade = CascadeType.REMOVE)
|
||||
public Set<UserRole> getUserRoles() {
|
||||
return userRoles;
|
||||
}
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
package org.tests.defaultvalues;
|
||||
|
||||
import io.ebean.annotation.Draft;
|
||||
import io.ebean.annotation.Draftable;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Draftable
|
||||
public class DefaultsModel {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@Draft
|
||||
boolean draft;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
List<ReferencedDefaultsModel> relatedModels;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<ReferencedDefaultsModel> getRelatedModels() {
|
||||
return relatedModels;
|
||||
}
|
||||
|
||||
public void setRelatedModels(final List<ReferencedDefaultsModel> relatedModels) {
|
||||
this.relatedModels = relatedModels;
|
||||
}
|
||||
|
||||
public boolean isDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
||||
public void setDraft(final boolean draft) {
|
||||
this.draft = draft;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package org.tests.defaultvalues;
|
||||
|
||||
import io.ebean.annotation.Draft;
|
||||
import io.ebean.annotation.Draftable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
@Draftable
|
||||
public class ReferencedDefaultsModel {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
String name;
|
||||
|
||||
@Draft
|
||||
boolean draft;
|
||||
|
||||
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 boolean isDraft() {
|
||||
return draft;
|
||||
}
|
||||
|
||||
public void setDraft(final boolean draft) {
|
||||
this.draft = draft;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package org.tests.defaultvalues;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.Ebean;
|
||||
import org.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestDefaults extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testInsertDefaultValues() {
|
||||
final DefaultsModel main = new DefaultsModel();
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final ReferencedDefaultsModel ref = new ReferencedDefaultsModel();
|
||||
ref.setName("r" + i);
|
||||
main.getRelatedModels().add(ref);
|
||||
}
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.save(main);
|
||||
final List<String> current = LoggedSqlCollector.current();
|
||||
|
||||
assertThat(current).isNotEmpty();
|
||||
if (isMySql()) {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft values (default);");
|
||||
} else {
|
||||
assertThat(current.get(0)).contains("insert into defaults_model_draft default values;");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,10 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
|
||||
@Entity
|
||||
@SequenceGenerator(name = "SEQ_NAME", sequenceName = GenKeySequence.SEQUENCE_NAME)
|
||||
public class GenKeySequence {
|
||||
public final static String SEQUENCE_NAME = "SEQ";
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.tests.idkeys.db;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class GenKeyTable {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE)
|
||||
private Long id;
|
||||
|
||||
private String description;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.tests.inheritance.cache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class CIAddress extends CIBaseModel {
|
||||
|
||||
@ManyToOne
|
||||
public CIStreetParent street;
|
||||
|
||||
public CIStreetParent getStreet() {
|
||||
return street;
|
||||
}
|
||||
|
||||
public void setStreet(CIStreetParent street) {
|
||||
this.street = street;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package org.tests.inheritance.cache;
|
||||
|
||||
import io.ebean.Model;
|
||||
import io.ebean.annotation.Cache;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
@Cache(enableQueryCache=true)
|
||||
@MappedSuperclass
|
||||
public abstract class CIBaseModel extends Model {
|
||||
|
||||
@Id
|
||||
protected long id;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.tests.inheritance.cache;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue(value="1")
|
||||
public class CICustomer extends CICustomerParent {
|
||||
|
||||
public String notes;
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user