mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
53
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8115c5e230 | ||
|
|
ad180c5531 | ||
|
|
b454f46dd4 | ||
|
|
8a853b28f3 | ||
|
|
a1be7ba5dd | ||
|
|
3914516793 | ||
|
|
8c5854f77c | ||
|
|
0bc5b94eae | ||
|
|
12fa287f35 | ||
|
|
2991cb9ad1 | ||
|
|
3b7f5496a8 | ||
|
|
4be703ff6e | ||
|
|
d2c5765ac1 | ||
|
|
aaf256b9be | ||
|
|
c7c6410cd9 | ||
|
|
2c3c23725a | ||
|
|
92069c0319 | ||
|
|
630ad66ff1 | ||
|
|
b732b390c7 | ||
|
|
8c62fcdcb2 | ||
|
|
e458f577fe | ||
|
|
23434bab8c | ||
|
|
c47b5a1595 | ||
|
|
411846347b | ||
|
|
3722d19424 | ||
|
|
04a7310e5d | ||
|
|
3490e90f03 | ||
|
|
d89817a5c5 | ||
|
|
db1ba5f20e | ||
|
|
4f9a9a5094 | ||
|
|
1c6ac1289d | ||
|
|
b96be84106 | ||
|
|
3c40293183 | ||
|
|
a9a6031986 | ||
|
|
b82085da42 | ||
|
|
9a17a7752c | ||
|
|
92474c2b24 | ||
|
|
9a00b9df0e | ||
|
|
697f67c14a | ||
|
|
2c34bc1636 | ||
|
|
1f9ccf1c8b | ||
|
|
a1f10b8704 | ||
|
|
3c21950b91 | ||
|
|
3b45308ac7 | ||
|
|
00e69e1b5d | ||
|
|
11b3f7a813 | ||
|
|
2185c8a886 | ||
|
|
f8bda05b37 | ||
|
|
0a3b819991 | ||
|
|
5c8b1eb3bb | ||
|
|
824f6dcc7e | ||
|
|
06e23b85ad | ||
|
|
09219c759b |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>7.15.1</version>
|
||||
<version>7.18.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:https://github.com/ebean-orm/avaje-ebeanorm.git</developerConnection>
|
||||
<tag>avaje-ebeanorm-7.15.1</tag>
|
||||
<tag>avaje-ebeanorm-7.18.1</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
@@ -177,7 +177,7 @@
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.189</version>
|
||||
<version>1.4.192</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -38,6 +38,11 @@ public interface BeanState {
|
||||
*/
|
||||
void setDisableLazyLoad(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Return true if the bean has lazy loading disabled.
|
||||
*/
|
||||
boolean isDisableLazyLoad();
|
||||
|
||||
/**
|
||||
* Set the loaded state of the property given it's name.
|
||||
*
|
||||
|
||||
@@ -49,7 +49,7 @@ final class DRawSqlColumnsParser {
|
||||
if (split.length > 1) {
|
||||
ArrayList<String> tmp = new ArrayList<String>(split.length);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (split[i].trim().length() > 0) {
|
||||
if (!split[i].trim().isEmpty()) {
|
||||
tmp.add(split[i].trim());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public final class Ebean {
|
||||
// look to see if there is a default server defined
|
||||
String defaultName = PrimaryServer.getDefaultServerName();
|
||||
logger.debug("defaultName:" + defaultName);
|
||||
if (defaultName != null && defaultName.trim().length() > 0) {
|
||||
if (defaultName != null && !defaultName.trim().isEmpty()) {
|
||||
defaultServer = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ public final class Ebean {
|
||||
}
|
||||
|
||||
private EbeanServer get(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return defaultServer;
|
||||
}
|
||||
// non-synchronized read
|
||||
@@ -945,6 +945,21 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
* </p>
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query for a type of entity bean.
|
||||
* <p>
|
||||
|
||||
@@ -199,6 +199,19 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> UpdateQuery<T> update(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
* </p>
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
<T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
|
||||
|
||||
/**
|
||||
* Create a query for an entity bean and synonym for {@link #find(Class)}.
|
||||
*
|
||||
|
||||
@@ -400,6 +400,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
}
|
||||
|
||||
private boolean isEmptyString(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,6 @@ class PrimaryServer {
|
||||
* Return true if the string is null or empty.
|
||||
*/
|
||||
private static boolean isEmpty(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,9 +606,9 @@ public final class RawSql implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private static String derivePropertyName(String dbAlias, String dbColumn) {
|
||||
protected static String derivePropertyName(String dbAlias, String dbColumn) {
|
||||
if (dbAlias != null) {
|
||||
return dbAlias;
|
||||
return CamelCaseHelper.toCamelFromUnderscore(dbAlias);
|
||||
}
|
||||
int dotPos = dbColumn.indexOf('.');
|
||||
if (dotPos > -1) {
|
||||
|
||||
@@ -26,7 +26,7 @@ package com.avaje.ebean;
|
||||
*
|
||||
* int modifiedCount = Ebean.execute(update);
|
||||
*
|
||||
* String msg = "There where " + modifiedCount + "rows updated"
|
||||
* String msg = "There were " + modifiedCount + " rows updated"
|
||||
* </pre>
|
||||
*
|
||||
* @see Update
|
||||
@@ -143,4 +143,4 @@ public interface SqlUpdate {
|
||||
*/
|
||||
SqlUpdate setNullParameter(String name, int jdbcType);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.ArrayList;
|
||||
* This object is used internally with the enhancement of a method with
|
||||
* Transactional annotation.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see TxCallable
|
||||
* @see TxRunnable
|
||||
* @see Ebean#execute(TxScope, TxCallable)
|
||||
@@ -44,27 +44,6 @@ public final class TxScope {
|
||||
|
||||
ArrayList<Class<? extends Throwable>> noRollbackFor;
|
||||
|
||||
/**
|
||||
* Return true if PersistBatch has been set.
|
||||
*/
|
||||
public boolean isBatchSet() {
|
||||
return batch != null && batch != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch on cascade has been set.
|
||||
*/
|
||||
public boolean isBatchOnCascadeSet() {
|
||||
return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch size has been set.
|
||||
*/
|
||||
public boolean isBatchSizeSet() {
|
||||
return batchSize > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a TxScope with REQUIRES.
|
||||
*/
|
||||
@@ -130,6 +109,44 @@ public final class TxScope {
|
||||
+ "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if PersistBatch has been set.
|
||||
*/
|
||||
public boolean isBatchSet() {
|
||||
return batch != null && batch != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch on cascade has been set.
|
||||
*/
|
||||
public boolean isBatchOnCascadeSet() {
|
||||
return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch size has been set.
|
||||
*/
|
||||
public boolean isBatchSizeSet() {
|
||||
return batchSize > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for batchSize being set without batch mode and use this to imply PersistBatch.ALL.
|
||||
*/
|
||||
public void checkBatchMode() {
|
||||
if (batchSize > 0 && notSet(batch) && notSet(batchOnCascade)) {
|
||||
// Use setting the batchSize as implying PersistBatch.ALL for @Transactional
|
||||
batch = PersistBatch.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the mode is considered not set.
|
||||
*/
|
||||
private boolean notSet(PersistBatch batchMode) {
|
||||
return batchMode == null || batchMode == PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction type.
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,11 @@ public interface BeanCollection<E> extends Serializable {
|
||||
ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the disableLazyLoad state.
|
||||
*/
|
||||
void setDisableLazyLoad(boolean disableLazyLoad);
|
||||
|
||||
/**
|
||||
* Load bean from another collection.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,8 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
protected boolean readOnly;
|
||||
|
||||
protected boolean disableLazyLoad;
|
||||
|
||||
/**
|
||||
* The EbeanServer this is associated with. (used for lazy fetch).
|
||||
*/
|
||||
@@ -84,6 +86,11 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.filterMany = filterMany;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisableLazyLoad(boolean disableLazyLoad) {
|
||||
this.disableLazyLoad = disableLazyLoad;
|
||||
}
|
||||
|
||||
protected void lazyLoadCollection(boolean onlyIds) {
|
||||
if (loader == null) {
|
||||
loader = (BeanCollectionLoader) Ebean.getServer(ebeanServerName);
|
||||
|
||||
@@ -102,7 +102,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
private void initClear() {
|
||||
synchronized (this) {
|
||||
if (list == null) {
|
||||
if (modifyListening) {
|
||||
if (!disableLazyLoad && modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
} else {
|
||||
list = new ArrayList<E>();
|
||||
@@ -114,7 +114,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
private void init() {
|
||||
synchronized (this) {
|
||||
if (list == null) {
|
||||
lazyLoadCollection(false);
|
||||
if (disableLazyLoad) {
|
||||
list = new ArrayList<E>();
|
||||
} else {
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +274,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
protected boolean isEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -163,6 +163,17 @@ public class ServerConfig {
|
||||
*/
|
||||
private int databaseSequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* JDBC fetchSize hint when using findList. Defaults to 0 leaving it up to the JDBC driver.
|
||||
*/
|
||||
private int jdbcFetchSizeFindList;
|
||||
|
||||
/**
|
||||
* JDBC fetchSize hint when using findEach/findEachWhile. Defaults to 100. Note that this does
|
||||
* not apply to MySql as that gets special treatment (forward only etc).
|
||||
*/
|
||||
private int jdbcFetchSizeFindEach = 100;
|
||||
|
||||
/**
|
||||
* Suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
@@ -187,9 +198,11 @@ public class ServerConfig {
|
||||
private PersistBatch persistBatch = PersistBatch.NONE;
|
||||
|
||||
/**
|
||||
* Use for per request batch mode.
|
||||
* Use for cascade persist JDBC batch mode. INHERIT means use the platform default
|
||||
* which is ALL except for SQL Server where it is NONE (as getGeneratedKeys isn't
|
||||
* supported on SQL Server with JDBC batch).
|
||||
*/
|
||||
private PersistBatch persistBatchOnCascade = PersistBatch.NONE;
|
||||
private PersistBatch persistBatchOnCascade = PersistBatch.INHERIT;
|
||||
|
||||
private int persistBatchSize = 20;
|
||||
|
||||
@@ -307,7 +320,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Setting to indicate if UUID should be stored as binary(16) or varchar(40) or native DB type (for H2 and Postgres).
|
||||
*/
|
||||
private DbUuid dbUuid = DbUuid.AUTO;
|
||||
private DbUuid dbUuid = DbUuid.AUTO_VARCHAR;
|
||||
|
||||
|
||||
private List<IdGenerator> idGenerators = new ArrayList<IdGenerator>();
|
||||
@@ -719,6 +732,34 @@ public class ServerConfig {
|
||||
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default JDBC fetchSize hint for findList queries.
|
||||
*/
|
||||
public int getJdbcFetchSizeFindList() {
|
||||
return jdbcFetchSizeFindList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default JDBC fetchSize hint for findList queries.
|
||||
*/
|
||||
public void setJdbcFetchSizeFindList(int jdbcFetchSizeFindList) {
|
||||
this.jdbcFetchSizeFindList = jdbcFetchSizeFindList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default JDBC fetchSize hint for findEach/findEachWhile queries.
|
||||
*/
|
||||
public int getJdbcFetchSizeFindEach() {
|
||||
return jdbcFetchSizeFindEach;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default JDBC fetchSize hint for findEach/findEachWhile queries.
|
||||
*/
|
||||
public void setJdbcFetchSizeFindEach(int jdbcFetchSizeFindEach) {
|
||||
this.jdbcFetchSizeFindEach = jdbcFetchSizeFindEach;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ChangeLogPrepare.
|
||||
* <p>
|
||||
@@ -2405,6 +2446,8 @@ public class ServerConfig {
|
||||
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
|
||||
historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
|
||||
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
@@ -2460,7 +2503,7 @@ public class ServerConfig {
|
||||
String[] split = classNames.split("[ ,;]");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String cn = split[i].trim();
|
||||
if (cn.length() > 0 && !"class".equalsIgnoreCase(cn)) {
|
||||
if (!cn.isEmpty() && !"class".equalsIgnoreCase(cn)) {
|
||||
try {
|
||||
classes.add(Class.forName(cn));
|
||||
} catch (ClassNotFoundException e) {
|
||||
@@ -2489,13 +2532,14 @@ public class ServerConfig {
|
||||
/**
|
||||
* Return the PersistBatch mode to use for 'batchOnCascade' taking into account if the database
|
||||
* platform supports getGeneratedKeys in batch mode.
|
||||
* <p>
|
||||
* Used to effectively turn off batchOnCascade for SQL Server - still allows explicit batch mode.
|
||||
* </p>
|
||||
*/
|
||||
public PersistBatch appliedPersistBatchOnCascade() {
|
||||
|
||||
return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
|
||||
if (persistBatchOnCascade == PersistBatch.INHERIT) {
|
||||
// use the platform default (ALL except SQL Server which has NONE)
|
||||
return databasePlatform.getPersistBatchOnCascade();
|
||||
}
|
||||
return persistBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2571,18 +2615,45 @@ public class ServerConfig {
|
||||
public enum DbUuid {
|
||||
|
||||
/**
|
||||
* Store using native UUID in H2 and Postgres.
|
||||
* Store using native UUID in H2 and Postgres and otherwise fallback to VARCHAR(40).
|
||||
*/
|
||||
AUTO,
|
||||
AUTO_VARCHAR(true, false),
|
||||
|
||||
/**
|
||||
* Store using DB VARCHAR.
|
||||
* Store using native UUID in H2 and Postgres and otherwise fallback to BINARY(16).
|
||||
*/
|
||||
VARCHAR,
|
||||
AUTO_BINARY(true, true),
|
||||
|
||||
/**
|
||||
* Store using DB BINARY.
|
||||
* Store using DB VARCHAR(40).
|
||||
*/
|
||||
BINARY
|
||||
VARCHAR(false, false),
|
||||
|
||||
/**
|
||||
* Store using DB BINARY(16).
|
||||
*/
|
||||
BINARY(false, true);
|
||||
|
||||
boolean nativeType;
|
||||
boolean binary;
|
||||
|
||||
DbUuid(boolean nativeType, boolean binary) {
|
||||
this.nativeType = nativeType;
|
||||
this.binary = binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if native UUID type is preferred.
|
||||
*/
|
||||
public boolean useNativeType() {
|
||||
return nativeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if BINARY(16) storage is preferred over VARCHAR(40).
|
||||
*/
|
||||
public boolean useBinary() {
|
||||
return binary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,6 @@ public final class TableName {
|
||||
* @return true, if is valid
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return name != null && name.length() > 0;
|
||||
return name != null && !name.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
|
||||
@@ -155,11 +156,9 @@ public class DatabasePlatform {
|
||||
protected boolean forwardOnlyHintOnFindIterate;
|
||||
|
||||
/**
|
||||
* Flag set for SQL Server due to lack of support of getGeneratedKeys in
|
||||
* batch mode (meaning for batch inserts you should explicitly turn off
|
||||
* getGeneratedKeys - joy).
|
||||
* By default we use JDBC batch when cascading (except for SQL Server).
|
||||
*/
|
||||
protected boolean disallowBatchOnCascade;
|
||||
protected PersistBatch persistBatchOnCascade = PersistBatch.ALL;
|
||||
|
||||
protected PlatformDdl platformDdl;
|
||||
|
||||
@@ -183,8 +182,11 @@ public class DatabasePlatform {
|
||||
public DatabasePlatform() {
|
||||
}
|
||||
|
||||
public void configure(Properties properties) {
|
||||
// by default do nothing
|
||||
/**
|
||||
* Configure UUID Storage etc based on ServerConfig settings.
|
||||
*/
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
dbTypeMap.config(nativeUuidType, serverConfig.getDbUuid());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -492,7 +494,7 @@ public class DatabasePlatform {
|
||||
*/
|
||||
public String convertQuotedIdentifiers(String dbName) {
|
||||
// Ignore null values e.g. schema name or catalog
|
||||
if (dbName != null && dbName.length() > 0) {
|
||||
if (dbName != null && !dbName.isEmpty()) {
|
||||
if (dbName.charAt(0) == BACK_TICK) {
|
||||
if (dbName.charAt(dbName.length() - 1) == BACK_TICK) {
|
||||
|
||||
@@ -542,14 +544,10 @@ public class DatabasePlatform {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the persistBatchOnCascade setting should be ignored.
|
||||
* <p>
|
||||
* This is primarily for SQL Server which does not support getGeneratedKeys with jdbc batch mode
|
||||
* so can't really be transparently used.
|
||||
* </p>
|
||||
* Return the platform default JDBC batch mode for persist cascade.
|
||||
*/
|
||||
public boolean isDisallowBatchOnCascade() {
|
||||
return disallowBatchOnCascade;
|
||||
public PersistBatch getPersistBatchOnCascade() {
|
||||
return persistBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,11 +6,13 @@ package com.avaje.ebean.config.dbplatform;
|
||||
public interface DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return true if the 'As of' predicate is part of the from clause
|
||||
* (more standard sql2011). So true for Oracle total recall and false
|
||||
* for Postgres and MySql (where we use views and history tables).
|
||||
* Return true if the implementation is SQL2011 standards based.
|
||||
* <p>
|
||||
* Non standards based means we need to add additional predicates into the
|
||||
* JOIN ON clause and add an additional predicate for the base table.
|
||||
* </p>
|
||||
*/
|
||||
boolean isBindWithFromClause();
|
||||
boolean isStandardsBased();
|
||||
|
||||
/**
|
||||
* Return the number of columns bound in a 'As Of' predicate.
|
||||
|
||||
@@ -5,11 +5,8 @@ package com.avaje.ebean.config.dbplatform;
|
||||
*/
|
||||
public abstract class DbStandardHistorySupport implements DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return true as with sql2011 the 'as of timestamp' clause included in from or join clause.
|
||||
*/
|
||||
@Override
|
||||
public boolean isBindWithFromClause() {
|
||||
public boolean isStandardsBased() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,4 +152,10 @@ public class DbType {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the type with a new default length.
|
||||
*/
|
||||
public DbType withLength(int defaultLength) {
|
||||
return new DbType(name, defaultLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -9,6 +11,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class DbTypeMap {
|
||||
|
||||
private static final DbType UUID_NATIVE = new DbType("uuid", false);
|
||||
private static final DbType UUID_PLACEHOLDER = new DbType("uuidPlaceholder");
|
||||
private static final DbType JSON_CLOB_PLACEHOLDER = new DbType("jsonClobPlaceholder");
|
||||
private static final DbType JSON_BLOB_PLACEHOLDER = new DbType("jsonBlobPlaceholder");
|
||||
private static final DbType JSON_VARCHAR_PLACEHOLDER = new DbType("jsonVarcharPlaceholder");
|
||||
@@ -66,7 +70,7 @@ public class DbTypeMap {
|
||||
|
||||
/**
|
||||
* Return the DbTypeMap with standard (not platform specific) types.
|
||||
*
|
||||
* <p>
|
||||
* This has some extended JSON types (JSON, JSONB, JSONVarchar, JSONClob, JSONBlob).
|
||||
* These types get translated to specific database platform types during DDL generation.
|
||||
*/
|
||||
@@ -104,8 +108,6 @@ public class DbTypeMap {
|
||||
put(Types.BLOB, new DbType("blob"));
|
||||
put(Types.CLOB, new DbType("clob"));
|
||||
|
||||
// DB native UUID support (H2 and Postgres)
|
||||
put(DbType.UUID, new DbType("uuid"));
|
||||
put(Types.ARRAY, new DbType("array"));
|
||||
|
||||
if (logicalTypes) {
|
||||
@@ -116,6 +118,7 @@ public class DbTypeMap {
|
||||
put(DbType.JSONClob, new DbType("jsonclob"));
|
||||
put(DbType.JSONBlob, new DbType("jsonblob"));
|
||||
put(DbType.JSONVarchar, new DbType("jsonvarchar", 1000));
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
|
||||
} else {
|
||||
put(DbType.JSON, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSON
|
||||
@@ -123,6 +126,7 @@ public class DbTypeMap {
|
||||
put(DbType.JSONClob, JSON_CLOB_PLACEHOLDER);
|
||||
put(DbType.JSONBlob, JSON_BLOB_PLACEHOLDER);
|
||||
put(DbType.JSONVarchar, JSON_VARCHAR_PLACEHOLDER);
|
||||
put(DbType.UUID, UUID_PLACEHOLDER);
|
||||
}
|
||||
|
||||
put(Types.LONGVARBINARY, new DbType("longvarbinary"));
|
||||
@@ -133,7 +137,6 @@ public class DbTypeMap {
|
||||
put(Types.DATE, new DbType("date"));
|
||||
put(Types.TIME, new DbType("time"));
|
||||
put(Types.TIMESTAMP, new DbType("timestamp"));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,4 +194,17 @@ public class DbTypeMap {
|
||||
public DbType get(int jdbcType) {
|
||||
return typeMap.get(jdbcType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the UUID appropriately based on native DB support and ServerConfig.DbUuid.
|
||||
*/
|
||||
public void config(boolean nativeUuidType, ServerConfig.DbUuid dbUuid) {
|
||||
if (nativeUuidType && dbUuid.useNativeType()) {
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
} else if (dbUuid.useBinary()) {
|
||||
put(DbType.UUID, get(Types.BINARY).withLength(16));
|
||||
} else {
|
||||
put(DbType.UUID, get(Types.VARCHAR).withLength(40));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,8 @@ package com.avaje.ebean.config.dbplatform;
|
||||
*/
|
||||
public abstract class DbViewHistorySupport implements DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return false for view based implementations where we append extra 'as of' predicates to the end.
|
||||
*/
|
||||
@Override
|
||||
public boolean isBindWithFromClause() {
|
||||
public boolean isStandardsBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* H2 database trigger used to populate history tables to support the @History feature.
|
||||
@@ -54,7 +52,6 @@ public class H2HistoryTrigger implements Trigger {
|
||||
insertSql.append("insert into ").append(tableName).append(HISTORY_SUFFIX).append(" (");
|
||||
|
||||
int count = 0;
|
||||
List<String> columns = new ArrayList<String>();
|
||||
while (rs.next()) {
|
||||
if (++count > 1) {
|
||||
insertSql.append(",");
|
||||
@@ -66,7 +63,6 @@ public class H2HistoryTrigger implements Trigger {
|
||||
this.effectEndPosition = count - 1;
|
||||
}
|
||||
insertSql.append(columnName);
|
||||
columns.add(columnName);
|
||||
}
|
||||
insertSql.append(") values (");
|
||||
for (int i = 0; i < count; i++) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.H2Ddl;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* H2 specific platform.
|
||||
@@ -19,9 +21,7 @@ public class H2Platform extends DatabasePlatform {
|
||||
this.nativeUuidType = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
|
||||
// only support getGeneratedKeys with non-batch JDBC
|
||||
// so generally use SEQUENCE instead of IDENTITY for H2
|
||||
this.dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
@@ -34,6 +34,18 @@ public class H2Platform extends DatabasePlatform {
|
||||
// so no changes to dbTypeMap required
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
super.configure(serverConfig);
|
||||
Properties properties = serverConfig.getProperties();
|
||||
if (properties != null) {
|
||||
String idType = properties.getProperty("ebean.h2.idtype");
|
||||
if (idType != null) {
|
||||
this.dbIdentity.setIdType(IdType.valueOf(idType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a H2 specific sequence IdGenerator that supports batch fetching
|
||||
* sequence values.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
@@ -18,6 +20,7 @@ public class MsSqlServer2000Platform extends DatabasePlatform {
|
||||
public MsSqlServer2000Platform() {
|
||||
super();
|
||||
this.name = "mssqlserver2000";
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
this.dbIdentity.setSelectLastInsertedIdTemplate("select @@IDENTITY as X");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.MsSqlServerDdl;
|
||||
|
||||
import java.sql.Types;
|
||||
@@ -21,7 +22,7 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
|
||||
this.name = "mssqlserver2005";
|
||||
// effectively disable persistBatchOnCascade mode for SQL Server
|
||||
// due to lack of support for getGeneratedKeys in batch mode
|
||||
this.disallowBatchOnCascade = true;
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.idInExpandedForm = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.sqlLimiter = new MsSqlServer2005SqlLimiter();
|
||||
|
||||
@@ -64,12 +64,15 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(Properties properties) {
|
||||
super.configure(properties);
|
||||
String tsType = properties.getProperty("ebean.postgres.timestamp");
|
||||
if (tsType != null) {
|
||||
// set timestamp type to "timestamp" without time zone
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType(tsType));
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
super.configure(serverConfig);
|
||||
Properties properties = serverConfig.getProperties();
|
||||
if (properties != null) {
|
||||
String tsType = properties.getProperty("ebean.postgres.timestamp");
|
||||
if (tsType != null) {
|
||||
// set timestamp type to "timestamp" without time zone
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType(tsType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -164,9 +164,6 @@ public class DbMigration {
|
||||
* </p>
|
||||
*/
|
||||
public void addPlatform(DbPlatformName platform, String prefix) {
|
||||
if (!prefix.endsWith("-")) {
|
||||
prefix += "-";
|
||||
}
|
||||
platforms.add(new Pair(getPlatform(platform), prefix));
|
||||
}
|
||||
|
||||
@@ -204,13 +201,20 @@ public class DbMigration {
|
||||
|
||||
// use this flag to stop other plugins like full DDL generation
|
||||
if (!online) {
|
||||
DbOffline.setRunningMigration();
|
||||
DbOffline.setGenerateMigration();
|
||||
if (databasePlatform == null || !platforms.isEmpty()) {
|
||||
// for multiple platform generation set the general platform
|
||||
// to H2 so that it runs offline without DB connection
|
||||
setPlatform(DbPlatformName.H2);
|
||||
}
|
||||
}
|
||||
setDefaults();
|
||||
try {
|
||||
Request request = createRequest();
|
||||
|
||||
generateExtraDdl(request);
|
||||
if (platforms.isEmpty()) {
|
||||
generateExtraDdl(request.migrationDir, databasePlatform);
|
||||
}
|
||||
|
||||
String pendingVersion = generatePendingDrop();
|
||||
if (pendingVersion != null) {
|
||||
@@ -234,15 +238,15 @@ public class DbMigration {
|
||||
* migration runner.
|
||||
* </p>
|
||||
*/
|
||||
private void generateExtraDdl(Request request) throws IOException {
|
||||
private void generateExtraDdl(File migrationDir, DatabasePlatform dbPlatform) throws IOException {
|
||||
|
||||
if (databasePlatform != null) {
|
||||
if (dbPlatform != null) {
|
||||
ExtraDdl extraDdl = ExtraDdlXmlReader.read("/extra-ddl.xml");
|
||||
if (extraDdl != null) {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (ExtraDdlXmlReader.matchPlatform(databasePlatform.getName(), script.getPlatforms())) {
|
||||
writeExtraDdl(request, script);
|
||||
if (ExtraDdlXmlReader.matchPlatform(dbPlatform.getName(), script.getPlatforms())) {
|
||||
writeExtraDdl(migrationDir, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,13 +256,13 @@ public class DbMigration {
|
||||
/**
|
||||
* Write (or override) the "repeatable" migration script.
|
||||
*/
|
||||
private void writeExtraDdl(Request request, DdlScript script) throws IOException {
|
||||
private void writeExtraDdl(File migrationDir, DdlScript script) throws IOException {
|
||||
|
||||
String fullName = repeatableMigrationName(script.getName());
|
||||
|
||||
logger.info("writing repeatable script {}", fullName);
|
||||
|
||||
File file = new File(request.migrationDir, fullName);
|
||||
File file = new File(migrationDir, fullName);
|
||||
FileWriter writer = new FileWriter(file);
|
||||
writer.write(script.getValue());
|
||||
writer.flush();
|
||||
@@ -363,14 +367,16 @@ public class DbMigration {
|
||||
logger.warn("migration already exists, not generating DDL");
|
||||
|
||||
} else {
|
||||
if (databasePlatform != null) {
|
||||
if (!platforms.isEmpty()) {
|
||||
writeExtraPlatformDdl(fullVersion, request.currentModel, dbMigration, request.migrationDir);
|
||||
|
||||
} else if (databasePlatform != null) {
|
||||
// writer needs the current model to provide table/column details for
|
||||
// history ddl generation (triggers, history tables etc)
|
||||
DdlWrite write = new DdlWrite(new MConfiguration(), request.current);
|
||||
PlatformDdlWriter writer = createDdlWriter(databasePlatform, "");
|
||||
writer.processMigration(dbMigration, write, request.migrationDir, fullVersion);
|
||||
}
|
||||
writeExtraPlatformDdl(fullVersion, request.currentModel, dbMigration, request.migrationDir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +432,10 @@ public class DbMigration {
|
||||
for (Pair pair : platforms) {
|
||||
DdlWrite platformBuffer = new DdlWrite(new MConfiguration(), currentModel.read());
|
||||
PlatformDdlWriter platformWriter = createDdlWriter(pair);
|
||||
platformWriter.processMigration(dbMigration, platformBuffer, writePath, fullVersion);
|
||||
File subPath = platformWriter.subPath(writePath, pair.prefix);
|
||||
platformWriter.processMigration(dbMigration, platformBuffer, subPath, fullVersion);
|
||||
|
||||
generateExtraDdl(subPath, pair.platform);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ public class DbOffline {
|
||||
|
||||
private static final String KEY = "ebean.dboffline";
|
||||
|
||||
private static boolean runningMigration;
|
||||
private static boolean generateMigration;
|
||||
|
||||
/**
|
||||
* Set the platform to use when creating the next EbeanServer instance.
|
||||
@@ -55,23 +55,23 @@ public class DbOffline {
|
||||
* Return true if the migration is running. This typically means don't run the
|
||||
* plugins like full DDL generation.
|
||||
*/
|
||||
public static boolean isRunningMigration() {
|
||||
return runningMigration;
|
||||
public static boolean isGenerateMigration() {
|
||||
return generateMigration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the migration is running is order to stop other plugins
|
||||
* like the full DDL generation from executing.
|
||||
*/
|
||||
public static void setRunningMigration() {
|
||||
runningMigration = true;
|
||||
public static void setGenerateMigration() {
|
||||
generateMigration = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the offline platform and runningMigration flag.
|
||||
*/
|
||||
public static void reset() {
|
||||
runningMigration = false;
|
||||
generateMigration = false;
|
||||
System.clearProperty(KEY);
|
||||
logger.debug("reset");
|
||||
}
|
||||
|
||||
@@ -831,9 +831,10 @@ public class BaseTableDdl implements TableDdl {
|
||||
|
||||
protected void alterTableAddColumn(DdlBuffer buffer, String tableName, Column column, boolean onHistoryTable) throws IOException {
|
||||
|
||||
String convertedType = platformDdl.convert(column.getType(), false);
|
||||
buffer.append("alter table ").append(tableName)
|
||||
.append(" add column ").append(column.getName())
|
||||
.append(" ").append(column.getType());
|
||||
.append(" ").append(convertedType);
|
||||
|
||||
if (!onHistoryTable) {
|
||||
if (isTrue(column.isNotnull())) {
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.util.List;
|
||||
*/
|
||||
public class PlatformDdl {
|
||||
|
||||
protected final DatabasePlatform platform;
|
||||
|
||||
protected PlatformHistoryDdl historyDdl = new NoHistorySupportDdl();
|
||||
|
||||
/**
|
||||
@@ -98,6 +100,7 @@ public class PlatformDdl {
|
||||
protected final DbDefaultValue dbDefaultValue;
|
||||
|
||||
public PlatformDdl(DatabasePlatform platform) {
|
||||
this.platform = platform;
|
||||
this.dbIdentity = platform.getDbIdentity();
|
||||
this.dbDefaultValue = platform.getDbDefaultValue();
|
||||
this.typeConverter = new PlatformTypeConverter(platform.getDbTypeMap());
|
||||
@@ -107,6 +110,7 @@ public class PlatformDdl {
|
||||
* Set configuration options.
|
||||
*/
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
platform.configure(serverConfig);
|
||||
historyDdl.configure(serverConfig, this);
|
||||
naming = serverConfig.getConstraintNaming();
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import com.avaje.ebean.dbmigration.model.visitor.VisitAllUsing;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Reads EbeanServer bean descriptors to build the current model.
|
||||
@@ -24,6 +23,8 @@ public class CurrentModel {
|
||||
|
||||
private final DbConstraintNaming.MaxLength maxLength;
|
||||
|
||||
private final boolean platformTypes;
|
||||
|
||||
private ModelContainer model;
|
||||
|
||||
private ChangeSet changeSet;
|
||||
@@ -31,32 +32,31 @@ public class CurrentModel {
|
||||
private DdlWrite write;
|
||||
|
||||
/**
|
||||
* Construct with a given EbeanServer instance.
|
||||
* Construct with a given EbeanServer instance for DDL create all generation, not migration.
|
||||
*/
|
||||
public CurrentModel(SpiEbeanServer server) {
|
||||
this(server, server.getServerConfig().getConstraintNaming());
|
||||
this(server, server.getServerConfig().getConstraintNaming(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with a given EbeanServer, platformDdl and constraintNaming convention.
|
||||
* <p>
|
||||
* Note the EbeanServer is just used to read the BeanDescriptors and platformDdl supplies
|
||||
* the platform specific handling on
|
||||
* Note the EbeanServer is just used to read the BeanDescriptors and platformDdl supplies
|
||||
* the platform specific handling on
|
||||
* </p>
|
||||
*/
|
||||
public CurrentModel(SpiEbeanServer server, DbConstraintNaming constraintNaming) {
|
||||
this(server, constraintNaming, false);
|
||||
}
|
||||
|
||||
private CurrentModel(SpiEbeanServer server, DbConstraintNaming constraintNaming, boolean platformTypes) {
|
||||
this.server = server;
|
||||
this.constraintNaming = constraintNaming;
|
||||
this.maxLength = maxLength(server, constraintNaming);
|
||||
this.platformTypes = platformTypes;
|
||||
}
|
||||
|
||||
public CurrentModel(SpiEbeanServer server, DbConstraintNaming constraintNaming, int maxConstraintLength) {
|
||||
this.server = server;
|
||||
this.constraintNaming = constraintNaming;
|
||||
this.maxLength = new DefaultConstraintMaxLength(maxConstraintLength);
|
||||
}
|
||||
|
||||
private DbConstraintNaming.MaxLength maxLength(SpiEbeanServer server, DbConstraintNaming naming) {
|
||||
private static DbConstraintNaming.MaxLength maxLength(SpiEbeanServer server, DbConstraintNaming naming) {
|
||||
|
||||
if (naming.getMaxLength() != null) {
|
||||
return naming.getMaxLength();
|
||||
@@ -73,7 +73,7 @@ public class CurrentModel {
|
||||
if (model == null) {
|
||||
model = new ModelContainer();
|
||||
|
||||
ModelBuildContext context = new ModelBuildContext(model, constraintNaming, maxLength);
|
||||
ModelBuildContext context = new ModelBuildContext(model, constraintNaming, maxLength, platformTypes);
|
||||
ModelBuildBeanVisitor visitor = new ModelBuildBeanVisitor(context);
|
||||
VisitAllUsing visit = new VisitAllUsing(visitor, server);
|
||||
visit.visitAllBeans();
|
||||
|
||||
@@ -104,7 +104,7 @@ public class MTable {
|
||||
/**
|
||||
* Compound unique constraints.
|
||||
*/
|
||||
private List<MCompoundUniqueConstraint> compoundUniqueConstraints = new ArrayList<MCompoundUniqueConstraint>();
|
||||
private List<MCompoundUniqueConstraint> uniqueConstraints = new ArrayList<MCompoundUniqueConstraint>();
|
||||
|
||||
/**
|
||||
* Compound foreign keys.
|
||||
@@ -216,7 +216,7 @@ public class MTable {
|
||||
createTable.getForeignKey().add(compoundKey.createForeignKey());
|
||||
}
|
||||
|
||||
for (MCompoundUniqueConstraint constraint : compoundUniqueConstraints) {
|
||||
for (MCompoundUniqueConstraint constraint : uniqueConstraints) {
|
||||
UniqueConstraint uq = new UniqueConstraint();
|
||||
uq.setName(constraint.getName());
|
||||
String[] columns = constraint.getColumns();
|
||||
@@ -404,8 +404,8 @@ public class MTable {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public List<MCompoundUniqueConstraint> getCompoundUniqueConstraints() {
|
||||
return compoundUniqueConstraints;
|
||||
public List<MCompoundUniqueConstraint> getUniqueConstraints() {
|
||||
return uniqueConstraints;
|
||||
}
|
||||
|
||||
public List<MCompoundForeignKey> getCompoundKeys() {
|
||||
@@ -476,21 +476,21 @@ public class MTable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
* Add a unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(String[] columns, boolean oneToOne, String constraintName) {
|
||||
compoundUniqueConstraints.add(new MCompoundUniqueConstraint(columns, oneToOne, constraintName));
|
||||
public void addUniqueConstraint(String[] columns, boolean oneToOne, String constraintName) {
|
||||
uniqueConstraints.add(new MCompoundUniqueConstraint(columns, oneToOne, constraintName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
* Add a unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(List<MColumn> columns, boolean oneToOne, String constraintName) {
|
||||
public void addUniqueConstraint(List<MColumn> columns, boolean oneToOne, String constraintName) {
|
||||
String[] cols = new String[columns.size()];
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
cols[i] = columns.get(i).getName();
|
||||
}
|
||||
addCompoundUniqueConstraint(cols, oneToOne, constraintName);
|
||||
addUniqueConstraint(cols, oneToOne, constraintName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,6 +9,8 @@ import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite;
|
||||
import com.avaje.ebean.dbmigration.migration.ChangeSet;
|
||||
import com.avaje.ebean.dbmigration.migration.ChangeSetType;
|
||||
import com.avaje.ebean.dbmigration.migration.Migration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
@@ -21,6 +23,8 @@ import java.util.List;
|
||||
*/
|
||||
public class PlatformDdlWriter {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PlatformDdlWriter.class);
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
|
||||
private final DatabasePlatform platform;
|
||||
@@ -67,7 +71,7 @@ public class PlatformDdlWriter {
|
||||
protected void writePlatformDdl(DdlWrite write, File resourcePath, String fullVersion) throws IOException {
|
||||
|
||||
if (!write.isApplyEmpty()) {
|
||||
FileWriter applyWriter = createWriter(resourcePath, fullVersion, "", config.getApplySuffix());
|
||||
FileWriter applyWriter = createWriter(resourcePath, fullVersion, config.getApplySuffix());
|
||||
try {
|
||||
writeApplyDdl(applyWriter, write);
|
||||
applyWriter.flush();
|
||||
@@ -77,28 +81,12 @@ public class PlatformDdlWriter {
|
||||
}
|
||||
}
|
||||
|
||||
protected FileWriter createWriter(File path, String fullVersion, String subPath, String suffix) throws IOException {
|
||||
protected FileWriter createWriter(File path, String fullVersion, String suffix) throws IOException {
|
||||
|
||||
String fileName = fullVersion;
|
||||
if (!platformPrefix.isEmpty()) {
|
||||
fileName += "-"+platformPrefix;
|
||||
}
|
||||
if (subPath != null && !subPath.isEmpty()) {
|
||||
path = subPath(path, subPath);
|
||||
}
|
||||
fileName += suffix;
|
||||
File applyFile = new File(path, fileName);
|
||||
File applyFile = new File(path, fullVersion + suffix);
|
||||
return new FileWriter(applyFile);
|
||||
}
|
||||
|
||||
protected File subPath(File path, String suffix) {
|
||||
File subPath = new File(path, suffix);
|
||||
if (!subPath.exists()) {
|
||||
subPath.mkdirs();
|
||||
}
|
||||
return subPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the 'Apply' DDL buffers to the writer.
|
||||
*/
|
||||
@@ -127,4 +115,17 @@ public class PlatformDdlWriter {
|
||||
return platform.createDdlHandler(serverConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a sub directory (for multi-platform ddl generation).
|
||||
*/
|
||||
public File subPath(File path, String suffix) {
|
||||
File subPath = new File(path, suffix);
|
||||
if (!subPath.exists()) {
|
||||
if (!subPath.mkdirs()) {
|
||||
logger.error("failed to create directories for " + subPath.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
return subPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,10 +29,13 @@ public class ModelBuildContext {
|
||||
|
||||
private final DbConstraintNaming.MaxLength maxLength;
|
||||
|
||||
public ModelBuildContext(ModelContainer model, DbConstraintNaming naming, DbConstraintNaming.MaxLength maxLength) {
|
||||
private final boolean platformTypes;
|
||||
|
||||
public ModelBuildContext(ModelContainer model, DbConstraintNaming naming, DbConstraintNaming.MaxLength maxLength, boolean platformTypes) {
|
||||
this.model = model;
|
||||
this.constraintNaming = naming;
|
||||
this.maxLength = maxLength;
|
||||
this.platformTypes = platformTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,7 +135,7 @@ public class ModelBuildContext {
|
||||
}
|
||||
|
||||
// can be the logical JSON types (JSON, JSONB, JSONClob, JSONBlob, JSONVarchar)
|
||||
int dbType = p.getDbType();
|
||||
int dbType = p.getDbType(platformTypes);
|
||||
if (dbType == 0) {
|
||||
throw new RuntimeException("No scalarType defined for " + p.getFullBeanName());
|
||||
}
|
||||
|
||||
@@ -85,6 +85,11 @@ public class ModelBuildIntersectionTable {
|
||||
|
||||
String tableName = intersectionTableJoin.getTable();
|
||||
MTable table = new MTable(tableName);
|
||||
if (!manyProp.isExcludedFromHistory()) {
|
||||
if (localDesc.isHistorySupport()) {
|
||||
table.setWithHistory(true);
|
||||
}
|
||||
}
|
||||
table.setPkName(ctx.primaryKeyName(tableName));
|
||||
|
||||
TableJoinColumn[] columns = intersectionTableJoin.columns();
|
||||
|
||||
+12
-21
@@ -10,7 +10,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
@@ -45,30 +45,30 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
this.ctx = ctx;
|
||||
this.table = table;
|
||||
this.beanDescriptor = beanDescriptor;
|
||||
addCompoundUniqueConstraint(beanDescriptor.getCompoundUniqueConstraints());
|
||||
addIndexes(beanDescriptor.getIndexDefinitions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add unique constraints defined via JPA UniqueConstraint annotations.
|
||||
*/
|
||||
private void addCompoundUniqueConstraint(CompoundUniqueConstraint[] constraints) {
|
||||
private void addIndexes(IndexDefinition[] indexes) {
|
||||
|
||||
if (constraints != null) {
|
||||
for (int i = 0; i < constraints.length; i++) {
|
||||
CompoundUniqueConstraint constraint = constraints[i];
|
||||
String[] columns = constraint.getColumns();
|
||||
if (indexes != null) {
|
||||
for (int i = 0; i < indexes.length; i++) {
|
||||
IndexDefinition index = indexes[i];
|
||||
String[] columns = index.getColumns();
|
||||
indexSet.add(columns);
|
||||
|
||||
if (constraint.isUnique()) {
|
||||
String uqName = constraint.getName();
|
||||
if (index.isUnique()) {
|
||||
String uqName = index.getName();
|
||||
if (uqName == null || uqName.trim().isEmpty()) {
|
||||
uqName = determineUniqueConstraintName(columns);
|
||||
}
|
||||
table.addCompoundUniqueConstraint(columns, false, uqName);
|
||||
table.addUniqueConstraint(columns, false, uqName);
|
||||
|
||||
} else {
|
||||
// 'just' an index (not a unique constraint)
|
||||
String idxName = constraint.getName();
|
||||
String idxName = index.getName();
|
||||
if (idxName == null || idxName.trim().isEmpty()) {
|
||||
idxName = determineIndexName(columns);
|
||||
}
|
||||
@@ -216,7 +216,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
} else {
|
||||
String uqName = determineUniqueConstraintName(p.getName());
|
||||
table.addCompoundUniqueConstraint(modelColumns, true, uqName);
|
||||
table.addUniqueConstraint(modelColumns, true, uqName);
|
||||
indexSetAdd(modelColumns);
|
||||
}
|
||||
}
|
||||
@@ -260,15 +260,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setCheckConstraintName(determineCheckConstraintName(col.getName()));
|
||||
}
|
||||
|
||||
String indexName = p.getIndexName();
|
||||
if (indexName != null) {
|
||||
// single column non-unique index
|
||||
if (indexName.trim().isEmpty()) {
|
||||
indexName = determineIndexName(col.getName());
|
||||
}
|
||||
ctx.addIndex(indexName, table.getName(), p.getDbColumn());
|
||||
}
|
||||
|
||||
lastColumn = col;
|
||||
table.addColumn(col);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class PathProperties implements FetchPath {
|
||||
String path = entry.getKey();
|
||||
String props = entry.getValue().getPropertiesAsString();
|
||||
|
||||
if (path == null || path.length() == 0) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
query.select(props);
|
||||
} else {
|
||||
query.fetch(path, props);
|
||||
|
||||
@@ -108,7 +108,7 @@ class PathPropertiesParser {
|
||||
|
||||
private void addCurrentProperty() {
|
||||
String w = currentWord();
|
||||
if (w.length() > 0) {
|
||||
if (!w.isEmpty()) {
|
||||
currentPathProps.addProperty(w);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class TimeStringParser implements StringParser {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object parse(String value) {
|
||||
if (value == null || value.trim().length() == 0) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,12 @@ public class CamelCaseHelper {
|
||||
*/
|
||||
public static String toCamelFromUnderscore(String underscore) {
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
String[] vals = underscore.split("_");
|
||||
if (vals.length == 1) {
|
||||
return underscore;
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < vals.length; i++) {
|
||||
String lower = vals[i].toLowerCase();
|
||||
if (i > 0) {
|
||||
|
||||
@@ -123,7 +123,7 @@ public class StringHelper {
|
||||
String listDelimiter, String nameValueSeparator) {
|
||||
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.length() == 0)) {
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
@@ -155,7 +155,7 @@ public class StringHelper {
|
||||
* Return true if the value is null or an empty string.
|
||||
*/
|
||||
public static boolean isNull(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ public class StringHelper {
|
||||
// there is a key without a value?
|
||||
String key = allNameValuePairs.substring(pos, delimPos);
|
||||
key = key.trim();
|
||||
if (key.length() > 0) {
|
||||
if (!key.isEmpty()) {
|
||||
map.put(key, null);
|
||||
}
|
||||
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
|
||||
@@ -251,7 +251,7 @@ public class StringHelper {
|
||||
if (endPos == -1) {
|
||||
if (startPos <= str.length()) {
|
||||
String lastValue = str.substring(startPos, str.length());
|
||||
if (keepEmpties || lastValue.length() != 0) {
|
||||
if (keepEmpties || !lastValue.isEmpty()) {
|
||||
list.add(lastValue);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +260,7 @@ public class StringHelper {
|
||||
} else {
|
||||
// get the delimited value... add it..
|
||||
String value = str.substring(startPos, endPos);
|
||||
if (keepEmpties || value.length() != 0) {
|
||||
if (keepEmpties || !value.isEmpty()) {
|
||||
list.add(value);
|
||||
}
|
||||
// recursively search as we are not at the end yet...
|
||||
@@ -398,7 +398,7 @@ public class StringHelper {
|
||||
int additionalSize, int startPos, int endPos) {
|
||||
|
||||
if (source == null) {
|
||||
return source;
|
||||
return null;
|
||||
}
|
||||
|
||||
char match0 = match.charAt(0);
|
||||
|
||||
@@ -223,14 +223,14 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
Timestamp getAsOf();
|
||||
|
||||
/**
|
||||
* Add a table alias for a @History entity involved in a 'As Of' query.
|
||||
* Increment the counter of tables used in 'As Of' query.
|
||||
*/
|
||||
void addAsOfTableAlias(String tableAlias);
|
||||
void incrementAsOfTableCount();
|
||||
|
||||
/**
|
||||
* Return the list of table alias involved in a 'As Of' query that have @History support.
|
||||
* Return the table alias used for the base table.
|
||||
*/
|
||||
List<String> getAsOfTableAlias();
|
||||
int getAsOfTableCount();
|
||||
|
||||
void addSoftDeletePredicate(String softDeletePredicate);
|
||||
|
||||
@@ -564,6 +564,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
boolean tuneFetchProperties(OrmQueryDetail detail);
|
||||
|
||||
/**
|
||||
* If this is a RawSql based entity set the default RawSql if not set.
|
||||
*/
|
||||
void setDefaultRawSqlIfRequired();
|
||||
|
||||
/**
|
||||
* Set to true if this query has been tuned by autoTune.
|
||||
*/
|
||||
@@ -625,6 +630,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
void setGeneratedSql(String generatedSql);
|
||||
|
||||
/**
|
||||
* Set the JDBC fetchSize buffer hint if not explicitly set.
|
||||
*/
|
||||
void setDefaultFetchBuffer(int fetchSize);
|
||||
|
||||
/**
|
||||
* Return the hint for Statement.setFetchSize().
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ExtraDdlXmlReader {
|
||||
* @param platforms The platforms (comma delimited) this script should run for
|
||||
*/
|
||||
public static boolean matchPlatform(String platformName, String platforms) {
|
||||
if (platforms == null || platforms.trim().length() == 0) {
|
||||
if (platforms == null || platforms.trim().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
String[] names = platforms.split("[,;]");
|
||||
|
||||
+1
-2
@@ -45,9 +45,8 @@ public class ProfileOriginNodeUsage {
|
||||
if (path != null) {
|
||||
ElPropertyValue elGetValue = rootDesc.getElGetValue(path);
|
||||
if (elGetValue == null) {
|
||||
desc = null;
|
||||
logger.warn("AutoTune: Can't find join for path[" + path + "] for " + rootDesc.getName());
|
||||
|
||||
return;
|
||||
} else {
|
||||
BeanProperty beanProperty = elGetValue.getBeanProperty();
|
||||
if (beanProperty instanceof BeanPropertyAssoc<?>) {
|
||||
|
||||
@@ -14,14 +14,14 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefaultBeanState implements BeanState {
|
||||
|
||||
private final EntityBean entityBean;
|
||||
|
||||
private final EntityBeanIntercept intercept;
|
||||
|
||||
public DefaultBeanState(EntityBean entityBean){
|
||||
this.entityBean = entityBean;
|
||||
this.intercept = entityBean._ebean_getIntercept();
|
||||
}
|
||||
private final EntityBean entityBean;
|
||||
|
||||
private final EntityBeanIntercept intercept;
|
||||
|
||||
public DefaultBeanState(EntityBean entityBean) {
|
||||
this.entityBean = entityBean;
|
||||
this.intercept = entityBean._ebean_getIntercept();
|
||||
}
|
||||
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
intercept.setPropertyLoaded(propertyName, loaded);
|
||||
@@ -31,52 +31,57 @@ public class DefaultBeanState implements BeanState {
|
||||
return intercept.isReference();
|
||||
}
|
||||
|
||||
public boolean isNew() {
|
||||
return intercept.isNew();
|
||||
}
|
||||
|
||||
public boolean isNewOrDirty() {
|
||||
return intercept.isNewOrDirty();
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return intercept.isDirty();
|
||||
}
|
||||
|
||||
public Set<String> getLoadedProps() {
|
||||
return intercept.getLoadedPropertyNames();
|
||||
}
|
||||
|
||||
public Set<String> getChangedProps() {
|
||||
return intercept.getDirtyPropertyNames();
|
||||
public boolean isNew() {
|
||||
return intercept.isNew();
|
||||
}
|
||||
|
||||
public Map<String,ValuePair> getDirtyValues() {
|
||||
|
||||
public boolean isNewOrDirty() {
|
||||
return intercept.isNewOrDirty();
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return intercept.isDirty();
|
||||
}
|
||||
|
||||
public Set<String> getLoadedProps() {
|
||||
return intercept.getLoadedPropertyNames();
|
||||
}
|
||||
|
||||
public Set<String> getChangedProps() {
|
||||
return intercept.getDirtyPropertyNames();
|
||||
}
|
||||
|
||||
public Map<String, ValuePair> getDirtyValues() {
|
||||
return intercept.getDirtyValues();
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return intercept.isReadOnly();
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly){
|
||||
intercept.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
entityBean.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
entityBean.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void setLoaded() {
|
||||
intercept.setLoaded();
|
||||
}
|
||||
public boolean isReadOnly() {
|
||||
return intercept.isReadOnly();
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
intercept.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public void addPropertyChangeListener(PropertyChangeListener listener) {
|
||||
entityBean.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener) {
|
||||
entityBean.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void setLoaded() {
|
||||
intercept.setLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisableLazyLoad(boolean disableLazyLoading) {
|
||||
intercept.setDisableLazyLoad(disableLazyLoading);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableLazyLoad() {
|
||||
return intercept.isDisableLazyLoad();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,22 +122,20 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
// generate and run DDL if required
|
||||
// if there are any other tasks requiring action in their plugins, do them as well
|
||||
if (!DbOffline.isRunningMigration()) {
|
||||
if (!DbOffline.isGenerateMigration()) {
|
||||
server.executePlugins(online);
|
||||
}
|
||||
|
||||
// initialise prior to registering with clusterManager
|
||||
server.initialise();
|
||||
|
||||
if (online) {
|
||||
if (clusterManager.isClustering()) {
|
||||
// register the server once it has been created
|
||||
clusterManager.registerServer(server);
|
||||
// initialise prior to registering with clusterManager
|
||||
server.initialise();
|
||||
if (online) {
|
||||
if (clusterManager.isClustering()) {
|
||||
// register the server once it has been created
|
||||
clusterManager.registerServer(server);
|
||||
}
|
||||
}
|
||||
// start any services after registering with clusterManager
|
||||
server.start();
|
||||
}
|
||||
|
||||
// start any services after registering with clusterManager
|
||||
server.start();
|
||||
DbOffline.reset();
|
||||
return server;
|
||||
}
|
||||
@@ -244,7 +242,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
if (dbPlatform == null) {
|
||||
DatabasePlatformFactory factory = new DatabasePlatformFactory();
|
||||
DatabasePlatform db = factory.create(config);
|
||||
db.configure(config.getProperties());
|
||||
db.configure(config);
|
||||
config.setDatabasePlatform(db);
|
||||
logger.info("DatabasePlatform name:" + config.getName() + " platform:" + db.getName());
|
||||
}
|
||||
|
||||
@@ -557,7 +557,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
InheritInfo inheritInfo = desc.getInheritInfo();
|
||||
if (inheritInfo == null) {
|
||||
return (T)desc.contextRef(pc, null, id);
|
||||
return (T)desc.contextRef(pc, null, false, id);
|
||||
}
|
||||
|
||||
BeanProperty idProp = desc.getIdProperty();
|
||||
@@ -683,6 +683,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (txScope == null) {
|
||||
// create a TxScope with default settings
|
||||
txScope = new TxScope();
|
||||
} else {
|
||||
// check for implied batch mode via setting batchSize
|
||||
txScope.checkBatchMode();
|
||||
}
|
||||
|
||||
SpiTransaction suspended = null;
|
||||
@@ -884,6 +887,21 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return createQuery(beanType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
throw new PersistenceException(beanType.getName() + " is NOT an Entity Bean registered with this server?");
|
||||
}
|
||||
RawSql rawSql = desc.getNamedRawSql(namedQuery);
|
||||
if (rawSql != null) {
|
||||
DefaultOrmQuery<T> query = createQuery(beanType);
|
||||
query.setRawSql(rawSql);
|
||||
return query;
|
||||
}
|
||||
throw new PersistenceException("No named query called " + namedQuery + " for bean:" + beanType.getName());
|
||||
}
|
||||
|
||||
public <T> DefaultOrmQuery<T> createQuery(Class<T> beanType) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
@@ -942,6 +960,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private <T> SpiOrmQueryRequest<T> createQueryRequest(SpiQuery<T> query, Transaction t) {
|
||||
|
||||
query.setDefaultRawSqlIfRequired();
|
||||
if (query.isAutoTunable() && !autoTuneService.tuneQuery(query)) {
|
||||
// use deployment FetchType.LAZY/EAGER annotations
|
||||
// to define the 'default' select clause
|
||||
|
||||
@@ -137,7 +137,7 @@ public class InternalConfiguration {
|
||||
|
||||
this.dataTimeZone = initDataTimeZone();
|
||||
this.binder = getBinder(typeManager, databasePlatform, dataTimeZone);
|
||||
this.cQueryEngine = new CQueryEngine(databasePlatform, binder, asOfTableMapping, serverConfig.getAsOfSysPeriod(), draftTableMap);
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig, databasePlatform, binder, asOfTableMapping, draftTableMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,7 +235,7 @@ public class InternalConfiguration {
|
||||
if (historySupport == null) {
|
||||
return new Binder(typeManager, 0, false, jsonHandler, dataTimeZone);
|
||||
}
|
||||
return new Binder(typeManager, historySupport.getBindCount(), historySupport.isBindWithFromClause(), jsonHandler, dataTimeZone);
|
||||
return new Binder(typeManager, historySupport.getBindCount(), historySupport.isStandardsBased(), jsonHandler, dataTimeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -513,4 +513,18 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
public boolean isAuditReads() {
|
||||
return !query.isDisableReadAudit() && beanDescriptor.isReadAuditing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base table alias for this query.
|
||||
*/
|
||||
public String getBaseTableAlias() {
|
||||
return query.getAlias() == null ? beanDescriptor.getBaseTableAlias() : query.getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC buffer fetchSize hint if not set explicitly.
|
||||
*/
|
||||
public void setDefaultFetchBuffer(int fetchSize) {
|
||||
query.setDefaultFetchBuffer(fetchSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +548,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.createReference(Boolean.FALSE, getBeanId(), null);
|
||||
return beanDescriptor.createReference(Boolean.FALSE, false, getBeanId(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -46,9 +46,11 @@ abstract class AssocOneHelp {
|
||||
return existing;
|
||||
}
|
||||
|
||||
Object ref = target.contextRef(pc, ctx.isReadOnly(), id);
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
ctx.register(property.name, ebi);
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = target.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (!disableLazyLoading) {
|
||||
ctx.register(property.name, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,11 @@ class AssocOneHelpRefInherit extends AssocOneHelp {
|
||||
}
|
||||
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
Object ref = desc.contextRef(pc, ctx.isReadOnly(), id);
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
ctx.register(property.name, ebi);
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = desc.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (disableLazyLoading) {
|
||||
ctx.register(property.name, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,6 +109,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<String, ElComparator<T>>();
|
||||
|
||||
private final Map<String, RawSql> namedRawSql;
|
||||
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
|
||||
EntityBeanIntercept fromEbi = bean._ebean_getIntercept();
|
||||
@@ -176,7 +178,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
*/
|
||||
private final ConcurrencyMode concurrencyMode;
|
||||
|
||||
private final CompoundUniqueConstraint[] compoundUniqueConstraints;
|
||||
private final IndexDefinition[] indexDefinitions;
|
||||
|
||||
private final String[] dependentTables;
|
||||
|
||||
@@ -412,6 +414,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.rootBeanType = PersistenceContextUtil.root(beanType);
|
||||
this.prototypeEntityBean = createPrototypeEntityBean(beanType);
|
||||
|
||||
this.namedRawSql = deploy.getNamedRawSql();
|
||||
this.inheritInfo = deploy.getInheritInfo();
|
||||
|
||||
this.beanFinder = deploy.getBeanFinder();
|
||||
@@ -431,7 +434,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
|
||||
this.concurrencyMode = deploy.getConcurrencyMode();
|
||||
this.updateChangesOnly = deploy.isUpdateChangesOnly();
|
||||
this.compoundUniqueConstraints = deploy.getCompoundUniqueConstraints();
|
||||
this.indexDefinitions = deploy.getIndexDefinitions();
|
||||
|
||||
this.readAuditing = deploy.isReadAuditing();
|
||||
this.draftable = deploy.isDraftable();
|
||||
@@ -443,7 +446,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.baseTableVersionsBetween = deploy.getBaseTableVersionsBetween();
|
||||
this.dependentTables = deploy.getDependentTables();
|
||||
this.dbComment = deploy.getDbComment();
|
||||
this.autoTunable = EntityType.ORM.equals(entityType) && (beanFinder == null);
|
||||
this.autoTunable = EntityType.ORM == entityType && (beanFinder == null);
|
||||
|
||||
// helper object used to derive lists of properties
|
||||
DeployBeanPropertyLists listHelper = new DeployBeanPropertyLists(owner, this, deploy);
|
||||
@@ -985,6 +988,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the named RawSql query.
|
||||
*/
|
||||
public RawSql getNamedRawSql(String named) {
|
||||
return namedRawSql.get(named);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of DocStoreMode that should occur for this type of persist request
|
||||
* given the transactions requested mode.
|
||||
@@ -1559,9 +1569,9 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
* Create a reference bean based on the id.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createReference(Boolean readOnly, Object id, PersistenceContext pc) {
|
||||
public T createReference(Boolean readOnly, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
|
||||
if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) {
|
||||
if (cacheSharableBeans && !disableLazyLoad && !Boolean.FALSE.equals(readOnly)) {
|
||||
CachedBeanData d = cacheHelp.beanCacheGetData(id);
|
||||
if (d != null) {
|
||||
Object shareableBean = d.getSharableBean();
|
||||
@@ -1578,7 +1588,11 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
id = convertSetId(id, eb);
|
||||
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
ebi.setBeanLoader(ebeanServer);
|
||||
if (disableLazyLoad) {
|
||||
ebi.setDisableLazyLoad(true);
|
||||
} else {
|
||||
ebi.setBeanLoader(ebeanServer);
|
||||
}
|
||||
ebi.setReference(idPropertyIndex);
|
||||
if (Boolean.TRUE == readOnly) {
|
||||
ebi.setReadOnly(true);
|
||||
@@ -1750,8 +1764,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
/**
|
||||
* Create a reference bean and put it in the persistence context (and return it).
|
||||
*/
|
||||
public Object contextRef(PersistenceContext pc, Boolean readOnly, Object id) {
|
||||
return createReference(readOnly, id, pc);
|
||||
public Object contextRef(PersistenceContext pc, Boolean readOnly, boolean disableLazyLoad, Object id) {
|
||||
return createReference(readOnly, disableLazyLoad, id, pc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2169,14 +2183,14 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
* Return true if this is an embedded bean.
|
||||
*/
|
||||
public boolean isEmbedded() {
|
||||
return EntityType.EMBEDDED.equals(entityType);
|
||||
return EntityType.EMBEDDED == entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the compound unique constraints.
|
||||
*/
|
||||
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
|
||||
return compoundUniqueConstraints;
|
||||
public IndexDefinition[] getIndexDefinitions() {
|
||||
return indexDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2295,15 +2309,10 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this bean is based on a table (or possibly view) and
|
||||
* returns false if this bean is based on a raw sql select statement.
|
||||
* <p>
|
||||
* When false querying this bean is based on a supplied sql select statement
|
||||
* placed in the orm xml file (as opposed to Ebean generated sql).
|
||||
* </p>
|
||||
* Returns true if this bean is based on RawSql.
|
||||
*/
|
||||
public boolean isSqlSelectBased() {
|
||||
return EntityType.SQL.equals(entityType);
|
||||
public boolean isRawSqlBased() {
|
||||
return EntityType.SQL == entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -266,7 +266,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
bc.checkEmptyLazyLoad();
|
||||
for (int i = 0; i < idList.size(); i++) {
|
||||
Object id = idList.get(i);
|
||||
Object refBean = targetDescriptor.createReference(readOnly, id, persistenceContext);
|
||||
Object refBean = targetDescriptor.createReference(readOnly, false, id, persistenceContext);
|
||||
many.add(bc, (EntityBean) refBean);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Model;
|
||||
import com.avaje.ebean.RawSqlBuilder;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
@@ -22,10 +23,10 @@ import com.avaje.ebean.plugin.BeanType;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.TransactionEventTable;
|
||||
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.core.InternalConfiguration;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinderEmbedded;
|
||||
@@ -47,6 +48,12 @@ import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory;
|
||||
import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory;
|
||||
import com.avaje.ebeaninternal.xmlmapping.XmlMappingReader;
|
||||
import com.avaje.ebeaninternal.xmlmapping.model.XmAliasMapping;
|
||||
import com.avaje.ebeaninternal.xmlmapping.model.XmColumnMapping;
|
||||
import com.avaje.ebeaninternal.xmlmapping.model.XmEbean;
|
||||
import com.avaje.ebeaninternal.xmlmapping.model.XmEntity;
|
||||
import com.avaje.ebeaninternal.xmlmapping.model.XmRawSql;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreBeanAdapter;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreFactory;
|
||||
import org.slf4j.Logger;
|
||||
@@ -56,12 +63,16 @@ import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
import javax.sql.DataSource;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -116,7 +127,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final DocStoreFactory docStoreFactory;
|
||||
|
||||
private int enhancedClassCount;
|
||||
private int entityBeanCount;
|
||||
|
||||
private final boolean updateChangesOnly;
|
||||
|
||||
@@ -124,7 +135,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final String serverName;
|
||||
|
||||
private Map<Class<?>, DeployBeanInfo<?>> deplyInfoMap = new HashMap<Class<?>, DeployBeanInfo<?>>();
|
||||
private Map<Class<?>, DeployBeanInfo<?>> deployInfoMap = new HashMap<Class<?>, DeployBeanInfo<?>>();
|
||||
|
||||
private final Map<Class<?>, BeanTable> beanTableMap = new HashMap<Class<?>, BeanTable>();
|
||||
|
||||
@@ -301,6 +312,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
try {
|
||||
createListeners();
|
||||
readEntityDeploymentInitial();
|
||||
readXmlMapping();
|
||||
readEmbeddedDeployment();
|
||||
readEntityBeanTable();
|
||||
readEntityDeploymentAssociations();
|
||||
@@ -319,8 +331,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
logStatus();
|
||||
|
||||
deplyInfoMap.clear();
|
||||
deplyInfoMap = null;
|
||||
deployInfoMap.clear();
|
||||
deployInfoMap = null;
|
||||
|
||||
return asOfTableMap;
|
||||
|
||||
@@ -330,6 +342,62 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
}
|
||||
|
||||
private void readXmlMapping() {
|
||||
|
||||
try {
|
||||
ClassLoader classLoader = serverConfig.getClassLoadConfig().getClassLoader();
|
||||
|
||||
Enumeration<URL> resources = classLoader.getResources("ebean.xml");
|
||||
|
||||
List<XmEbean> mappings = new ArrayList<XmEbean>();
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
InputStream is = url.openStream();
|
||||
mappings.add(XmlMappingReader.read(is));
|
||||
is.close();
|
||||
}
|
||||
|
||||
for (XmEbean mapping : mappings) {
|
||||
List<XmEntity> entityDeploy = mapping.getEntity();
|
||||
for (XmEntity deploy : entityDeploy) {
|
||||
readEntityMapping(classLoader, deploy);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading ebean.xml", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void readEntityMapping(ClassLoader classLoader, XmEntity entityDeploy) {
|
||||
|
||||
String entityClassName = entityDeploy.getClazz();
|
||||
Class<?> entityClass;
|
||||
try {
|
||||
entityClass = Class.forName(entityClassName, false, classLoader);
|
||||
} catch (Exception e) {
|
||||
logger.error("Could not load entity bean class "+entityClassName+" for ebean.xml entry");
|
||||
return;
|
||||
}
|
||||
|
||||
DeployBeanInfo<?> info = deployInfoMap.get(entityClass);
|
||||
if (info == null) {
|
||||
logger.error("No entity bean for ebean.xml entry "+entityClassName);
|
||||
|
||||
} else {
|
||||
for (XmRawSql sql : entityDeploy.getRawSql()) {
|
||||
RawSqlBuilder builder = RawSqlBuilder.parse(sql.getQuery().getValue());
|
||||
for (XmColumnMapping columnMapping : sql.getColumnMapping()) {
|
||||
builder.columnMapping(columnMapping.getColumn(), columnMapping.getProperty());
|
||||
}
|
||||
for (XmAliasMapping aliasMapping : sql.getAliasMapping()) {
|
||||
builder.tableAliasMapping(aliasMapping.getAlias(), aliasMapping.getProperty());
|
||||
}
|
||||
info.addRawSql(sql.getName(), builder.create());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Encrypt key given the table and column name.
|
||||
*/
|
||||
@@ -381,7 +449,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
for (String depTable : viewInvalidation) {
|
||||
List<BeanDescriptor<?>> list = tableToViewDescMap.get(depTable.toLowerCase());
|
||||
if (list == null) {
|
||||
if (list != null) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).queryCacheClear();
|
||||
}
|
||||
@@ -557,7 +625,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
|
||||
private void logStatus() {
|
||||
logger.info("Entities enhanced[" + enhancedClassCount + "]");
|
||||
logger.debug("Entities[{}]", entityBeanCount);
|
||||
}
|
||||
|
||||
private <T> BeanDescriptor<T> createEmbedded(Class<T> beanClass) {
|
||||
@@ -569,7 +637,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* Return the bean deploy info for the given class.
|
||||
*/
|
||||
public <T> DeployBeanInfo<T> getDeploy(Class<T> cls) {
|
||||
return (DeployBeanInfo<T>) deplyInfoMap.get(cls);
|
||||
return (DeployBeanInfo<T>) deployInfoMap.get(cls);
|
||||
}
|
||||
|
||||
private void registerBeanDescriptor(BeanDescriptor<?> desc) {
|
||||
@@ -601,12 +669,12 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
for (Class<?> entityClass : bootupClasses.getEntities()) {
|
||||
DeployBeanInfo<?> info = createDeployBeanInfo(entityClass);
|
||||
deplyInfoMap.put(entityClass, info);
|
||||
deployInfoMap.put(entityClass, info);
|
||||
}
|
||||
for (Class<?> entityClass : bootupClasses.getEmbeddables()) {
|
||||
DeployBeanInfo<?> info = createDeployBeanInfo(entityClass);
|
||||
readDeployAssociations(info);
|
||||
deplyInfoMap.put(entityClass, info);
|
||||
deployInfoMap.put(entityClass, info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +686,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEntityBeanTable() {
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
BeanTable beanTable = createBeanTable(info);
|
||||
beanTableMap.put(beanTable.getBeanType(), beanTable);
|
||||
}
|
||||
@@ -632,18 +700,18 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEntityDeploymentAssociations() {
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
readDeployAssociations(info);
|
||||
}
|
||||
}
|
||||
|
||||
private void readInheritedIdGenerators() {
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
DeployBeanDescriptor<?> descriptor = info.getDescriptor();
|
||||
InheritInfo inheritInfo = descriptor.getInheritInfo();
|
||||
if (inheritInfo != null && !inheritInfo.isRoot()) {
|
||||
DeployBeanInfo<?> rootBeanInfo = deplyInfoMap.get(inheritInfo.getRoot().getType());
|
||||
DeployBeanInfo<?> rootBeanInfo = deployInfoMap.get(inheritInfo.getRoot().getType());
|
||||
PlatformIdGenerator rootIdGen = rootBeanInfo.getDescriptor().getIdGenerator();
|
||||
if (rootIdGen != null) {
|
||||
descriptor.setIdGenerator(rootIdGen);
|
||||
@@ -668,20 +736,20 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// We only perform 'circular' checks etc after we have
|
||||
// all the DeployBeanDescriptors created and in the map.
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
checkMappedBy(info);
|
||||
}
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
secondaryPropsJoins(info);
|
||||
}
|
||||
|
||||
// Set inheritance info
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
setInheritanceInfo(info);
|
||||
}
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
for (DeployBeanInfo<?> info : deployInfoMap.values()) {
|
||||
registerBeanDescriptor(new BeanDescriptor(this, info.getDescriptor()));
|
||||
}
|
||||
}
|
||||
@@ -695,7 +763,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
for (DeployBeanPropertyAssocOne<?> oneProp : info.getDescriptor().propertiesAssocOne()) {
|
||||
if (!oneProp.isTransient()) {
|
||||
DeployBeanInfo<?> assoc = deplyInfoMap.get(oneProp.getTargetType());
|
||||
DeployBeanInfo<?> assoc = deployInfoMap.get(oneProp.getTargetType());
|
||||
if (assoc != null) {
|
||||
oneProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
|
||||
}
|
||||
@@ -704,7 +772,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
for (DeployBeanPropertyAssocMany<?> manyProp : info.getDescriptor().propertiesAssocMany()) {
|
||||
if (!manyProp.isTransient()) {
|
||||
DeployBeanInfo<?> assoc = deplyInfoMap.get(manyProp.getTargetType());
|
||||
DeployBeanInfo<?> assoc = deployInfoMap.get(manyProp.getTargetType());
|
||||
if (assoc != null) {
|
||||
manyProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
|
||||
}
|
||||
@@ -763,7 +831,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
private DeployBeanDescriptor<?> getTargetDescriptor(DeployBeanPropertyAssoc<?> prop) {
|
||||
|
||||
Class<?> targetType = prop.getTargetType();
|
||||
DeployBeanInfo<?> info = deplyInfoMap.get(targetType);
|
||||
DeployBeanInfo<?> info = deployInfoMap.get(targetType);
|
||||
if (info == null) {
|
||||
String msg = "Can not find descriptor [" + targetType + "] for " + prop.getFullBeanName();
|
||||
throw new PersistenceException(msg);
|
||||
@@ -1141,7 +1209,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// already assigned (So custom or UUID)
|
||||
return;
|
||||
}
|
||||
if (desc.propertiesId().size() == 0) {
|
||||
if (desc.propertiesId().isEmpty()) {
|
||||
// bean doesn't have an Id property
|
||||
if (desc.isBaseTableType() && desc.getBeanFinder() == null) {
|
||||
// expecting an id property
|
||||
@@ -1348,7 +1416,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
checkInheritedClasses(beanClass);
|
||||
|
||||
if (!beanClass.getName().startsWith("com.avaje.ebean.meta")) {
|
||||
enhancedClassCount++;
|
||||
entityBeanCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeBoolean;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeLogicalType;
|
||||
import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocMappingBuilder;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyMapping;
|
||||
@@ -255,10 +256,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
|
||||
final String softDeleteDbPredicate;
|
||||
|
||||
final boolean indexed;
|
||||
|
||||
final String indexName;
|
||||
|
||||
public BeanProperty(DeployBeanProperty deploy) {
|
||||
this(null, deploy);
|
||||
}
|
||||
@@ -268,8 +265,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
this.indexed = deploy.isIndexed();
|
||||
this.indexName = deploy.getIndexName();
|
||||
this.unidirectionalShadow = deploy.isUndirectionalShadow();
|
||||
this.discriminator = deploy.isDiscriminator();
|
||||
this.localEncrypted = deploy.isLocalEncrypted();
|
||||
@@ -370,9 +365,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
this.descriptor = source.descriptor;
|
||||
this.name = InternString.intern(source.getName());
|
||||
this.propertyIndex = source.propertyIndex;
|
||||
|
||||
this.indexed = source.isIndexed();
|
||||
this.indexName = source.getIndexName();
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
// override with sqlFormula not currently supported
|
||||
this.sqlFormulaJoin = null;
|
||||
@@ -422,7 +414,7 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
this.generatedProperty = source.getGeneratedProperty();
|
||||
this.getter = source.getter;
|
||||
this.setter = source.setter;
|
||||
this.dbType = source.getDbType();
|
||||
this.dbType = source.getDbType(true);
|
||||
this.scalarType = source.scalarType;
|
||||
this.lob = isLobType(dbType);
|
||||
this.propertyType = source.getPropertyType();
|
||||
@@ -631,14 +623,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this object is part of an inheritance hierarchy.
|
||||
*/
|
||||
@@ -1104,9 +1088,14 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
|
||||
/**
|
||||
* Return the database jdbc data type this is mapped to.
|
||||
*
|
||||
* @param platformTypes Set as false when we want logical platform agnostic types.
|
||||
*/
|
||||
public int getDbType() {
|
||||
return dbType;
|
||||
public int getDbType(boolean platformTypes) {
|
||||
if (platformTypes || !(scalarType instanceof ScalarTypeLogicalType)) {
|
||||
return dbType;
|
||||
}
|
||||
return ((ScalarTypeLogicalType)scalarType).getLogicalType();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -322,7 +322,7 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty {
|
||||
BeanProperty idProp = target.getIdProperty();
|
||||
BeanProperty[] others = target.propertiesBaseScalar();
|
||||
|
||||
if (descriptor.isSqlSelectBased()) {
|
||||
if (descriptor.isRawSqlBased()) {
|
||||
String dbColumn = owner.getDbColumn();
|
||||
return new ImportedIdSimple(owner, dbColumn, idProp, 0);
|
||||
}
|
||||
|
||||
@@ -1028,7 +1028,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
if (isManyToMany()) {
|
||||
if (liveBean == null) {
|
||||
// add new relationship (Map not allowed here)
|
||||
liveVal.addBean(targetDescriptor.createReference(Boolean.FALSE, id, null));
|
||||
liveVal.addBean(targetDescriptor.createReference(Boolean.FALSE, false, id, null));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -422,7 +422,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
// cacheData is the id value, maybe already in persistence context
|
||||
Object assocBean = targetDescriptor.contextGet(context, cacheData);
|
||||
if (assocBean == null) {
|
||||
assocBean = targetDescriptor.createReference(Boolean.FALSE, cacheData, context);
|
||||
assocBean = targetDescriptor.createReference(Boolean.FALSE, false, cacheData, context);
|
||||
}
|
||||
setValue(bean, assocBean);
|
||||
}
|
||||
|
||||
@@ -84,4 +84,9 @@ public interface DbReadContext {
|
||||
* Return true if the underlying query is a 'asDraft' query.
|
||||
*/
|
||||
boolean isDraftQuery();
|
||||
|
||||
/**
|
||||
* Return true if this request disables lazy loading.
|
||||
*/
|
||||
boolean isDisableLazyLoading();
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ public abstract class DeployParser {
|
||||
*/
|
||||
public abstract Set<String> getIncludes();
|
||||
|
||||
public void setEncrypted(boolean encrytped) {
|
||||
this.encrypted = encrytped;
|
||||
}
|
||||
public void setEncrypted(boolean encrypted) {
|
||||
this.encrypted = encrypted;
|
||||
}
|
||||
|
||||
public String parse(String source) {
|
||||
|
||||
if (source == null) {
|
||||
return source;
|
||||
return null;
|
||||
}
|
||||
|
||||
pos = -1;
|
||||
|
||||
+12
-3
@@ -3,7 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
/**
|
||||
* Holds multiple column unique constraints defined for an entity.
|
||||
*/
|
||||
public class CompoundUniqueConstraint {
|
||||
public class IndexDefinition {
|
||||
|
||||
private final String[] columns;
|
||||
|
||||
@@ -11,7 +11,16 @@ public class CompoundUniqueConstraint {
|
||||
|
||||
private final boolean unique;
|
||||
|
||||
public CompoundUniqueConstraint(String[] columns, String name, boolean unique) {
|
||||
/**
|
||||
* A single column index.
|
||||
*/
|
||||
public IndexDefinition(String column, String name, boolean unique) {
|
||||
this.columns = new String[]{column};
|
||||
this.unique = unique;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public IndexDefinition(String[] columns, String name, boolean unique) {
|
||||
this.columns = columns;
|
||||
this.unique = unique;
|
||||
this.name = name;
|
||||
@@ -20,7 +29,7 @@ public class CompoundUniqueConstraint {
|
||||
/**
|
||||
* Create a unique constraint given the column names.
|
||||
*/
|
||||
public CompoundUniqueConstraint(String[] columns) {
|
||||
public IndexDefinition(String[] columns) {
|
||||
this.columns = columns;
|
||||
this.unique = true;
|
||||
this.name = null;
|
||||
@@ -144,15 +144,13 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
*/
|
||||
public BeanProperty findMatchImport(String matchDbColumn) {
|
||||
|
||||
BeanProperty p = null;
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
p = imported[i].findMatchImport(matchDbColumn);
|
||||
BeanProperty p = imported[i].findMatchImport(matchDbColumn);
|
||||
if (p != null) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-13
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebean.annotation.Cache;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.DocStoreMode;
|
||||
@@ -23,7 +24,7 @@ import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostLoad;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
|
||||
@@ -35,14 +36,18 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
*/
|
||||
public class DeployBeanDescriptor<T> {
|
||||
|
||||
private static final Map<String, RawSql> EMPTY_RAW_MAP = new HashMap<String, RawSql>();
|
||||
|
||||
private static class PropOrder implements Comparator<DeployBeanProperty> {
|
||||
|
||||
public int compare(DeployBeanProperty o1, DeployBeanProperty o2) {
|
||||
@@ -66,6 +71,8 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
private LinkedHashMap<String, DeployBeanProperty> propMap = new LinkedHashMap<String, DeployBeanProperty>();
|
||||
|
||||
private Map<String, RawSql> namedRawSql;
|
||||
|
||||
private EntityType entityType;
|
||||
|
||||
private DeployBeanPropertyAssocOne<?> unidirectional;
|
||||
@@ -108,7 +115,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private boolean updateChangesOnly;
|
||||
|
||||
private List<CompoundUniqueConstraint> compoundUniqueConstraints;
|
||||
private List<IndexDefinition> indexDefinitions;
|
||||
|
||||
/**
|
||||
* The base database table.
|
||||
@@ -283,7 +290,7 @@ public class DeployBeanDescriptor<T> {
|
||||
docStoreUpdate = docStore.update();
|
||||
docStoreDelete = docStore.delete();
|
||||
String doc = docStore.doc();
|
||||
if (doc.length() > 0) {
|
||||
if (!doc.isEmpty()) {
|
||||
docStorePathProperties = PathProperties.parse(doc);
|
||||
}
|
||||
}
|
||||
@@ -388,7 +395,7 @@ public class DeployBeanDescriptor<T> {
|
||||
public void setCache(Cache cache) {
|
||||
|
||||
String naturalKey = null;
|
||||
if (cache.naturalKey().length() > 0) {
|
||||
if (!cache.naturalKey().isEmpty()) {
|
||||
// find the property and mark as natural key property
|
||||
String propName = cache.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = getBeanProperty(propName);
|
||||
@@ -440,21 +447,21 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(CompoundUniqueConstraint c) {
|
||||
if (compoundUniqueConstraints == null) {
|
||||
compoundUniqueConstraints = new ArrayList<CompoundUniqueConstraint>();
|
||||
public void addIndex(IndexDefinition c) {
|
||||
if (indexDefinitions == null) {
|
||||
indexDefinitions = new ArrayList<IndexDefinition>();
|
||||
}
|
||||
compoundUniqueConstraints.add(c);
|
||||
indexDefinitions.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the compound unique constraints (can be null).
|
||||
*/
|
||||
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
|
||||
if (compoundUniqueConstraints == null) {
|
||||
public IndexDefinition[] getIndexDefinitions() {
|
||||
if (indexDefinitions == null) {
|
||||
return null;
|
||||
} else {
|
||||
return compoundUniqueConstraints.toArray(new CompoundUniqueConstraint[compoundUniqueConstraints.size()]);
|
||||
return indexDefinitions.toArray(new IndexDefinition[indexDefinitions.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +590,7 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
public void setView(String viewName, String[] dependentTables) {
|
||||
this.entityType = EntityType.VIEW;
|
||||
this.dependentTables = this.dependentTables;
|
||||
this.dependentTables = dependentTables;
|
||||
setBaseTable(new TableName(viewName), "", "");
|
||||
}
|
||||
|
||||
@@ -835,7 +842,7 @@ public class DeployBeanDescriptor<T> {
|
||||
return null;
|
||||
}
|
||||
String selectClause = sb.toString();
|
||||
if (selectClause.length() == 0) {
|
||||
if (selectClause.isEmpty()) {
|
||||
throw new IllegalStateException("Bean " + getFullName() + " has no properties?");
|
||||
}
|
||||
return selectClause.substring(0, selectClause.length() - 1);
|
||||
@@ -1047,4 +1054,21 @@ public class DeployBeanDescriptor<T> {
|
||||
if (docStorePersist != DocStoreMode.DEFAULT) return docStorePersist;
|
||||
return serverConfig.getDocStoreConfig().getPersist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the named RawSql queries.
|
||||
*/
|
||||
public Map<String, RawSql> getNamedRawSql() {
|
||||
return (namedRawSql != null) ? namedRawSql : EMPTY_RAW_MAP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a named RawSql from ebean.xml file.
|
||||
*/
|
||||
public void addRawSql(String name, RawSql rawSql) {
|
||||
if (namedRawSql == null) {
|
||||
namedRawSql = new HashMap<String, RawSql>();
|
||||
}
|
||||
namedRawSql.put(name, rawSql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeWrapper;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyOptions;
|
||||
|
||||
@@ -192,9 +191,6 @@ public class DeployBeanProperty {
|
||||
|
||||
private int sortOrder;
|
||||
|
||||
private boolean indexed;
|
||||
private String indexName;
|
||||
|
||||
private boolean excludedFromHistory;
|
||||
|
||||
private boolean draft;
|
||||
@@ -386,7 +382,7 @@ public class DeployBeanProperty {
|
||||
* Set a specific DB column definition.
|
||||
*/
|
||||
public void setDbColumnDefn(String dbColumnDefn) {
|
||||
if (dbColumnDefn == null || dbColumnDefn.trim().length() == 0) {
|
||||
if (dbColumnDefn == null || dbColumnDefn.trim().isEmpty()) {
|
||||
this.dbColumnDefn = null;
|
||||
} else {
|
||||
this.dbColumnDefn = InternString.intern(dbColumnDefn);
|
||||
@@ -849,22 +845,6 @@ public class DeployBeanProperty {
|
||||
return desc.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public void setIndexed() {
|
||||
this.indexed = true;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public void setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
public boolean isExcludedFromHistory() {
|
||||
return excludedFromHistory;
|
||||
}
|
||||
|
||||
+2
-2
@@ -178,7 +178,7 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
|
||||
* Set the default mapKey to use when returning a Map.
|
||||
*/
|
||||
public void setMapKey(String mapKey) {
|
||||
if (mapKey != null && mapKey.length() > 0) {
|
||||
if (mapKey != null && !mapKey.isEmpty()) {
|
||||
this.mapKey = mapKey;
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
|
||||
* list, set or map.
|
||||
*/
|
||||
public void setFetchOrderBy(String orderBy) {
|
||||
if (orderBy != null && orderBy.length() > 0) {
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
fetchOrderBy = orderBy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public abstract class AnnotationBase {
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
protected boolean isEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.annotation.View;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -68,13 +68,11 @@ public class AnnotationClass extends AnnotationParser {
|
||||
if (override != null) {
|
||||
String propertyName = override.name();
|
||||
Column column = override.column();
|
||||
if (column != null) {
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propertyName);
|
||||
if (beanProperty == null) {
|
||||
logger.error("AttributeOverride property [" + propertyName + "] not found on " + descriptor.getFullName());
|
||||
} else {
|
||||
readColumn(column, beanProperty);
|
||||
}
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propertyName);
|
||||
if (beanProperty == null) {
|
||||
logger.error("AttributeOverride property [" + propertyName + "] not found on " + descriptor.getFullName());
|
||||
} else {
|
||||
readColumn(column, beanProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,12 +118,12 @@ public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
Index index = cls.getAnnotation(Index.class);
|
||||
if (index != null) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(index.columnNames(), index.name(), index.unique()));
|
||||
descriptor.addIndex(new IndexDefinition(index.columnNames(), index.name(), index.unique()));
|
||||
}
|
||||
|
||||
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
|
||||
if (uc != null) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(uc.columnNames()));
|
||||
descriptor.addIndex(new IndexDefinition(uc.columnNames()));
|
||||
}
|
||||
|
||||
View view = cls.getAnnotation(View.class);
|
||||
@@ -136,7 +134,7 @@ public class AnnotationClass extends AnnotationParser {
|
||||
if (table != null) {
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(c.columnNames()));
|
||||
descriptor.addIndex(new IndexDefinition(c.columnNames()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.avaje.ebean.config.dbplatform.DbEncrypt;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
|
||||
@@ -314,8 +315,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (hasRelationshipItem(prop)) {
|
||||
throw new RuntimeException("Can't use Index on foreign key relationships.");
|
||||
}
|
||||
prop.setIndexed();
|
||||
prop.setIndexName(index.name());
|
||||
descriptor.addIndex(new IndexDefinition(prop.getDbColumn(), index.name(), index.unique()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Wraps information about a bean during deployment parsing.
|
||||
*/
|
||||
@@ -75,4 +76,10 @@ public class DeployBeanInfo<T> {
|
||||
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named RawSql from ebean.xml.
|
||||
*/
|
||||
public void addRawSql(String name, RawSql rawSql) {
|
||||
descriptor.addRawSql(name, rawSql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public class DeployInheritInfo {
|
||||
public void setDiscriminatorValue(String value) {
|
||||
if (value != null) {
|
||||
value = value.trim();
|
||||
if (value.length() != 0) {
|
||||
if (!value.isEmpty()) {
|
||||
discriminatorStringValue = value;
|
||||
// convert the value if desired
|
||||
if (discriminatorType == Types.INTEGER) {
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SqlReservedWords {
|
||||
public static synchronized void addKeyword(String keyword){
|
||||
if (keyword != null){
|
||||
keyword = keyword.trim().toUpperCase();
|
||||
if (keyword.length() > 0){
|
||||
if (!keyword.isEmpty()){
|
||||
keywords.add(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public class StringHelper {
|
||||
String listDelimiter, String nameValueSeparator) {
|
||||
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.length() == 0)) {
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
@@ -56,7 +56,7 @@ public class StringHelper {
|
||||
* Return true if the value is null or an empty string.
|
||||
*/
|
||||
public static boolean isNull(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ public class StringHelper {
|
||||
// there is a key without a value?
|
||||
String key = allNameValuePairs.substring(pos, delimPos);
|
||||
key = key.trim();
|
||||
if (key.length() > 0) {
|
||||
if (!key.isEmpty()) {
|
||||
map.put(key, null);
|
||||
}
|
||||
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
|
||||
|
||||
@@ -105,7 +105,7 @@ public class BatchedPstmtHolder {
|
||||
firstError = ex;
|
||||
errorSql = bs.getSql();
|
||||
} else {
|
||||
logger.error(null, ex);
|
||||
logger.error("Error executing batched PreparedStatement", ex);
|
||||
}
|
||||
isError = true;
|
||||
|
||||
@@ -113,8 +113,7 @@ public class BatchedPstmtHolder {
|
||||
try {
|
||||
bs.close();
|
||||
} catch (SQLException ex) {
|
||||
// error closing PreparedStatement
|
||||
logger.error(null, ex);
|
||||
logger.error("Error closing batched PreparedStatement", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public class Binder {
|
||||
|
||||
private final int asOfBindCount;
|
||||
|
||||
private final boolean bindAsOfWithFromClause;
|
||||
private final boolean asOfStandardsBased;
|
||||
|
||||
private final DbExpressionHandler dbExpressionHandler;
|
||||
|
||||
@@ -42,12 +42,12 @@ public class Binder {
|
||||
/**
|
||||
* Set the PreparedStatement with which to bind variables to.
|
||||
*/
|
||||
public Binder(TypeManager typeManager, int asOfBindCount, boolean bindAsOfWithFromClause,
|
||||
public Binder(TypeManager typeManager, int asOfBindCount, boolean asOfStandardsBased,
|
||||
DbExpressionHandler dbExpressionHandler, DataTimeZone dataTimeZone) {
|
||||
|
||||
this.typeManager = typeManager;
|
||||
this.asOfBindCount = asOfBindCount;
|
||||
this.bindAsOfWithFromClause = bindAsOfWithFromClause;
|
||||
this.asOfStandardsBased = asOfStandardsBased;
|
||||
this.dbExpressionHandler = dbExpressionHandler;
|
||||
this.dataTimeZone = dataTimeZone;
|
||||
}
|
||||
@@ -60,12 +60,10 @@ public class Binder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the 'as of' predicates are in the from/join clause in which case the timestamp is
|
||||
* bound early (before all the other predicates ala Oracle). Return false if the 'as of' predicates are
|
||||
* appended to the end of the predicates and the timestamp is bound last (Postgres, MySql).
|
||||
* Return true if the 'as of' history support is SQL2011 standards based.
|
||||
*/
|
||||
public boolean isBindAsOfWithFromClause() {
|
||||
return bindAsOfWithFromClause;
|
||||
public boolean isAsOfStandardsBased() {
|
||||
return asOfStandardsBased;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -839,16 +839,6 @@ public final class DefaultPersister implements Persister {
|
||||
this.publish = request.isPublish();
|
||||
}
|
||||
|
||||
private SaveManyPropRequest(BeanPropertyAssocMany<?> many, EntityBean parentBean, SpiTransaction t) {
|
||||
this.insertedParent = false;
|
||||
this.many = many;
|
||||
this.parentBean = parentBean;
|
||||
this.transaction = t;
|
||||
this.cascade = true;
|
||||
this.deleteMissingChildren = false;
|
||||
this.publish = false;
|
||||
}
|
||||
|
||||
public boolean isSaveIntersection() {
|
||||
return transaction.isSaveAssocManyIntersection(many.getIntersectionTableJoin().getTable(), many.getBeanDescriptor().getName());
|
||||
}
|
||||
@@ -1304,7 +1294,7 @@ public final class DefaultPersister implements Persister {
|
||||
// convert into a list of reference objects and perform delete by object
|
||||
List<Object> refList = new ArrayList<Object>(childIds.size());
|
||||
for (Object id : childIds) {
|
||||
refList.add(targetDesc.createReference(null, id, null));
|
||||
refList.add(targetDesc.createReference(null, false, id, null));
|
||||
}
|
||||
deleteList(refList, t, softDelete);
|
||||
|
||||
|
||||
@@ -107,6 +107,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final boolean disableLazyLoading;
|
||||
|
||||
private Map<String, String> currentPathMap;
|
||||
|
||||
private String currentPrefix;
|
||||
@@ -197,6 +199,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
this.lazyLoadManyProperty = query.getLazyLoadMany();
|
||||
|
||||
this.readOnly = request.isReadOnly();
|
||||
this.disableLazyLoading = query.isDisableLazyLoading();
|
||||
|
||||
this.objectGraphNode = query.getParentNode();
|
||||
this.profilingListener = query.getProfilingListener();
|
||||
@@ -239,6 +242,11 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
return query.isAsDraft();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableLazyLoading() {
|
||||
return disableLazyLoading;
|
||||
}
|
||||
|
||||
public Boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@@ -466,18 +466,20 @@ public class CQueryBuilder {
|
||||
String inheritanceWhere = select.getInheritanceWhereSql();
|
||||
|
||||
boolean hasWhere = false;
|
||||
if (inheritanceWhere.length() > 0) {
|
||||
if (!inheritanceWhere.isEmpty()) {
|
||||
sb.append(" where");
|
||||
sb.append(inheritanceWhere);
|
||||
hasWhere = true;
|
||||
}
|
||||
|
||||
int asOfCount = query.getAsOfTableCount();
|
||||
if (asOfCount > 0 && !historySupport.isStandardsBased()) {
|
||||
hasWhere = appendWhere(hasWhere, sb);
|
||||
sb.append(historySupport.getAsOfPredicate(request.getBaseTableAlias()));
|
||||
}
|
||||
|
||||
if (request.isFindById() || query.getId() != null) {
|
||||
if (hasWhere) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" where ");
|
||||
}
|
||||
appendWhere(hasWhere, sb);
|
||||
|
||||
BeanDescriptor<?> desc = request.getBeanDescriptor();
|
||||
String idSql = desc.getIdBinderIdSql();
|
||||
@@ -515,24 +517,6 @@ public class CQueryBuilder {
|
||||
sb.append(dbFilterMany);
|
||||
}
|
||||
|
||||
List<String> asOfTableAlias = query.getAsOfTableAlias();
|
||||
if (asOfTableAlias != null && !historySupport.isBindAtFromClause()) {
|
||||
// append the effective date predicates for each table alias
|
||||
// that maps to a @History entity involved in this query
|
||||
// Do this when history using separate tables/views (PG, MySql etc)
|
||||
if (!hasWhere) {
|
||||
sb.append(" where ");
|
||||
} else {
|
||||
sb.append("and ");
|
||||
}
|
||||
for (int i = 0; i < asOfTableAlias.size(); i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(historySupport.getAsOfPredicate(asOfTableAlias.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!query.isIncludeSoftDeletes()) {
|
||||
List<String> softDeletePredicates = query.getSoftDeletePredicates();
|
||||
if (softDeletePredicates != null) {
|
||||
@@ -565,6 +549,18 @@ public class CQueryBuilder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Append where or and based on the hasWhere flag.
|
||||
*/
|
||||
private boolean appendWhere(boolean hasWhere, StringBuilder sb) {
|
||||
if (hasWhere) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" where ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the dbOrderBy clause to be safe for adding to select. This is done when 'distinct' is
|
||||
* used.
|
||||
@@ -575,7 +571,7 @@ public class CQueryBuilder {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class CQueryBuilderRawSql {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
private String getOrderBy(CQueryPredicates predicates, RawSql.Sql sql) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebeaninternal.server.core.QueryIterator;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.Version;
|
||||
@@ -19,6 +20,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -34,15 +36,22 @@ public class CQueryEngine {
|
||||
|
||||
private static final String T0 = "t0";
|
||||
|
||||
private final int defaultFetchSizeFindList;
|
||||
|
||||
private final int defaultFetchSizeFindEach;
|
||||
|
||||
private final boolean forwardOnlyHintOnFindIterate;
|
||||
|
||||
private final CQueryBuilder queryBuilder;
|
||||
|
||||
private final CQueryHistorySupport historySupport;
|
||||
|
||||
public CQueryEngine(DatabasePlatform dbPlatform, Binder binder, Map<String, String> asOfTableMapping, String asOfSysPeriod, Map<String, String> draftTableMap) {
|
||||
public CQueryEngine(ServerConfig serverConfig, DatabasePlatform dbPlatform, Binder binder, Map<String, String> asOfTableMapping, Map<String, String> draftTableMap) {
|
||||
this.defaultFetchSizeFindEach = serverConfig.getJdbcFetchSizeFindEach();
|
||||
this.defaultFetchSizeFindList = serverConfig.getJdbcFetchSizeFindList();
|
||||
this.forwardOnlyHintOnFindIterate = dbPlatform.isForwardOnlyHintOnFindIterate();
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, asOfSysPeriod);
|
||||
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, serverConfig.getAsOfSysPeriod());
|
||||
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
}
|
||||
|
||||
@@ -90,11 +99,7 @@ public class CQueryEngine {
|
||||
BeanIdList list = rcQuery.findIds();
|
||||
|
||||
if (request.isLogSql()) {
|
||||
String logSql = rcQuery.getGeneratedSql();
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
|
||||
}
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -114,6 +119,14 @@ public class CQueryEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void logGeneratedSql(OrmQueryRequest<T> request, String sql, String bindLog) {
|
||||
String logSql = sql;
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", bindLog, ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and execute the row count query.
|
||||
*/
|
||||
@@ -125,11 +138,7 @@ public class CQueryEngine {
|
||||
int rowCount = rcQuery.findRowCount();
|
||||
|
||||
if (request.isLogSql()) {
|
||||
String logSql = rcQuery.getGeneratedSql();
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
|
||||
}
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -137,7 +146,6 @@ public class CQueryEngine {
|
||||
}
|
||||
|
||||
if (request.getQuery().isFutureFetch()) {
|
||||
logger.debug("Future findRowCount completed!");
|
||||
request.getTransaction().end();
|
||||
}
|
||||
|
||||
@@ -158,7 +166,9 @@ public class CQueryEngine {
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
try {
|
||||
|
||||
if (defaultFetchSizeFindEach > 0) {
|
||||
request.setDefaultFetchBuffer(defaultFetchSizeFindEach);
|
||||
}
|
||||
if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
@@ -204,15 +214,16 @@ public class CQueryEngine {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
|
||||
if (query.isVersionsBetween() && !historySupport.isBindAtFromClause()) {
|
||||
String sysPeriodLower = getSysPeriodLower(query);
|
||||
if (query.isVersionsBetween() && !historySupport.isStandardsBased()) {
|
||||
// just add as normal predicates using the lower bound
|
||||
query.where().gt(getSysPeriodLower(query), query.getVersionStart());
|
||||
query.where().lt(getSysPeriodLower(query), query.getVersionEnd());
|
||||
query.where().gt(sysPeriodLower, query.getVersionStart());
|
||||
query.where().lt(sysPeriodLower, query.getVersionEnd());
|
||||
}
|
||||
|
||||
// order by id asc, lower sys period desc
|
||||
query.orderBy().asc(request.getBeanDescriptor().getIdProperty().getName());
|
||||
query.orderBy().desc(getSysPeriodLower(query));
|
||||
query.orderBy().desc(sysPeriodLower);
|
||||
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
try {
|
||||
@@ -222,6 +233,9 @@ public class CQueryEngine {
|
||||
}
|
||||
|
||||
List<Version<T>> versions = cquery.readVersions();
|
||||
// just order in memory rather than use NULLS LAST as that
|
||||
// is not universally supported, not expect huge list here
|
||||
Collections.sort(versions, OrderVersionDesc.INSTANCE);
|
||||
deriveVersionDiffs(versions, request);
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -296,6 +310,9 @@ public class CQueryEngine {
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
try {
|
||||
if (defaultFetchSizeFindList > 0) {
|
||||
request.setDefaultFetchBuffer(defaultFetchSizeFindList);
|
||||
}
|
||||
if (!cquery.prepareBindExecuteQuery()) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
|
||||
@@ -197,7 +197,7 @@ public class CQueryFetchIds {
|
||||
dataReader = null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.error(null, e);
|
||||
logger.error("Error closing DataReader", e);
|
||||
}
|
||||
try {
|
||||
if (pstmt != null) {
|
||||
@@ -205,7 +205,7 @@ public class CQueryFetchIds {
|
||||
pstmt = null;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
logger.error(null, e);
|
||||
logger.error("Error closing PreparedStatement", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,6 +228,11 @@ public class CQueryFetchIds {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableLazyLoading() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isRawSql() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -31,11 +31,10 @@ public class CQueryHistorySupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the bind of 'as of' timestamp occurs with the from clause
|
||||
* rather than at the end.
|
||||
* Return true if the underlying history support is standards based.
|
||||
*/
|
||||
public boolean isBindAtFromClause() {
|
||||
return dbHistorySupport.isBindWithFromClause();
|
||||
public boolean isStandardsBased() {
|
||||
return dbHistorySupport.isStandardsBased();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,6 +70,8 @@ public class CQueryPlan {
|
||||
|
||||
protected final DataTimeZone dataTimeZone;
|
||||
|
||||
private final int asOfTableCount;
|
||||
|
||||
/**
|
||||
* Key used to identify the query plan in audit logging.
|
||||
*/
|
||||
@@ -86,6 +88,7 @@ public class CQueryPlan {
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.planKey = request.getQueryPlanKey();
|
||||
this.autoTuned = request.getQuery().isAutoTuned();
|
||||
this.asOfTableCount = request.getQuery().getAsOfTableCount();
|
||||
if (sqlRes != null) {
|
||||
this.sql = sqlRes.getSql();
|
||||
this.rowNumberIncluded = sqlRes.isIncludesRowNumberColumn();
|
||||
@@ -111,6 +114,7 @@ public class CQueryPlan {
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.planKey = buildPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
this.autoTuned = false;
|
||||
this.asOfTableCount = 0;
|
||||
this.sql = sql;
|
||||
this.sqlTree = sqlTree;
|
||||
this.rawSql = rawSql;
|
||||
@@ -151,6 +155,10 @@ public class CQueryPlan {
|
||||
return dataBind;
|
||||
}
|
||||
|
||||
public int getAsOfTableCount() {
|
||||
return asOfTableCount;
|
||||
}
|
||||
|
||||
public boolean isAutoTuned() {
|
||||
return autoTuned;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class CQueryPredicates {
|
||||
updateProperties.bind(binder, dataBind);
|
||||
}
|
||||
|
||||
if (query.isVersionsBetween() && binder.isBindAsOfWithFromClause()) {
|
||||
if (query.isVersionsBetween() && binder.isAsOfStandardsBased()) {
|
||||
// sql2011 based versions between timestamp syntax
|
||||
Timestamp start = query.getVersionStart();
|
||||
Timestamp end = query.getVersionEnd();
|
||||
@@ -136,13 +136,13 @@ public class CQueryPredicates {
|
||||
dataBind.append(", ");
|
||||
}
|
||||
|
||||
List<String> historyTableAlias = query.getAsOfTableAlias();
|
||||
if (historyTableAlias != null && binder.isBindAsOfWithFromClause()) {
|
||||
int asOfTableCount = request.getQueryPlan().getAsOfTableCount();
|
||||
if (asOfTableCount > 0) {
|
||||
// bind the asOf value for each table alias as part of the from/join clauses
|
||||
// there is one effective date predicate per table alias
|
||||
Timestamp asOf = query.getAsOf();
|
||||
dataBind.append("asOf ").append(asOf);
|
||||
for (int i = 0; i < historyTableAlias.size() * binder.getAsOfBindCount(); i++) {
|
||||
for (int i = 0; i < asOfTableCount * binder.getAsOfBindCount(); i++) {
|
||||
binder.bindObject(dataBind, asOf);
|
||||
}
|
||||
dataBind.append(", ");
|
||||
@@ -167,16 +167,6 @@ public class CQueryPredicates {
|
||||
filterMany.bind(dataBind);
|
||||
}
|
||||
|
||||
if (historyTableAlias != null && !binder.isBindAsOfWithFromClause()) {
|
||||
// bind the asOf value for each table alias after all the normal predicates
|
||||
// there is one effective date predicate per table alias
|
||||
Timestamp asOf = query.getAsOf();
|
||||
dataBind.append(" asOf ").append(asOf);
|
||||
for (int i = 0; i < historyTableAlias.size() * binder.getAsOfBindCount(); i++) {
|
||||
binder.bindObject(dataBind, asOf);
|
||||
}
|
||||
}
|
||||
|
||||
if (having != null) {
|
||||
having.bind(dataBind);
|
||||
}
|
||||
@@ -305,7 +295,7 @@ public class CQueryPredicates {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
private String parse(String expr, DeployParser deployParser) {
|
||||
|
||||
@@ -106,8 +106,8 @@ public class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
tableJoins.add(joinKey);
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(type);
|
||||
sb.append(" ").append(type);
|
||||
boolean addAsOfOnClause = false;
|
||||
if (draftSupport != null) {
|
||||
appendTable(table, draftSupport.getDraftTable(table));
|
||||
|
||||
@@ -117,32 +117,32 @@ public class DefaultDbSqlContext implements DbSqlContext {
|
||||
} else {
|
||||
// check if there is an associated history table and if so
|
||||
// use the unionAll view - we expect an additional predicate to match
|
||||
appendTable(table, historySupport.getAsOfView(table));
|
||||
String asOfView = historySupport.getAsOfView(table);
|
||||
appendTable(table, asOfView);
|
||||
if (asOfView != null) {
|
||||
addAsOfOnClause = !historySupport.isStandardsBased();
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(a2);
|
||||
sb.append(" on ");
|
||||
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
TableJoinColumn pair = cols[i];
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
sb.append(a2);
|
||||
sb.append(".").append(pair.getForeignDbColumn());
|
||||
sb.append(a2).append(".").append(pair.getForeignDbColumn());
|
||||
sb.append(" = ");
|
||||
sb.append(a1);
|
||||
sb.append(".").append(pair.getLocalDbColumn());
|
||||
sb.append(a1).append(".").append(pair.getLocalDbColumn());
|
||||
}
|
||||
|
||||
|
||||
// add on any inheritance where clause
|
||||
if (inheritance != null && inheritance.length() > 0) {
|
||||
sb.append(" and ");
|
||||
sb.append(a2);
|
||||
sb.append(".");
|
||||
sb.append(inheritance);
|
||||
if (inheritance != null && !inheritance.isEmpty()) {
|
||||
sb.append(" and ").append(a2).append(".").append(inheritance);
|
||||
}
|
||||
|
||||
if (addAsOfOnClause) {
|
||||
sb.append(" and ").append(historySupport.getAsOfPredicate(a2));
|
||||
}
|
||||
|
||||
sb.append(" ");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebean.Version;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Compare Version beans in descending order with nulls last.
|
||||
*/
|
||||
class OrderVersionDesc implements Comparator<Version<?>> {
|
||||
|
||||
static final OrderVersionDesc INSTANCE = new OrderVersionDesc();
|
||||
|
||||
@Override
|
||||
public int compare(Version<?> o1, Version<?> o2) {
|
||||
|
||||
Timestamp v1 = o1.getStart();
|
||||
if (v1 == null) {
|
||||
return 1;
|
||||
}
|
||||
Timestamp v2 = o2.getStart();
|
||||
if (v2 == null) {
|
||||
return -1;
|
||||
}
|
||||
return v1.compareTo(v2) * -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class SqlTreeBuilder {
|
||||
this.queryDetail = query.getDetail();
|
||||
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.getQuery().getAlias() == null ? request.getBeanDescriptor().getBaseTableAlias() : request.getQuery().getAlias());
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias());
|
||||
this.ctx = new DefaultDbSqlContext(alias, tableAliasPlaceHolder, columnAliasPrefix, !subQuery, historySupport, draftSupport);
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ public class SqlTreeBuilder {
|
||||
// This makes sense for transient properties used to
|
||||
// hold sum() count() type values (with SqlSelect)
|
||||
for (String propName : queryProps.getSelectProperties()) {
|
||||
if (propName.length() > 0) {
|
||||
if (!propName.isEmpty()) {
|
||||
addProperty(selectProps, desc, queryProps, propName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
* Table alias set if this bean node includes a join to a intersection
|
||||
* table and that table has history support.
|
||||
*/
|
||||
protected String intersectionAsOfTableAlias;
|
||||
private boolean intersectionAsOfTableAlias;
|
||||
|
||||
/**
|
||||
* Construct for Raw SQL.
|
||||
@@ -128,7 +128,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
// the bean has an Id property and we want to use it
|
||||
this.readId = withId && (desc.getIdProperty() != null);
|
||||
this.disableLazyLoad = disableLazyLoad || !readId || desc.isSqlSelectBased() || temporalVersions;
|
||||
this.disableLazyLoad = disableLazyLoad || !readId || desc.isRawSqlBased() || temporalVersions;
|
||||
|
||||
this.partialObject = props.isPartialObject();
|
||||
this.properties = props.getProps();
|
||||
@@ -303,7 +303,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (!lazyLoadMany && localBean != null) {
|
||||
ctx.setCurrentPrefix(prefix, pathMap);
|
||||
if (readId && !temporalVersions) {
|
||||
createListProxies(localDesc, ctx, localBean);
|
||||
createListProxies(localDesc, ctx, localBean, disableLazyLoad);
|
||||
}
|
||||
if (temporalMode == SpiQuery.TemporalMode.DRAFT) {
|
||||
localDesc.setDraft(localBean);
|
||||
@@ -360,7 +360,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
* Create lazy loading proxies for the Many's except for the one that is
|
||||
* included in the actual query.
|
||||
*/
|
||||
private void createListProxies(BeanDescriptor<?> localDesc, DbReadContext ctx, EntityBean localBean) {
|
||||
private void createListProxies(BeanDescriptor<?> localDesc, DbReadContext ctx, EntityBean localBean, boolean disableLazyLoad) {
|
||||
|
||||
BeanPropertyAssocMany<?> fetchedMany = ctx.getManyProperty();
|
||||
|
||||
@@ -371,8 +371,13 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (fetchedMany == null || !fetchedMany.equals(manys[i])) {
|
||||
// create a proxy for the many (deferred fetching)
|
||||
BeanCollection<?> ref = manys[i].createReferenceIfNull(localBean);
|
||||
if (ref != null && !ref.isRegisteredWithLoadContext()) {
|
||||
ctx.register(manys[i].getName(), ref);
|
||||
if (ref != null) {
|
||||
if (disableLazyLoad) {
|
||||
ref.setDisableLazyLoad(true);
|
||||
}
|
||||
if (!ref.isRegisteredWithLoadContext()) {
|
||||
ctx.register(manys[i].getName(), ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -433,15 +438,14 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
public void appendWhere(DbSqlContext ctx) {
|
||||
|
||||
// Only apply inheritance to root node as any join will alreay have the inheritance join include - see TableJoin
|
||||
// Only apply inheritance to root node as any join will already have the inheritance join include - see TableJoin
|
||||
if (inheritInfo != null && nodeBeanProp == null) {
|
||||
if (!inheritInfo.isRoot()) {
|
||||
// restrict to this type and
|
||||
// sub types of this type.
|
||||
// restrict to this type and sub types of this type.
|
||||
if (ctx.length() > 0) {
|
||||
ctx.append(" and");
|
||||
}
|
||||
ctx.append(" ").append(ctx.getTableAlias(prefix)).append(".");// tableAlias
|
||||
ctx.append(" ").append(ctx.getTableAlias(prefix)).append(".");
|
||||
ctx.append(inheritInfo.getWhere()).append(" ");
|
||||
}
|
||||
}
|
||||
@@ -501,11 +505,10 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
// if history on this bean type add it's alias
|
||||
// for each alias we add an effect date predicate
|
||||
if (desc.isHistorySupport()) {
|
||||
query.addAsOfTableAlias(baseTableAlias);
|
||||
query.incrementAsOfTableCount();
|
||||
}
|
||||
if (intersectionAsOfTableAlias != null) {
|
||||
// adds the 'as of' predicate for this intersection table
|
||||
query.addAsOfTableAlias(intersectionAsOfTableAlias);
|
||||
if (intersectionAsOfTableAlias) {
|
||||
query.incrementAsOfTableCount();
|
||||
}
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
children[i].addAsOfTableAlias(query);
|
||||
@@ -531,7 +534,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
TableJoin manyToManyJoin = manyProp.getIntersectionTableJoin();
|
||||
manyToManyJoin.addJoin(joinType, parentAlias, alias2, ctx);
|
||||
if (!manyProp.isExcludedFromHistory()) {
|
||||
intersectionAsOfTableAlias = alias2;
|
||||
intersectionAsOfTableAlias = true;
|
||||
}
|
||||
|
||||
return nodeBeanProp.addJoin(joinType, alias2, alias, ctx);
|
||||
|
||||
@@ -38,6 +38,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
public static final String DEFAULT_QUERY_NAME = "default";
|
||||
|
||||
private final Class<T> beanType;
|
||||
|
||||
private final BeanDescriptor<T> beanDescriptor;
|
||||
@@ -144,10 +146,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private DefaultExpressionList<T> havingExpressions;
|
||||
|
||||
/**
|
||||
* The list of table alias associated with @History entity beans.
|
||||
*/
|
||||
private List<String> asOfTableAlias;
|
||||
private int asOfTableCount;
|
||||
|
||||
/**
|
||||
* Set for flashback style 'as of' query.
|
||||
@@ -281,21 +280,14 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return softDeletePredicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* This table alias is for a @History entity involved in the query and as
|
||||
* such we need to add a 'as of predicate' to the query using this alias.
|
||||
*/
|
||||
@Override
|
||||
public void addAsOfTableAlias(String tableAlias) {
|
||||
if (asOfTableAlias == null) {
|
||||
asOfTableAlias = new ArrayList<String>();
|
||||
}
|
||||
asOfTableAlias.add(tableAlias);
|
||||
public void incrementAsOfTableCount() {
|
||||
asOfTableCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAsOfTableAlias() {
|
||||
return asOfTableAlias;
|
||||
public int getAsOfTableCount() {
|
||||
return asOfTableCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -709,6 +701,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return forUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultRawSqlIfRequired() {
|
||||
if (beanDescriptor.isRawSqlBased() && rawSql == null) {
|
||||
rawSql = beanDescriptor.getNamedRawSql(DEFAULT_QUERY_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> setAutoTune(boolean autoTune) {
|
||||
this.autoTune = autoTune;
|
||||
@@ -1171,7 +1170,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> order(String orderByClause) {
|
||||
if (orderByClause == null || orderByClause.trim().length() == 0) {
|
||||
if (orderByClause == null || orderByClause.trim().isEmpty()) {
|
||||
this.orderBy = null;
|
||||
} else {
|
||||
this.orderBy = new OrderBy<T>(this, orderByClause);
|
||||
@@ -1376,6 +1375,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
this.generatedSql = generatedSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFetchBuffer(int fetchSize) {
|
||||
if (bufferFetchSizeHint == 0) {
|
||||
bufferFetchSizeHint = fetchSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setBufferFetchSizeHint(int bufferFetchSizeHint) {
|
||||
this.bufferFetchSizeHint = bufferFetchSizeHint;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class OrmQueryDetailParser {
|
||||
}
|
||||
}
|
||||
String whereClause = sb.toString().trim();
|
||||
if (whereClause.length() > 0) {
|
||||
if (!whereClause.isEmpty()) {
|
||||
rawWhereClause = whereClause;
|
||||
}
|
||||
|
||||
@@ -146,11 +146,10 @@ public class OrmQueryDetailParser {
|
||||
}
|
||||
|
||||
private void readSelect() {
|
||||
String path = null;
|
||||
String props = parser.nextWord();
|
||||
if (props.startsWith("(")) {
|
||||
props = props.substring(1, props.length() - 1);
|
||||
OrmQueryProperties base = new OrmQueryProperties(path, props);
|
||||
OrmQueryProperties base = new OrmQueryProperties(null, props);
|
||||
detail.setBase(base);
|
||||
parser.nextWord();
|
||||
} else {
|
||||
|
||||
@@ -236,7 +236,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configureBeanQuery(SpiQuery<?> query) {
|
||||
|
||||
if (trimmedProperties != null && trimmedProperties.length() > 0) {
|
||||
if (trimmedProperties != null && !trimmedProperties.isEmpty()) {
|
||||
query.select(trimmedProperties);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ public class OrmQueryPropertiesParser {
|
||||
String temp;
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
temp = res[i].trim();
|
||||
if (temp.length() > 0) {
|
||||
if (!temp.isEmpty()) {
|
||||
if (count > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ public class OrmUpdateProperties {
|
||||
@Override
|
||||
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
||||
binder.bindObject(dataBind, value);
|
||||
dataBind.append(value).append(",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +106,7 @@ public class OrmUpdateProperties {
|
||||
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
||||
for (Object val : bindValues) {
|
||||
binder.bindObject(dataBind, val);
|
||||
dataBind.append(val).append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class TCsvReader<T> implements CsvReader<T> {
|
||||
|
||||
strValue = strValue.trim();
|
||||
|
||||
if (strValue.length() == 0) {
|
||||
if (strValue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -402,12 +402,7 @@ public class TransactionManager {
|
||||
public void notifyOfCommit(SpiTransaction transaction) {
|
||||
|
||||
try {
|
||||
|
||||
if (transaction.isExplicit()) {
|
||||
if (TXN_LOGGER.isInfoEnabled()) {
|
||||
TXN_LOGGER.info(transaction.getLogPrefix() + "Commit");
|
||||
}
|
||||
} else if (TXN_LOGGER.isDebugEnabled()) {
|
||||
if (TXN_LOGGER.isDebugEnabled()) {
|
||||
TXN_LOGGER.debug(transaction.getLogPrefix() + "Commit");
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.dbmigration.DbOffline;
|
||||
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutable;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
|
||||
@@ -156,6 +157,8 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
|
||||
private final boolean postgres;
|
||||
|
||||
private final boolean offlineMigrationGeneration;
|
||||
|
||||
// OPTIONAL ScalarTypes registered if Jackson/JsonNode is in the classpath
|
||||
|
||||
/**
|
||||
@@ -198,6 +201,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
|
||||
this.extraTypeFactory = new DefaultTypeFactory(config);
|
||||
this.postgres = isPostgres(config.getDatabasePlatform());
|
||||
this.offlineMigrationGeneration = DbOffline.isGenerateMigration();
|
||||
|
||||
initialiseStandard(jsonDateTime, config);
|
||||
initialiseJavaTimeTypes(jsonDateTime, config);
|
||||
@@ -961,15 +965,13 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
nativeMap.put(Types.BIT, booleanType);
|
||||
}
|
||||
|
||||
boolean nativeUuidType = databasePlatform.isNativeUuidType();
|
||||
ServerConfig.DbUuid dbUuid = config.getDbUuid();
|
||||
|
||||
if (nativeUuidType && dbUuid == ServerConfig.DbUuid.AUTO) {
|
||||
// DB has native support for UUID
|
||||
if (offlineMigrationGeneration || (databasePlatform.isNativeUuidType() && dbUuid.useNativeType())) {
|
||||
typeMap.put(UUID.class, new ScalarTypeUUIDNative());
|
||||
} else {
|
||||
// Store UUID as binary(16) or varchar(40)
|
||||
ScalarType<?> uuidType = (ServerConfig.DbUuid.BINARY == dbUuid) ? new ScalarTypeUUIDBinary() : new ScalarTypeUUIDVarchar();
|
||||
ScalarType<?> uuidType = dbUuid.useBinary() ? new ScalarTypeUUIDBinary() : new ScalarTypeUUIDVarchar();
|
||||
typeMap.put(UUID.class, uuidType);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ScalarTypeChar extends ScalarTypeBaseVarchar<Character> {
|
||||
|
||||
public Character read(DataReader dataReader) throws SQLException {
|
||||
String string = dataReader.getString();
|
||||
if (string == null || string.length() == 0) {
|
||||
if (string == null || string.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return string.charAt(0);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
/**
|
||||
* Marks types that can be mapped differently to different DB platforms.
|
||||
*/
|
||||
public interface ScalarTypeLogicalType {
|
||||
|
||||
/**
|
||||
* Return the DB agnostic logical type.
|
||||
*/
|
||||
int getLogicalType();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -13,12 +14,17 @@ import java.util.UUID;
|
||||
/**
|
||||
* Base UUID type for string formatting, json handling etc.
|
||||
*/
|
||||
public abstract class ScalarTypeUUIDBase extends ScalarTypeBase<UUID> {
|
||||
public abstract class ScalarTypeUUIDBase extends ScalarTypeBase<UUID> implements ScalarTypeLogicalType {
|
||||
|
||||
public ScalarTypeUUIDBase(boolean jdbcNative, int jdbcType) {
|
||||
super(UUID.class, jdbcNative, jdbcType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLogicalType() {
|
||||
return DbType.UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user