mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
67
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
861a8a4ee5 | ||
|
|
abe2f76d5c | ||
|
|
d0f75a940c | ||
|
|
44ad78b5e0 | ||
|
|
967b4de784 | ||
|
|
ea45201905 | ||
|
|
938f4ec9c2 | ||
|
|
99bd2972d0 | ||
|
|
deac291951 | ||
|
|
3161e24677 | ||
|
|
37804bd083 | ||
|
|
0a2a987695 | ||
|
|
4a085cb819 | ||
|
|
67469ef4d3 | ||
|
|
c3f43d503f | ||
|
|
9158f46bb3 | ||
|
|
b3bfa88eb5 | ||
|
|
185dec9c02 | ||
|
|
20634233ca | ||
|
|
7c9dda586e | ||
|
|
3ca0f7b776 | ||
|
|
85caca48de | ||
|
|
ff85a51994 | ||
|
|
6dc3038d0d | ||
|
|
c0fcb77f3d | ||
|
|
da5d5296b6 | ||
|
|
f04ab28c3f | ||
|
|
d6cd41f8d2 | ||
|
|
504a209a78 | ||
|
|
9f98b5333d | ||
|
|
2a600adbcf | ||
|
|
9ce6007330 | ||
|
|
7780dd6272 | ||
|
|
b01ddea781 | ||
|
|
b848587cd3 | ||
|
|
fe7e929a99 | ||
|
|
3ee0b0224e | ||
|
|
169eba4296 | ||
|
|
91d3279061 | ||
|
|
b4b7c631da | ||
|
|
4f98ca5d91 | ||
|
|
014a9aef6f | ||
|
|
f21c33df7b | ||
|
|
f1eb494e0d | ||
|
|
d26203db1f | ||
|
|
abfe58fb06 | ||
|
|
d0ad5f6c48 | ||
|
|
bc4a246f33 | ||
|
|
61f590944b | ||
|
|
223e53416d | ||
|
|
a3143b1cf6 | ||
|
|
bd3e7c8035 | ||
|
|
b753ce3a73 | ||
|
|
a0f2ebe448 | ||
|
|
7e7810602e | ||
|
|
d218fff374 | ||
|
|
a0e927d353 | ||
|
|
51a58d4993 | ||
|
|
b9f0ee7ac0 | ||
|
|
4f3b461f8e | ||
|
|
adfe5f0305 | ||
|
|
1796c8b9bc | ||
|
|
4bad4358f0 | ||
|
|
92665ebc3b | ||
|
|
59670d0303 | ||
|
|
244275fd72 | ||
|
|
d1e2176a5a |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>8.2.2</version>
|
||||
<version>8.6.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:https://github.com/ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-8.2.2</tag>
|
||||
<tag>ebean-8.6.1</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -167,8 +167,9 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Create a new instance of T that is an EntityBean.
|
||||
* <p>
|
||||
* Generally not expected to be useful (now dynamic subclassing support was removed in
|
||||
* favour of always using enhancement).
|
||||
* Useful if you use BeanPostConstructListeners or @PostConstruct Annotations.
|
||||
* In this case you should not use "new Bean...()". Making all bean construtors protected
|
||||
* could be a good idea here.
|
||||
* </p>
|
||||
*/
|
||||
<T> T createEntityBean(Class<T> type);
|
||||
@@ -746,14 +747,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> int findCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findCount()
|
||||
*
|
||||
* Return the number of 'top level' or 'root' entities this query should return.
|
||||
* @deprecated
|
||||
*/
|
||||
<T> int findRowCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the Id values of the query as a List.
|
||||
*
|
||||
@@ -892,18 +885,10 @@ public interface EbeanServer {
|
||||
* @param query the query to execute the row count on
|
||||
* @param transaction the transaction (can be null).
|
||||
* @return a Future object for the row count query
|
||||
* @see com.avaje.ebean.Query#findFutureRowCount()
|
||||
* @see com.avaje.ebean.Query#findFutureCount()
|
||||
*/
|
||||
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findFutureCount().
|
||||
*
|
||||
* Execute find row count query in a background thread.
|
||||
* @deprecated
|
||||
*/
|
||||
<T> FutureRowCount<T> findFutureRowCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
|
||||
@@ -185,13 +185,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
int findRowCount();
|
||||
|
||||
/**
|
||||
* Execute the query returning a set.
|
||||
*
|
||||
@@ -265,13 +258,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findFutureCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
FutureRowCount<T> findFutureRowCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
|
||||
@@ -44,30 +44,6 @@ import java.util.concurrent.Future;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: typical use including total row count</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // We want to find the first 100 new orders
|
||||
* // ... 0 means first page
|
||||
* // ... page size is 100
|
||||
*
|
||||
* PagedList<Order> pagedList
|
||||
* = ebeanServer.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .findPagedList(0, 100);
|
||||
*
|
||||
* // Optional: initiate the loading of the total
|
||||
* // row count in a background thread
|
||||
* pagedList.loadRowCount();
|
||||
*
|
||||
* // fetch and return the list in the foreground thread
|
||||
* List<Order> orders = pagedList.getList();
|
||||
*
|
||||
* // get the total row count (from the future)
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: No total row count required</h4>
|
||||
* <pre>{@code
|
||||
@@ -112,13 +88,6 @@ public interface PagedList<T> {
|
||||
*/
|
||||
void loadCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of loadCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void loadRowCount();
|
||||
|
||||
/**
|
||||
* Return the Future row count. You might get this if you wish to cancel the total row count query
|
||||
* or specify a timeout for the row count query.
|
||||
@@ -147,13 +116,6 @@ public interface PagedList<T> {
|
||||
*/
|
||||
Future<Integer> getFutureCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of getFutureCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
Future<Integer> getFutureRowCount();
|
||||
|
||||
/**
|
||||
* Return the list of entities for this page.
|
||||
*/
|
||||
@@ -186,13 +148,6 @@ public interface PagedList<T> {
|
||||
*/
|
||||
int getTotalCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of getTotalCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
int getTotalRowCount();
|
||||
|
||||
/**
|
||||
* Return the total number of pages based on the page size and total row count.
|
||||
* <p>
|
||||
@@ -207,6 +162,14 @@ public interface PagedList<T> {
|
||||
*/
|
||||
int getPageSize();
|
||||
|
||||
/**
|
||||
* Return the index position of this page (Zero based).
|
||||
* <p>
|
||||
* This is a calculated value based on firstRow/maxRows.
|
||||
* </p>
|
||||
*/
|
||||
int getPageIndex();
|
||||
|
||||
/**
|
||||
* Return true if there is a next page.
|
||||
* <p>
|
||||
|
||||
@@ -845,15 +845,6 @@ public interface Query<T> {
|
||||
*/
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findCount().
|
||||
* <p>
|
||||
* Return the count of entities this query should return.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
int findRowCount();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
@@ -866,21 +857,6 @@ public interface Query<T> {
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findFutureCount().
|
||||
* <p>
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
* @deprecated
|
||||
*/
|
||||
FutureRowCount<T> findFutureRowCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
|
||||
@@ -57,7 +57,7 @@ package com.avaje.ebean;
|
||||
* where id in (
|
||||
* select t0.id c0
|
||||
* from o_customer t0
|
||||
* left outer join o_address t1 on t1.id = t0.billing_address_id
|
||||
* left join o_address t1 on t1.id = t0.billing_address_id
|
||||
* where t0.status = ?
|
||||
* and t1.country_code = ?
|
||||
* and t0.id > ? )
|
||||
|
||||
@@ -82,7 +82,7 @@ public @interface Formula {
|
||||
* as count, sum etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* The join string should start with either "left outer join" or "join".
|
||||
* The join string should start with either "left join" or "join".
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ClassLoadConfig {
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
protected boolean isPresent(String className) {
|
||||
public boolean isPresent(String className) {
|
||||
try {
|
||||
forName(className);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
|
||||
/**
|
||||
* Custom mappings for DB types that override the default.
|
||||
*
|
||||
* @see ServerConfig#addCustomMapping(DbType, String)
|
||||
*/
|
||||
public class CustomDbTypeMapping {
|
||||
|
||||
protected final DbType type;
|
||||
|
||||
protected final String columnDefinition;
|
||||
|
||||
protected final Platform platform;
|
||||
|
||||
/**
|
||||
* Create a mapping.
|
||||
*/
|
||||
public CustomDbTypeMapping(DbType type, String columnDefinition, Platform platform) {
|
||||
this.type = type;
|
||||
this.columnDefinition = columnDefinition;
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a mapping that should apply to all the database platforms.
|
||||
*/
|
||||
public CustomDbTypeMapping(DbType type, String columnDefinition) {
|
||||
this(type, columnDefinition, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB type the mapping applies to.
|
||||
*/
|
||||
public DbType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB column definition to use.
|
||||
*/
|
||||
public String getColumnDefinition() {
|
||||
return columnDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform this mapping should apply to. Null means it applied to all platforms.
|
||||
*/
|
||||
public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformName;
|
||||
import com.avaje.ebean.dbmigration.DbMigration;
|
||||
import org.avaje.dbmigration.MigrationConfig;
|
||||
import org.avaje.dbmigration.MigrationRunner;
|
||||
@@ -20,7 +19,7 @@ public class DbMigrationConfig {
|
||||
/**
|
||||
* The database platform to generate migration DDL for.
|
||||
*/
|
||||
protected DbPlatformName platform;
|
||||
protected Platform platform;
|
||||
|
||||
/**
|
||||
* Set to true if the DB migration should be generated on server start.
|
||||
@@ -112,14 +111,14 @@ public class DbMigrationConfig {
|
||||
* We typically need to explicitly specify this as migration can often be generated
|
||||
* when running against H2.
|
||||
*/
|
||||
public DbPlatformName getPlatform() {
|
||||
public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB platform to generate migration DDL for.
|
||||
*/
|
||||
public void setPlatform(DbPlatformName platform) {
|
||||
public void setPlatform(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
@@ -366,7 +365,7 @@ public class DbMigrationConfig {
|
||||
includeGeneratedFileComment = properties.getBoolean("migration.includeGeneratedFileComment", includeGeneratedFileComment);
|
||||
generatePendingDrop = properties.get("migration.generatePendingDrop", generatePendingDrop);
|
||||
|
||||
platform = properties.getEnum(DbPlatformName.class, "migration.platform", platform);
|
||||
platform = properties.getEnum(Platform.class, "migration.platform", platform);
|
||||
|
||||
generate = properties.getBoolean("migration.generate", generate);
|
||||
version = properties.get("migration.version", version);
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Built in supported platforms.
|
||||
*/
|
||||
public enum DbPlatformName {
|
||||
public enum Platform {
|
||||
|
||||
/**
|
||||
* Generic base platform configured via properties or code.
|
||||
@@ -7,9 +7,11 @@ import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.cache.ServerCachePlugin;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncrypt;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.BulkTableEventListener;
|
||||
@@ -83,6 +85,8 @@ public class ServerConfig {
|
||||
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
private List<CustomDbTypeMapping> customDbTypeMappings = new ArrayList<CustomDbTypeMapping>();
|
||||
|
||||
/**
|
||||
* The underlying properties that were used during configuration.
|
||||
*/
|
||||
@@ -108,6 +112,11 @@ public class ServerConfig {
|
||||
*/
|
||||
private boolean disableClasspathSearch;
|
||||
|
||||
/**
|
||||
* The Geometry SRID value (default 4326).
|
||||
*/
|
||||
private int geometrySRID = 4326;
|
||||
|
||||
/**
|
||||
* List of interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers etc.
|
||||
@@ -326,6 +335,7 @@ public class ServerConfig {
|
||||
private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
|
||||
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
|
||||
private List<BeanPostLoad> postLoaders = new ArrayList<BeanPostLoad>();
|
||||
private List<BeanPostConstructListener> postConstructListeners = new ArrayList<BeanPostConstructListener>();
|
||||
private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
|
||||
private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
|
||||
private List<BulkTableEventListener> bulkTableEventListeners = new ArrayList<BulkTableEventListener>();
|
||||
@@ -871,6 +881,20 @@ public class ServerConfig {
|
||||
this.migrationConfig = migrationConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Geometry SRID.
|
||||
*/
|
||||
public int getGeometrySRID() {
|
||||
return geometrySRID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Geometry SRID.
|
||||
*/
|
||||
public void setGeometrySRID(int geometrySRID) {
|
||||
this.geometrySRID = geometrySRID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time zone to use when reading/writing Timestamps via JDBC.
|
||||
* <p>
|
||||
@@ -1437,7 +1461,7 @@ public class ServerConfig {
|
||||
* <p>
|
||||
* You can also set this in ebean.proprerties:
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* # set via ebean.properties
|
||||
* ebean.encryptKeyManager=com.avaje.tests.basic.encrypt.BasicEncyptKeyManager
|
||||
@@ -1770,7 +1794,7 @@ public class ServerConfig {
|
||||
* queries that normally hit L2 bean cache automatically will not do so after a write/persist
|
||||
* on the transaction.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // assume Customer has L2 bean caching enabled ...
|
||||
@@ -1932,6 +1956,54 @@ public class ServerConfig {
|
||||
this.resourceDirectory = resourceDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom type mapping.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // set the default mapping for BigDecimal.class/decimal
|
||||
* serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
|
||||
*
|
||||
* // set the default mapping for String.class/varchar but only for Postgres
|
||||
* serverConfig.addCustomMapping(DbType.VARCHAR, "text", Platform.POSTGRES);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param type The DB type this mapping should apply to
|
||||
* @param columnDefinition The column definition that should be used
|
||||
* @param platform Optionally specify the platform this mapping should apply to.
|
||||
*/
|
||||
public void addCustomMapping(DbType type, String columnDefinition, Platform platform) {
|
||||
customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition, platform));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a custom type mapping that applies to all platforms.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // set the default mapping for BigDecimal/decimal
|
||||
* serverConfig.addCustomMapping(DbType.DECIMAL, "decimal(18,6)");
|
||||
*
|
||||
* // set the default mapping for String/varchar
|
||||
* serverConfig.addCustomMapping(DbType.VARCHAR, "text");
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param type The DB type this mapping should apply to
|
||||
* @param columnDefinition The column definition that should be used
|
||||
*/
|
||||
public void addCustomMapping(DbType type, String columnDefinition) {
|
||||
customDbTypeMappings.add(new CustomDbTypeMapping(type, columnDefinition));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of custom type mappings.
|
||||
*/
|
||||
public List<CustomDbTypeMapping> getCustomTypeMappings() {
|
||||
return customDbTypeMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a BeanQueryAdapter instance.
|
||||
* <p>
|
||||
@@ -2004,6 +2076,16 @@ public class ServerConfig {
|
||||
postLoaders.add(postLoad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a BeanPostConstructListener instance.
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPostConstructListeners(List)} to set
|
||||
* all the BeanPostConstructListener instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPostConstructListener listener) {
|
||||
postConstructListeners.add(listener);
|
||||
}
|
||||
/**
|
||||
* Return the list of BeanFindController instances.
|
||||
*/
|
||||
@@ -2032,6 +2114,19 @@ public class ServerConfig {
|
||||
this.postLoaders = postLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanPostLoader instances.
|
||||
*/
|
||||
public List<BeanPostConstructListener> getPostConstructListeners() {
|
||||
return postConstructListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of BeanPostLoader instances.
|
||||
*/
|
||||
public void setPostConstructListeners(List<BeanPostConstructListener> listeners) {
|
||||
this.postConstructListeners = listeners;
|
||||
}
|
||||
/**
|
||||
* Return the BeanPersistController instances.
|
||||
*/
|
||||
@@ -2287,6 +2382,7 @@ public class ServerConfig {
|
||||
}
|
||||
loadDocStoreSettings(p);
|
||||
|
||||
geometrySRID = p.getInt("geometrySRID", geometrySRID);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
explicitTransactionBeginMode = p.getBoolean("explicitTransactionBeginMode", explicitTransactionBeginMode);
|
||||
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
|
||||
|
||||
@@ -24,9 +24,9 @@ public class DB2Platform extends DatabasePlatform {
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
|
||||
booleanDbType = Types.BOOLEAN;
|
||||
dbTypeMap.put(Types.REAL, new DbType("real"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 15));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("real"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 15));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.config.CustomDbTypeMapping;
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
import com.avaje.ebean.config.Platform;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
|
||||
@@ -73,7 +75,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Mapping of JDBC to Database types.
|
||||
*/
|
||||
protected DbTypeMap dbTypeMap = new DbTypeMap();
|
||||
protected DbPlatformTypeMapping dbTypeMap = new DbPlatformTypeMapping();
|
||||
|
||||
/**
|
||||
* Default values for DB columns.
|
||||
@@ -180,6 +182,19 @@ public class DatabasePlatform {
|
||||
*/
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
dbTypeMap.config(nativeUuidType, serverConfig.getDbUuid());
|
||||
for (CustomDbTypeMapping mapping : serverConfig.getCustomTypeMappings()) {
|
||||
if (platformMatch(mapping.getPlatform())) {
|
||||
dbTypeMap.put(mapping.getType(), parse(mapping.getColumnDefinition()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DbPlatformType parse(String columnDefinition) {
|
||||
return DbPlatformType.parse(columnDefinition);
|
||||
}
|
||||
|
||||
private boolean platformMatch(Platform platform) {
|
||||
return platform == null || platform.name().equalsIgnoreCase(name);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -309,7 +324,7 @@ public class DatabasePlatform {
|
||||
*
|
||||
* @return the db type map
|
||||
*/
|
||||
public DbTypeMap getDbTypeMap() {
|
||||
public DbPlatformTypeMapping getDbTypeMap() {
|
||||
return dbTypeMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
/**
|
||||
* Represents a DB type with name, length, precision, and scale.
|
||||
* <p>
|
||||
* The length is for VARCHAR types and precision/scale for DECIMAL types.
|
||||
* </p>
|
||||
*/
|
||||
public class DbPlatformType implements ExtraDbTypes {
|
||||
|
||||
/**
|
||||
* The data type name (VARCHAR, INTEGER ...)
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The default length or precision.
|
||||
*/
|
||||
private final int defaultLength;
|
||||
|
||||
/**
|
||||
* The default scale (decimal).
|
||||
*/
|
||||
private final int defaultScale;
|
||||
|
||||
/**
|
||||
* Set to true if the type should never have a length or scale.
|
||||
*/
|
||||
private final boolean canHaveLength;
|
||||
|
||||
/**
|
||||
* Parse a type definition into a DbPlatformType.
|
||||
* <p>
|
||||
* e.g. "decimal(18,6)"
|
||||
* e.g. "text"
|
||||
* </p>
|
||||
*/
|
||||
public static DbPlatformType parse(String columnDefinition) {
|
||||
return DbPlatformTypeParser.parse(columnDefinition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with no length or scale.
|
||||
*/
|
||||
public DbPlatformType(String name) {
|
||||
this(name, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with a given length.
|
||||
*/
|
||||
public DbPlatformType(String name, int defaultLength) {
|
||||
this(name, defaultLength, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for Decimal with precision and scale.
|
||||
*/
|
||||
public DbPlatformType(String name, int defaultPrecision, int defaultScale) {
|
||||
this.name = name;
|
||||
this.defaultLength = defaultPrecision;
|
||||
this.defaultScale = defaultScale;
|
||||
this.canHaveLength = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use with canHaveLength=false for types that should never have a length.
|
||||
*
|
||||
* @param name
|
||||
* the type name
|
||||
* @param canHaveLength
|
||||
* set this to false for type that should never have a length
|
||||
*/
|
||||
public DbPlatformType(String name, boolean canHaveLength) {
|
||||
this.name = name;
|
||||
this.defaultLength = 0;
|
||||
this.defaultScale = 0;
|
||||
this.canHaveLength = canHaveLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type name.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default length/precision.
|
||||
*/
|
||||
public int getDefaultLength() {
|
||||
return defaultLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default scale.
|
||||
*/
|
||||
public int getDefaultScale() {
|
||||
return defaultScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for a specific property that incorporates the name, length,
|
||||
* precision and scale.
|
||||
* <p>
|
||||
* The deployLength and deployScale are for the property we are rendering the
|
||||
* DB type for.
|
||||
* </p>
|
||||
*
|
||||
* @param deployLength
|
||||
* the length or precision defined by deployment on a specific
|
||||
* property.
|
||||
* @param deployScale
|
||||
* the scale defined by deployment on a specific property.
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale) {
|
||||
return renderType(deployLength, deployScale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the type defining strict mode.
|
||||
* <p>
|
||||
* If strict mode if OFF then this will render with a scale value even if
|
||||
* that is not strictly supported. The reason for supporting this is to enable
|
||||
* use to use types like jsonb(200) as a "logical" type that maps to JSONB for
|
||||
* Postgres and VARCHAR(200) for other databases.
|
||||
* </p>
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale, boolean strict) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
|
||||
if (canHaveLength || !strict) {
|
||||
// see if there is a precision/scale to add (or not)
|
||||
int len = deployLength != 0 ? deployLength : defaultLength;
|
||||
if (len > 0) {
|
||||
sb.append("(");
|
||||
sb.append(len);
|
||||
int scale = deployScale != 0 ? deployScale : defaultScale;
|
||||
if (scale > 0) {
|
||||
sb.append(",");
|
||||
sb.append(scale);
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the type with a new default length.
|
||||
*/
|
||||
public DbPlatformType withLength(int defaultLength) {
|
||||
return new DbPlatformType(name, defaultLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper to reverse lookup a DbType given the name or JDBC int value.
|
||||
*/
|
||||
class DbPlatformTypeLookup {
|
||||
|
||||
/**
|
||||
* A map to lookup the type by name.
|
||||
*/
|
||||
private Map<String, DbType> nameLookup = new HashMap<String, DbType>();
|
||||
|
||||
/**
|
||||
* A map to lookup the type by JDBC int value.
|
||||
*/
|
||||
private Map<Integer, DbType> idLookup = new HashMap<Integer, DbType>();
|
||||
|
||||
DbPlatformTypeLookup() {
|
||||
addAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DbType for the given name.
|
||||
*/
|
||||
DbType byName(String name) {
|
||||
return nameLookup.get(name.trim().toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DbType for the given name.
|
||||
*/
|
||||
DbType byId(int jdbcId) {
|
||||
return idLookup.get(jdbcId);
|
||||
}
|
||||
|
||||
private void addAll() {
|
||||
// Extra mapping for Float and Varchar2
|
||||
add("FLOAT", DbType.REAL);
|
||||
add("VARCHAR2", DbType.VARCHAR);
|
||||
for (DbType type : DbType.values()) {
|
||||
add(type.name(), type);
|
||||
}
|
||||
}
|
||||
|
||||
private void add(String name, DbType dbType) {
|
||||
nameLookup.put(name, dbType);
|
||||
idLookup.put(dbType.id(), dbType);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used to map bean property types to DB specific types for DDL generation.
|
||||
*/
|
||||
public class DbPlatformTypeMapping {
|
||||
|
||||
private static DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
|
||||
|
||||
private static final DbPlatformType UUID_NATIVE = new DbPlatformType("uuid", false);
|
||||
private static final DbPlatformType UUID_PLACEHOLDER = new DbPlatformType("uuidPlaceholder");
|
||||
private static final DbPlatformType JSON_CLOB_PLACEHOLDER = new DbPlatformType("jsonClobPlaceholder");
|
||||
private static final DbPlatformType JSON_BLOB_PLACEHOLDER = new DbPlatformType("jsonBlobPlaceholder");
|
||||
private static final DbPlatformType JSON_VARCHAR_PLACEHOLDER = new DbPlatformType("jsonVarcharPlaceholder");
|
||||
|
||||
private static final DbPlatformType POINT = new DbPlatformType("point");
|
||||
private static final DbPlatformType POLYGON = new DbPlatformType("polygon");
|
||||
private static final DbPlatformType LINESTRING = new DbPlatformType("linestring");
|
||||
private static final DbPlatformType MULTIPOINT = new DbPlatformType("multipoint");
|
||||
private static final DbPlatformType MULTILINESTRING = new DbPlatformType("multilinestring");
|
||||
private static final DbPlatformType MULTIPOLYGON = new DbPlatformType("multipolygon");
|
||||
|
||||
private final Map<DbType, DbPlatformType> typeMap = new HashMap<DbType, DbPlatformType>();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static DbPlatformTypeMapping logicalTypes() {
|
||||
return new DbPlatformTypeMapping(true);
|
||||
}
|
||||
|
||||
public DbPlatformTypeMapping() {
|
||||
loadDefaults(false);
|
||||
}
|
||||
|
||||
private DbPlatformTypeMapping(boolean logicalTypes) {
|
||||
loadDefaults(logicalTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the standard types. These can be overridden by DB specific platform.
|
||||
*/
|
||||
private void loadDefaults(boolean logicalTypes) {
|
||||
|
||||
put(DbType.BOOLEAN);
|
||||
put(DbType.BIT);
|
||||
put(DbType.INTEGER);
|
||||
put(DbType.BIGINT);
|
||||
put(DbType.DOUBLE);
|
||||
put(DbType.SMALLINT);
|
||||
put(DbType.TINYINT);
|
||||
put(DbType.BLOB);
|
||||
put(DbType.CLOB);
|
||||
put(DbType.ARRAY);
|
||||
put(DbType.DATE);
|
||||
put(DbType.TIME);
|
||||
put(DbType.TIMESTAMP);
|
||||
put(DbType.LONGVARBINARY);
|
||||
put(DbType.LONGVARCHAR);
|
||||
// most commonly real maps to db float
|
||||
put(DbType.REAL, new DbPlatformType("float"));
|
||||
|
||||
put(DbType.POINT, POINT);
|
||||
put(DbType.POLYGON, POLYGON);
|
||||
put(DbType.LINESTRING, LINESTRING);
|
||||
put(DbType.MULTIPOINT, MULTIPOINT);
|
||||
put(DbType.MULTILINESTRING, MULTILINESTRING);
|
||||
put(DbType.MULTIPOLYGON, MULTIPOLYGON);
|
||||
|
||||
if (logicalTypes) {
|
||||
// keep it logical for 2 layer DDL generation
|
||||
put(DbType.VARCHAR, new DbPlatformType("varchar"));
|
||||
put(DbType.DECIMAL, new DbPlatformType("decimal"));
|
||||
put(DbType.VARBINARY, new DbPlatformType("varbinary"));
|
||||
put(DbType.BINARY, new DbPlatformType("binary"));
|
||||
put(DbType.CHAR, new DbPlatformType("char"));
|
||||
|
||||
put(DbType.HSTORE, new DbPlatformType("hstore", false));
|
||||
put(DbType.JSON, new DbPlatformType("json", false));
|
||||
put(DbType.JSONB, new DbPlatformType("jsonb", false));
|
||||
put(DbType.JSONCLOB, new DbPlatformType("jsonclob"));
|
||||
put(DbType.JSONBLOB, new DbPlatformType("jsonblob"));
|
||||
put(DbType.JSONVARCHAR, new DbPlatformType("jsonvarchar", 1000));
|
||||
put(DbType.UUID, UUID_NATIVE);
|
||||
|
||||
} else {
|
||||
put(DbType.VARCHAR, new DbPlatformType("varchar", 255));
|
||||
put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
|
||||
put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
|
||||
put(DbType.BINARY, new DbPlatformType("binary", 255));
|
||||
put(DbType.CHAR, new DbPlatformType("char", 1));
|
||||
|
||||
put(DbType.JSON, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSON
|
||||
put(DbType.JSONB, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSONB
|
||||
put(DbType.JSONCLOB, JSON_CLOB_PLACEHOLDER);
|
||||
put(DbType.JSONBLOB, JSON_BLOB_PLACEHOLDER);
|
||||
put(DbType.JSONVARCHAR, JSON_VARCHAR_PLACEHOLDER);
|
||||
put(DbType.UUID, UUID_PLACEHOLDER);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the platform specific DbType given the standard sql type name.
|
||||
*/
|
||||
public DbPlatformType lookup(String name, boolean withScale) {
|
||||
|
||||
DbType type = lookup.byName(name);
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("Unknown type [" + name + "] - not standard sql type");
|
||||
}
|
||||
// handle JSON types mapped to clob, blob and varchar
|
||||
switch (type) {
|
||||
case JSONBLOB:
|
||||
return get(DbType.BLOB);
|
||||
case JSONCLOB:
|
||||
return get(DbType.CLOB);
|
||||
case JSONVARCHAR:
|
||||
return get(DbType.VARCHAR);
|
||||
case JSON:
|
||||
return getJsonType(DbType.JSON, withScale);
|
||||
case JSONB:
|
||||
return getJsonType(DbType.JSONB, withScale);
|
||||
default:
|
||||
return get(type);
|
||||
}
|
||||
}
|
||||
|
||||
private DbPlatformType getJsonType(DbType type, boolean withScale) {
|
||||
|
||||
DbPlatformType dbType = get(type);
|
||||
if (dbType == JSON_CLOB_PLACEHOLDER) {
|
||||
// if we have scale that implies this maps to varchar
|
||||
return withScale ? get(DbType.VARCHAR) : get(DbType.CLOB);
|
||||
}
|
||||
if (dbType == JSON_BLOB_PLACEHOLDER) {
|
||||
return get(DbType.BLOB);
|
||||
}
|
||||
if (dbType == JSON_VARCHAR_PLACEHOLDER) {
|
||||
return get(DbType.VARCHAR);
|
||||
}
|
||||
// Postgres has specific type
|
||||
return get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the type for a given JDBC type.
|
||||
*/
|
||||
private void put(DbType type) {
|
||||
typeMap.put(type, type.createPlatformType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the type for a given JDBC type.
|
||||
*/
|
||||
public void put(DbType type, DbPlatformType platformType) {
|
||||
typeMap.put(type, platformType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for a given jdbc type.
|
||||
*/
|
||||
public DbPlatformType get(int jdbcType) {
|
||||
return get(lookup.byId(jdbcType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for a given jdbc type.
|
||||
*/
|
||||
public DbPlatformType get(DbType dbType) {
|
||||
return typeMap.get(dbType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(DbType.BINARY).withLength(16));
|
||||
} else {
|
||||
put(DbType.UUID, get(DbType.VARCHAR).withLength(40));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
/**
|
||||
* Parse raw column definitions into DbPlatformType like "decimal(18,6)" and "varchar(20) and "json".
|
||||
*/
|
||||
class DbPlatformTypeParser {
|
||||
|
||||
/**
|
||||
* Parse the column definition and return the DbPlatformType.
|
||||
*/
|
||||
static DbPlatformType parse(String columnDefinition) {
|
||||
|
||||
columnDefinition = columnDefinition.trim();
|
||||
|
||||
int openPos = columnDefinition.indexOf('(');
|
||||
if (openPos == -1) {
|
||||
return new DbPlatformType(columnDefinition, false);
|
||||
}
|
||||
int closePos = columnDefinition.indexOf(')', openPos);
|
||||
if (closePos == -1) {
|
||||
return new DbPlatformType(columnDefinition, false);
|
||||
}
|
||||
try {
|
||||
int commaPos = columnDefinition.indexOf(',', openPos);
|
||||
if (commaPos > -1) {
|
||||
String type = columnDefinition.substring(0, openPos);
|
||||
int scale = Integer.parseInt(columnDefinition.substring(openPos + 1, commaPos));
|
||||
int precision = Integer.parseInt(columnDefinition.substring(commaPos + 1, closePos));
|
||||
return new DbPlatformType(type, scale, precision);
|
||||
|
||||
} else {
|
||||
String type = columnDefinition.substring(0, openPos);
|
||||
int scale = Integer.parseInt(columnDefinition.substring(openPos + 1, closePos));
|
||||
return new DbPlatformType(type, scale);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
return new DbPlatformType(columnDefinition, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +1,72 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Represents a DB type with name, length, precision, and scale.
|
||||
* The known DB types that are mapped.
|
||||
* <p>
|
||||
* The length is for VARCHAR types and precision/scale for DECIMAL types.
|
||||
* This includes extra types such as UUID, JSON, JSONB and HSTORE.
|
||||
* </p>
|
||||
*/
|
||||
public class DbType {
|
||||
public enum DbType {
|
||||
|
||||
/**
|
||||
* DB native UUID type (H2 and Postgres).
|
||||
*/
|
||||
public static final int UUID = 5010;
|
||||
BOOLEAN(Types.BOOLEAN),
|
||||
BIT(Types.BIT),
|
||||
INTEGER(Types.INTEGER),
|
||||
BIGINT(Types.BIGINT),
|
||||
SMALLINT(Types.SMALLINT),
|
||||
TINYINT(Types.TINYINT),
|
||||
REAL(Types.REAL),
|
||||
//FLOAT(Types.FLOAT),
|
||||
DOUBLE(Types.DOUBLE),
|
||||
DECIMAL(Types.DECIMAL),
|
||||
VARCHAR(Types.VARCHAR),
|
||||
CHAR(Types.CHAR),
|
||||
BLOB(Types.BLOB),
|
||||
CLOB(Types.CLOB),
|
||||
LONGVARBINARY(Types.LONGVARBINARY),
|
||||
LONGVARCHAR(Types.LONGVARCHAR),
|
||||
VARBINARY(Types.VARBINARY),
|
||||
BINARY(Types.BINARY),
|
||||
DATE(Types.DATE),
|
||||
TIME(Types.TIME),
|
||||
TIMESTAMP(Types.TIMESTAMP),
|
||||
|
||||
/**
|
||||
* Type to map Map content to Postgres HSTORE.
|
||||
*/
|
||||
public static final int HSTORE = 5000;
|
||||
ARRAY(Types.ARRAY),
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob or Postgres JSON type.
|
||||
*/
|
||||
public static final int JSON = 5001;
|
||||
UUID(ExtraDbTypes.UUID),
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob or Postgres JSONB type.
|
||||
*/
|
||||
public static final int JSONB = 5002;
|
||||
POINT(ExtraDbTypes.POINT),
|
||||
POLYGON(ExtraDbTypes.POLYGON),
|
||||
LINESTRING(ExtraDbTypes.LINESTRING),
|
||||
MULTIPOINT(ExtraDbTypes.MULTIPOINT),
|
||||
MULTILINESTRING(ExtraDbTypes.MULTILINESTRING),
|
||||
MULTIPOLYGON(ExtraDbTypes.MULTIPOLYGON),
|
||||
|
||||
/**
|
||||
* Type to map JSON content to VARCHAR.
|
||||
*/
|
||||
public static final int JSONVarchar = 5003;
|
||||
HSTORE(ExtraDbTypes.HSTORE),
|
||||
JSON(ExtraDbTypes.JSON),
|
||||
JSONB(ExtraDbTypes.JSONB),
|
||||
JSONCLOB(ExtraDbTypes.JSONClob),
|
||||
JSONBLOB(ExtraDbTypes.JSONBlob),
|
||||
JSONVARCHAR(ExtraDbTypes.JSONVarchar);
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob.
|
||||
*/
|
||||
public static final int JSONClob = 5004;
|
||||
private final int id;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Blob.
|
||||
*/
|
||||
public static final int JSONBlob = 5005;
|
||||
|
||||
/**
|
||||
* The data type name (VARCHAR, INTEGER ...)
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The default length or precision.
|
||||
*/
|
||||
private final int defaultLength;
|
||||
|
||||
/**
|
||||
* The default scale (decimal).
|
||||
*/
|
||||
private final int defaultScale;
|
||||
|
||||
/**
|
||||
* Set to true if the type should never have a length or scale.
|
||||
*/
|
||||
private final boolean canHaveLength;
|
||||
|
||||
/**
|
||||
* Construct with no length or scale.
|
||||
*/
|
||||
public DbType(String name) {
|
||||
this(name, 0, 0);
|
||||
DbType(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with a given length.
|
||||
* Return the JDBC java.sql.Types value.
|
||||
*/
|
||||
public DbType(String name, int defaultLength) {
|
||||
this(name, defaultLength, 0);
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for Decimal with precision and scale.
|
||||
* Create a platform type without scale or precision.
|
||||
*/
|
||||
public DbType(String name, int defaultPrecision, int defaultScale) {
|
||||
this.name = name;
|
||||
this.defaultLength = defaultPrecision;
|
||||
this.defaultScale = defaultScale;
|
||||
this.canHaveLength = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use with canHaveLength=false for types that should never have a length.
|
||||
*
|
||||
* @param name
|
||||
* the type name
|
||||
* @param canHaveLength
|
||||
* set this to false for type that should never have a length
|
||||
*/
|
||||
public DbType(String name, boolean canHaveLength) {
|
||||
this.name = name;
|
||||
this.defaultLength = 0;
|
||||
this.defaultScale = 0;
|
||||
this.canHaveLength = canHaveLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for a specific property that incorporates the name, length,
|
||||
* precision and scale.
|
||||
* <p>
|
||||
* The deployLength and deployScale are for the property we are rendering the
|
||||
* DB type for.
|
||||
* </p>
|
||||
*
|
||||
* @param deployLength
|
||||
* the length or precision defined by deployment on a specific
|
||||
* property.
|
||||
* @param deployScale
|
||||
* the scale defined by deployment on a specific property.
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale) {
|
||||
return renderType(deployLength, deployScale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the type defining strict mode.
|
||||
* <p>
|
||||
* If strict mode if OFF then this will render with a scale value even if
|
||||
* that is not strictly supported. The reason for supporting this is to enable
|
||||
* use to use types like jsonb(200) as a "logical" type that maps to JSONB for
|
||||
* Postgres and VARCHAR(200) for other databases.
|
||||
* </p>
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale, boolean strict) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(name);
|
||||
|
||||
if (canHaveLength || !strict) {
|
||||
// see if there is a precision/scale to add (or not)
|
||||
int len = deployLength != 0 ? deployLength : defaultLength;
|
||||
if (len > 0) {
|
||||
sb.append("(");
|
||||
sb.append(len);
|
||||
int scale = deployScale != 0 ? deployScale : defaultScale;
|
||||
if (scale > 0) {
|
||||
sb.append(",");
|
||||
sb.append(scale);
|
||||
}
|
||||
sb.append(")");
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the type with a new default length.
|
||||
*/
|
||||
public DbType withLength(int defaultLength) {
|
||||
return new DbType(name, defaultLength);
|
||||
public DbPlatformType createPlatformType() {
|
||||
return new DbPlatformType(name().toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,210 +0,0 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used to map bean property types to DB specific types for DDL generation.
|
||||
*/
|
||||
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");
|
||||
|
||||
/**
|
||||
* A map to reverse lookup the type by name.
|
||||
* <p>
|
||||
* Used when converting from logical types to platform types which we
|
||||
* want to do with 2 phase DDL generation.
|
||||
*/
|
||||
static Map<String, Integer> lookup = new HashMap<String, Integer>();
|
||||
|
||||
static {
|
||||
lookup.put("BOOLEAN", Types.BOOLEAN);
|
||||
lookup.put("BIT", Types.BIT);
|
||||
lookup.put("INTEGER", Types.INTEGER);
|
||||
lookup.put("BIGINT", Types.BIGINT);
|
||||
lookup.put("REAL", Types.REAL);
|
||||
// Float is most common REAL mapping to have that as well
|
||||
lookup.put("FLOAT", Types.REAL);
|
||||
|
||||
lookup.put("DOUBLE", Types.DOUBLE);
|
||||
lookup.put("SMALLINT", Types.SMALLINT);
|
||||
lookup.put("TINYINT", Types.TINYINT);
|
||||
lookup.put("DECIMAL", Types.DECIMAL);
|
||||
lookup.put("VARCHAR", Types.VARCHAR);
|
||||
// VARCHAR2 - extra for Oracle specific column definition
|
||||
lookup.put("VARCHAR2", Types.VARCHAR);
|
||||
lookup.put("CHAR", Types.CHAR);
|
||||
lookup.put("BLOB", Types.BLOB);
|
||||
lookup.put("CLOB", Types.CLOB);
|
||||
|
||||
lookup.put("LONGVARBINARY", Types.LONGVARBINARY);
|
||||
lookup.put("LONGVARCHAR", Types.LONGVARCHAR);
|
||||
lookup.put("VARBINARY", Types.VARBINARY);
|
||||
lookup.put("BINARY", Types.BINARY);
|
||||
lookup.put("DATE", Types.DATE);
|
||||
lookup.put("TIME", Types.TIME);
|
||||
lookup.put("TIMESTAMP", Types.TIMESTAMP);
|
||||
|
||||
lookup.put("ARRAY", Types.ARRAY);
|
||||
lookup.put("UUID", DbType.UUID);
|
||||
|
||||
// Not standard java.sql.Types
|
||||
// logical JSON storage types
|
||||
lookup.put("JSON", DbType.JSON);
|
||||
lookup.put("JSONB", DbType.JSONB);
|
||||
lookup.put("JSONCLOB", DbType.JSONClob);
|
||||
lookup.put("JSONBLOB", DbType.JSONBlob);
|
||||
lookup.put("JSONVARCHAR", DbType.JSONVarchar);
|
||||
}
|
||||
|
||||
|
||||
private final Map<Integer, DbType> typeMap = new HashMap<Integer, DbType>();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public static DbTypeMap logicalTypes() {
|
||||
return new DbTypeMap(true);
|
||||
}
|
||||
|
||||
public DbTypeMap() {
|
||||
loadDefaults(false);
|
||||
}
|
||||
|
||||
private DbTypeMap(boolean logicalTypes) {
|
||||
loadDefaults(logicalTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the standard types. These can be overridden by DB specific platform.
|
||||
*/
|
||||
private void loadDefaults(boolean logicalTypes) {
|
||||
|
||||
put(Types.BOOLEAN, new DbType("boolean"));
|
||||
put(Types.BIT, new DbType("bit"));
|
||||
|
||||
put(Types.INTEGER, new DbType("integer"));
|
||||
put(Types.BIGINT, new DbType("bigint"));
|
||||
put(Types.REAL, new DbType("float"));
|
||||
put(Types.DOUBLE, new DbType("double"));
|
||||
put(Types.SMALLINT, new DbType("smallint"));
|
||||
put(Types.TINYINT, new DbType("tinyint"));
|
||||
put(Types.DECIMAL, new DbType("decimal", 38));
|
||||
|
||||
put(Types.VARCHAR, new DbType("varchar", 255));
|
||||
put(Types.CHAR, new DbType("char", 1));
|
||||
|
||||
put(Types.BLOB, new DbType("blob"));
|
||||
put(Types.CLOB, new DbType("clob"));
|
||||
|
||||
put(Types.ARRAY, new DbType("array"));
|
||||
|
||||
if (logicalTypes) {
|
||||
// keep it logical for 2 layer DDL generation
|
||||
put(DbType.HSTORE, new DbType("hstore", false));
|
||||
put(DbType.JSON, new DbType("json", false));
|
||||
put(DbType.JSONB, new DbType("jsonb", false));
|
||||
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
|
||||
put(DbType.JSONB, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSONB
|
||||
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"));
|
||||
put(Types.LONGVARCHAR, new DbType("lonvarchar"));
|
||||
put(Types.VARBINARY, new DbType("varbinary", 255));
|
||||
put(Types.BINARY, new DbType("binary", 255));
|
||||
|
||||
put(Types.DATE, new DbType("date"));
|
||||
put(Types.TIME, new DbType("time"));
|
||||
put(Types.TIMESTAMP, new DbType("timestamp"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the platform specific DbType given the standard sql type name.
|
||||
*/
|
||||
public DbType lookup(String name, boolean withScale) {
|
||||
name = name.trim().toUpperCase();
|
||||
Integer typeKey = lookup.get(name);
|
||||
if (typeKey == null) {
|
||||
throw new IllegalArgumentException("Unknown type [" + name + "] - not standard sql type");
|
||||
}
|
||||
// handle JSON types mapped to clob, blob and varchar
|
||||
switch (typeKey) {
|
||||
case DbType.JSONBlob:
|
||||
return get(Types.BLOB);
|
||||
case DbType.JSONClob:
|
||||
return get(Types.CLOB);
|
||||
case DbType.JSONVarchar:
|
||||
return get(Types.VARCHAR);
|
||||
case DbType.JSON:
|
||||
return getJsonType(DbType.JSON, withScale);
|
||||
case DbType.JSONB:
|
||||
return getJsonType(DbType.JSONB, withScale);
|
||||
default:
|
||||
return get(typeKey);
|
||||
}
|
||||
}
|
||||
|
||||
private DbType getJsonType(int type, boolean withScale) {
|
||||
DbType dbType = get(type);
|
||||
if (dbType == JSON_CLOB_PLACEHOLDER) {
|
||||
// if we have scale that implies this maps to varchar
|
||||
return withScale ? get(Types.VARCHAR) : get(Types.CLOB);
|
||||
}
|
||||
if (dbType == JSON_BLOB_PLACEHOLDER) {
|
||||
return get(Types.BLOB);
|
||||
}
|
||||
if (dbType == JSON_VARCHAR_PLACEHOLDER) {
|
||||
return get(Types.VARCHAR);
|
||||
}
|
||||
// Postgres has specific type
|
||||
return get(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the type for a given JDBC type.
|
||||
*/
|
||||
public void put(int jdbcType, DbType dbType) {
|
||||
typeMap.put(jdbcType, dbType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type for a given jdbc type.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
/**
|
||||
* Integer codes for the extra types beyond java.sql.Types.
|
||||
*/
|
||||
public interface ExtraDbTypes {
|
||||
|
||||
/**
|
||||
* DB native UUID type (H2 and Postgres).
|
||||
*/
|
||||
int UUID = 5010;
|
||||
|
||||
/**
|
||||
* Type to map Map content to Postgres HSTORE.
|
||||
*/
|
||||
int HSTORE = 5000;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob or Postgres JSON type.
|
||||
*/
|
||||
int JSON = 5001;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob or Postgres JSONB type.
|
||||
*/
|
||||
int JSONB = 5002;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to VARCHAR.
|
||||
*/
|
||||
int JSONVarchar = 5003;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Clob.
|
||||
*/
|
||||
int JSONClob = 5004;
|
||||
|
||||
/**
|
||||
* Type to map JSON content to Blob.
|
||||
*/
|
||||
int JSONBlob = 5005;
|
||||
|
||||
/**
|
||||
* Geo Point
|
||||
*/
|
||||
int POINT = 6000;
|
||||
|
||||
/**
|
||||
* Geo Polygon
|
||||
*/
|
||||
int POLYGON = 6001;
|
||||
|
||||
/**
|
||||
* Geo Point
|
||||
*/
|
||||
int LINESTRING = 6002;
|
||||
|
||||
/**
|
||||
* Geo MultiPolygon
|
||||
*/
|
||||
int MULTIPOINT = 6005;
|
||||
|
||||
/**
|
||||
* Geo MultiPolygon
|
||||
*/
|
||||
int MULTIPOLYGON = 6006;
|
||||
|
||||
/**
|
||||
* Geo MultiPolygon
|
||||
*/
|
||||
int MULTILINESTRING = 6007;
|
||||
|
||||
}
|
||||
@@ -4,7 +4,6 @@ import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.HsqldbDdl;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* H2 specific platform.
|
||||
@@ -22,7 +21,7 @@ public class HsqldbPlatform extends DatabasePlatform {
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,8 +2,6 @@ package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Microsoft SQL Server 2000 specific platform.
|
||||
* <p>
|
||||
@@ -29,22 +27,22 @@ public class MsSqlServer2000Platform extends DatabasePlatform {
|
||||
this.openQuote = "[";
|
||||
this.closeQuote = "]";
|
||||
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("bit default 0"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0"));
|
||||
|
||||
dbTypeMap.put(Types.BIGINT, new DbType("numeric", 19));
|
||||
dbTypeMap.put(Types.REAL, new DbType("float(16)"));
|
||||
dbTypeMap.put(Types.DOUBLE, new DbType("float(32)"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("numeric", 28));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("numeric", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
|
||||
|
||||
dbTypeMap.put(Types.BLOB, new DbType("image"));
|
||||
dbTypeMap.put(Types.CLOB, new DbType("text"));
|
||||
dbTypeMap.put(Types.LONGVARBINARY, new DbType("image"));
|
||||
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
|
||||
dbTypeMap.put(DbType.BLOB, new DbPlatformType("image"));
|
||||
dbTypeMap.put(DbType.CLOB, new DbPlatformType("text"));
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("image"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("text"));
|
||||
|
||||
dbTypeMap.put(Types.DATE, new DbType("datetime"));
|
||||
dbTypeMap.put(Types.TIME, new DbType("datetime"));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime"));
|
||||
dbTypeMap.put(DbType.DATE, new DbPlatformType("datetime"));
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("datetime"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,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;
|
||||
|
||||
/**
|
||||
* Microsoft SQL Server 2005 specific platform.
|
||||
* <p>
|
||||
@@ -34,23 +32,23 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
|
||||
this.openQuote = "[";
|
||||
this.closeQuote = "]";
|
||||
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("bit default 0"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0"));
|
||||
|
||||
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
|
||||
dbTypeMap.put(Types.BIGINT, new DbType("numeric", 19));
|
||||
dbTypeMap.put(Types.REAL, new DbType("float(16)"));
|
||||
dbTypeMap.put(Types.DOUBLE, new DbType("float(32)"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("numeric", 28));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("numeric", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
|
||||
|
||||
dbTypeMap.put(Types.BLOB, new DbType("image"));
|
||||
dbTypeMap.put(Types.CLOB, new DbType("text"));
|
||||
dbTypeMap.put(Types.LONGVARBINARY, new DbType("image"));
|
||||
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
|
||||
dbTypeMap.put(DbType.BLOB, new DbPlatformType("image"));
|
||||
dbTypeMap.put(DbType.CLOB, new DbPlatformType("text"));
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("image"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("text"));
|
||||
|
||||
dbTypeMap.put(Types.DATE, new DbType("date"));
|
||||
dbTypeMap.put(Types.TIME, new DbType("time"));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime2"));
|
||||
dbTypeMap.put(DbType.DATE, new DbPlatformType("date"));
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("time"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime2"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ package com.avaje.ebean.config.dbplatform;
|
||||
* If no deployment length is defined longblob is used.
|
||||
* </p>
|
||||
*/
|
||||
public class MySqlBlob extends DbType {
|
||||
public class MySqlBlob extends DbPlatformType {
|
||||
|
||||
private static final int POWER_2_16 = 65536;
|
||||
private static final int POWER_2_24 = 16777216;
|
||||
|
||||
@@ -7,7 +7,7 @@ package com.avaje.ebean.config.dbplatform;
|
||||
* If no deployment length is defined longtext is used.
|
||||
* </p>
|
||||
*/
|
||||
public class MySqlClob extends DbType {
|
||||
public class MySqlClob extends DbPlatformType {
|
||||
|
||||
private static final int POWER_2_16 = 65536;
|
||||
private static final int POWER_2_24 = 16777216;
|
||||
|
||||
@@ -39,13 +39,13 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
this.forwardOnlyHintOnFindIterate = true;
|
||||
this.booleanDbType = Types.BIT;
|
||||
|
||||
dbTypeMap.put(Types.BIT, new DbType("tinyint(1) default 0"));
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("tinyint(1) default 0"));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime(6)"));
|
||||
dbTypeMap.put(Types.CLOB, new MySqlClob());
|
||||
dbTypeMap.put(Types.BLOB, new MySqlBlob());
|
||||
dbTypeMap.put(Types.BINARY, new DbType("binary", 255));
|
||||
dbTypeMap.put(Types.VARBINARY, new DbType("varbinary", 255));
|
||||
dbTypeMap.put(DbType.BIT, new DbPlatformType("tinyint(1) default 0"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("tinyint(1) default 0"));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime(6)"));
|
||||
dbTypeMap.put(DbType.CLOB, new MySqlClob());
|
||||
dbTypeMap.put(DbType.BLOB, new MySqlBlob());
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("binary", 255));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,24 +34,24 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
this.closeQuote = "\"";
|
||||
|
||||
booleanDbType = Types.INTEGER;
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("number(1) default 0"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("number(1) default 0"));
|
||||
|
||||
dbTypeMap.put(Types.INTEGER, new DbType("number", 10));
|
||||
dbTypeMap.put(Types.BIGINT, new DbType("number", 19));
|
||||
dbTypeMap.put(Types.REAL, new DbType("number", 19, 4));
|
||||
dbTypeMap.put(Types.DOUBLE, new DbType("number", 19, 4));
|
||||
dbTypeMap.put(Types.SMALLINT, new DbType("number", 5));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("number", 3));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("number", 38));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("number", 10));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("number", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("number", 19, 4));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("number", 19, 4));
|
||||
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("number", 5));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("number", 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 38));
|
||||
|
||||
dbTypeMap.put(Types.VARCHAR, new DbType("varchar2", 255));
|
||||
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("varchar2", 255));
|
||||
|
||||
dbTypeMap.put(Types.LONGVARBINARY, new DbType("blob"));
|
||||
dbTypeMap.put(Types.LONGVARCHAR, new DbType("clob"));
|
||||
dbTypeMap.put(Types.VARBINARY, new DbType("raw", 255));
|
||||
dbTypeMap.put(Types.BINARY, new DbType("raw", 255));
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("blob"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("clob"));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("raw", 255));
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("raw", 255));
|
||||
|
||||
dbTypeMap.put(Types.TIME, new DbType("timestamp"));
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("timestamp"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,26 +41,26 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
this.openQuote = "\"";
|
||||
this.closeQuote = "\"";
|
||||
|
||||
DbType dbTypeText = new DbType("text");
|
||||
DbType dbBytea = new DbType("bytea", false);
|
||||
DbPlatformType dbTypeText = new DbPlatformType("text");
|
||||
DbPlatformType dbBytea = new DbPlatformType("bytea", false);
|
||||
|
||||
dbTypeMap.put(DbType.HSTORE, new DbType("hstore", false));
|
||||
dbTypeMap.put(DbType.JSON, new DbType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbType("jsonb", false));
|
||||
dbTypeMap.put(DbType.HSTORE, new DbPlatformType("hstore", false));
|
||||
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
|
||||
dbTypeMap.put(DbType.JSONB, new DbPlatformType("jsonb", false));
|
||||
|
||||
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
|
||||
dbTypeMap.put(Types.DOUBLE, new DbType("float"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 38));
|
||||
dbTypeMap.put(Types.TIMESTAMP, new DbType("timestamptz"));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("timestamptz"));
|
||||
|
||||
dbTypeMap.put(Types.BINARY, dbBytea);
|
||||
dbTypeMap.put(Types.VARBINARY, dbBytea);
|
||||
dbTypeMap.put(DbType.BINARY, dbBytea);
|
||||
dbTypeMap.put(DbType.VARBINARY, dbBytea);
|
||||
|
||||
dbTypeMap.put(Types.BLOB, dbBytea);
|
||||
dbTypeMap.put(Types.CLOB, dbTypeText);
|
||||
dbTypeMap.put(Types.LONGVARBINARY, dbBytea);
|
||||
dbTypeMap.put(Types.LONGVARCHAR, dbTypeText);
|
||||
dbTypeMap.put(DbType.BLOB, dbBytea);
|
||||
dbTypeMap.put(DbType.CLOB, dbTypeText);
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, dbBytea);
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, dbTypeText);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,9 +71,23 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
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));
|
||||
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType(tsType));
|
||||
}
|
||||
}
|
||||
addGeoTypes(serverConfig.getGeometrySRID());
|
||||
}
|
||||
|
||||
private void addGeoTypes(int srid) {
|
||||
dbTypeMap.put(DbType.POINT, geoType("point",srid));
|
||||
dbTypeMap.put(DbType.POLYGON, geoType("polygon",srid));
|
||||
dbTypeMap.put(DbType.LINESTRING, geoType("linestring",srid));
|
||||
dbTypeMap.put(DbType.MULTIPOINT, geoType("multipoint",srid));
|
||||
dbTypeMap.put(DbType.MULTILINESTRING, geoType("multilinestring",srid));
|
||||
dbTypeMap.put(DbType.MULTIPOLYGON, geoType("multipolygon",srid));
|
||||
}
|
||||
|
||||
private DbPlatformType geoType(String type, int srid) {
|
||||
return new DbPlatformType("geometry("+type+","+srid+")");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,10 +18,10 @@ public class SQLitePlatform extends DatabasePlatform {
|
||||
|
||||
this.booleanDbType = Types.INTEGER;
|
||||
|
||||
dbTypeMap.put(Types.BIT, new DbType("int default 0"));
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("int default 0"));
|
||||
dbTypeMap.put(Types.BIGINT, new DbType("integer"));
|
||||
dbTypeMap.put(Types.SMALLINT, new DbType("integer"));
|
||||
dbTypeMap.put(DbType.BIT, new DbPlatformType("int default 0"));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("int default 0"));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("integer"));
|
||||
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("integer"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Sybase SQL Anywhere specific platform.
|
||||
* <p>
|
||||
@@ -23,17 +21,17 @@ public class SqlAnywherePlatform extends DatabasePlatform {
|
||||
this.dbIdentity.setSelectLastInsertedIdTemplate("select @@IDENTITY as X");
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
dbTypeMap.put(Types.BOOLEAN, new DbType("bit default 0"));
|
||||
dbTypeMap.put(Types.BIGINT, new DbType("numeric", 19));
|
||||
dbTypeMap.put(Types.REAL, new DbType("float(16)"));
|
||||
dbTypeMap.put(Types.DOUBLE, new DbType("float(32)"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("numeric", 28));
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0"));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("numeric", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
|
||||
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
|
||||
|
||||
dbTypeMap.put(Types.BLOB, new DbType("binary(4500)"));
|
||||
dbTypeMap.put(Types.CLOB, new DbType("long varchar"));
|
||||
dbTypeMap.put(Types.LONGVARBINARY, new DbType("long binary"));
|
||||
dbTypeMap.put(Types.LONGVARCHAR, new DbType("long varchar"));
|
||||
dbTypeMap.put(DbType.BLOB, new DbPlatformType("binary(4500)"));
|
||||
dbTypeMap.put(DbType.CLOB, new DbPlatformType("long varchar"));
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("long binary"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("long varchar"));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.avaje.ebean.config.DbMigrationConfig;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DB2Platform;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformName;
|
||||
import com.avaje.ebean.config.Platform;
|
||||
import com.avaje.ebean.config.dbplatform.H2Platform;
|
||||
import com.avaje.ebean.config.dbplatform.MsSqlServer2005Platform;
|
||||
import com.avaje.ebean.config.dbplatform.MySqlPlatform;
|
||||
@@ -139,7 +139,7 @@ public class DbMigration {
|
||||
* If not set this defaults to the platform of the default server.
|
||||
* </p>
|
||||
*/
|
||||
public void setPlatform(DbPlatformName platform) {
|
||||
public void setPlatform(Platform platform) {
|
||||
setPlatform(getPlatform(platform));
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public class DbMigration {
|
||||
* from the migration (e.g. generate migration sql for MySql, Postgres and Oracle).
|
||||
* </p>
|
||||
*/
|
||||
public void addPlatform(DbPlatformName platform, String prefix) {
|
||||
public void addPlatform(Platform platform, String prefix) {
|
||||
platforms.add(new Pair(getPlatform(platform), prefix));
|
||||
}
|
||||
|
||||
@@ -515,7 +515,7 @@ public class DbMigration {
|
||||
/**
|
||||
* Return the DatabasePlatform given the platform key.
|
||||
*/
|
||||
protected DatabasePlatform getPlatform(DbPlatformName platform) {
|
||||
protected DatabasePlatform getPlatform(Platform platform) {
|
||||
switch (platform) {
|
||||
case H2:
|
||||
return new H2Platform();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebean.dbmigration;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformName;
|
||||
import com.avaje.ebean.config.Platform;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -19,7 +19,7 @@ public class DbOffline {
|
||||
/**
|
||||
* Set the platform to use when creating the next EbeanServer instance.
|
||||
*/
|
||||
public static void setPlatform(DbPlatformName dbPlatform) {
|
||||
public static void setPlatform(Platform dbPlatform) {
|
||||
System.setProperty(KEY, dbPlatform.name());
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class DbOffline {
|
||||
* Bring up the next EbeanServer instance using the H2 platform.
|
||||
*/
|
||||
public static void asH2() {
|
||||
setPlatform(DbPlatformName.H2);
|
||||
setPlatform(Platform.H2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,8 @@ public class Oracle10Ddl extends PlatformDdl {
|
||||
super(platform);
|
||||
this.dropTableIfExists = "drop table ";
|
||||
this.dropSequenceIfExists = "drop sequence ";
|
||||
this.dropConstraintIfExists = "drop constraint";
|
||||
this.dropIndexIfExists = "drop index ";
|
||||
this.dropTableCascade = " cascade constraints purge";
|
||||
this.foreignKeyRestrict = "";
|
||||
this.alterColumn = "modify";
|
||||
|
||||
@@ -110,7 +110,6 @@ public class PlatformDdl {
|
||||
* Set configuration options.
|
||||
*/
|
||||
public void configure(ServerConfig serverConfig) {
|
||||
platform.configure(serverConfig);
|
||||
historyDdl.configure(serverConfig, this);
|
||||
naming = serverConfig.getConstraintNaming();
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebean.dbmigration.ddlgeneration.platform.util;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbTypeMap;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformTypeMapping;
|
||||
|
||||
/**
|
||||
* Converts a logical column definition into platform specific one.
|
||||
@@ -10,12 +10,12 @@ import com.avaje.ebean.config.dbplatform.DbTypeMap;
|
||||
*/
|
||||
public class PlatformTypeConverter {
|
||||
|
||||
protected final DbTypeMap platformTypes;
|
||||
protected final DbPlatformTypeMapping platformTypes;
|
||||
|
||||
/**
|
||||
* Construct with the platform specific types.
|
||||
*/
|
||||
public PlatformTypeConverter(DbTypeMap platformTypes) {
|
||||
public PlatformTypeConverter(DbPlatformTypeMapping platformTypes) {
|
||||
this.platformTypes = platformTypes;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class PlatformTypeConverter {
|
||||
String suffix = close + 1 < columnDefinition.length() ? columnDefinition.substring(close + 1) : "";
|
||||
String type = columnDefinition.substring(0, open);
|
||||
try {
|
||||
DbType dbType = platformTypes.lookup(type, true);
|
||||
DbPlatformType dbType = platformTypes.lookup(type, true);
|
||||
int comma = columnDefinition.indexOf(',', open);
|
||||
if (comma > -1) {
|
||||
// scale and precision - decimal(10,4)
|
||||
@@ -73,7 +73,7 @@ public class PlatformTypeConverter {
|
||||
protected String convertNoScale(String columnDefinition) {
|
||||
|
||||
try {
|
||||
DbType dbType = platformTypes.lookup(columnDefinition, false);
|
||||
DbPlatformType dbType = platformTypes.lookup(columnDefinition, false);
|
||||
return dbType.renderType(0, 0);
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebean.dbmigration.model.build;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.dbmigration.migration.IdentityType;
|
||||
import com.avaje.ebean.dbmigration.model.MColumn;
|
||||
@@ -52,7 +52,7 @@ public class ModelBuildBeanVisitor implements BeanVisitor {
|
||||
if (inheritInfo != null && inheritInfo.isRoot()) {
|
||||
// add the discriminator column
|
||||
String discColumn = inheritInfo.getDiscriminatorColumn();
|
||||
DbType dbType = ctx.getDbTypeMap().get(inheritInfo.getDiscriminatorType());
|
||||
DbPlatformType dbType = ctx.getDbTypeMap().get(inheritInfo.getDiscriminatorType());
|
||||
String discDbType = dbType.renderType(inheritInfo.getDiscriminatorLength(), 0);
|
||||
|
||||
table.addColumn(new MColumn(discColumn, discDbType, true));
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.avaje.ebean.dbmigration.model.build;
|
||||
|
||||
import com.avaje.ebean.config.DbConstraintNaming;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbTypeMap;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformTypeMapping;
|
||||
import com.avaje.ebean.dbmigration.model.MColumn;
|
||||
import com.avaje.ebean.dbmigration.model.MTable;
|
||||
import com.avaje.ebean.dbmigration.model.ModelContainer;
|
||||
@@ -21,7 +21,7 @@ public class ModelBuildContext {
|
||||
* Use platform agnostic logical types. These types are converted to
|
||||
* platform specific types in the DDL generation.
|
||||
*/
|
||||
private final DbTypeMap dbTypeMap = DbTypeMap.logicalTypes();
|
||||
private final DbPlatformTypeMapping dbTypeMap = DbPlatformTypeMapping.logicalTypes();
|
||||
|
||||
private final ModelContainer model;
|
||||
|
||||
@@ -106,7 +106,7 @@ public class ModelBuildContext {
|
||||
* Return the map used to determine the DB specific type
|
||||
* for a given bean property.
|
||||
*/
|
||||
public DbTypeMap getDbTypeMap() {
|
||||
public DbPlatformTypeMapping getDbTypeMap() {
|
||||
return dbTypeMap;
|
||||
}
|
||||
|
||||
@@ -115,14 +115,14 @@ public class ModelBuildContext {
|
||||
* Render the DB type for this property given the strict mode.
|
||||
*/
|
||||
public String getColumnDefn(BeanProperty p, boolean strict) {
|
||||
DbType dbType = getDbType(p);
|
||||
DbPlatformType dbType = getDbType(p);
|
||||
if (dbType == null) {
|
||||
throw new IllegalStateException("Unknown DbType mapping for " + p.getFullBeanName());
|
||||
}
|
||||
return p.renderDbType(dbType, strict);
|
||||
}
|
||||
|
||||
private DbType getDbType(BeanProperty p) {
|
||||
private DbPlatformType getDbType(BeanProperty p) {
|
||||
|
||||
if (p.isDbEncrypted()) {
|
||||
return dbTypeMap.get(p.getDbEncryptedType());
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.avaje.ebean.event;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
/**
|
||||
* Fired after a bean is constructed, but not yet loaded from database.
|
||||
* <p>
|
||||
* Note: You MUST NOT set any default values, as in a following step,
|
||||
* properties will get unload. Use {@link BeanPostLoad} instead.
|
||||
*
|
||||
* it's intended to do some dependency-injection here.
|
||||
* If you plan to use this feature you should use {@link EbeanServer#createEntityBean(Class)}
|
||||
* to create new beans.
|
||||
* </p>
|
||||
*/
|
||||
public interface BeanPostConstructListener {
|
||||
|
||||
/**
|
||||
* Return true if this BeanPostConstructListener instance should be registered
|
||||
* for post construct on this entity type.
|
||||
*/
|
||||
boolean isRegisterFor(Class<?> cls);
|
||||
|
||||
/**
|
||||
* Called immediately after construction. Perform DI here.
|
||||
*/
|
||||
void autowire(Object bean);
|
||||
|
||||
/**
|
||||
* Called after every @PostConstruct annotated method of the bean is executed
|
||||
*/
|
||||
void postConstruct(Object bean);
|
||||
|
||||
/**
|
||||
* Called after {@link EbeanServer#createEntityBean(Class)}. Only for new beans.
|
||||
* intended to set default values here.
|
||||
*/
|
||||
void postCreate(Object bean);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.avaje.ebean.plugin;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A factory that provides extra types to Ebean.
|
||||
*/
|
||||
public interface ExtraTypeFactory {
|
||||
|
||||
/**
|
||||
* Provide extra types to Ebean.
|
||||
*/
|
||||
List<? extends ScalarType> createTypes(ServerConfig config, Object objectMapper);
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
public final class DerivedRelationshipData {
|
||||
|
||||
private final Object assocBean;
|
||||
private final String logicalName;
|
||||
private final Object bean;
|
||||
|
||||
public DerivedRelationshipData(Object assocBean, String logicalName, Object bean) {
|
||||
this.assocBean = assocBean;
|
||||
this.logicalName = logicalName;
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
public Object getAssocBean() {
|
||||
return assocBean;
|
||||
}
|
||||
|
||||
public String getLogicalName() {
|
||||
return logicalName;
|
||||
}
|
||||
|
||||
public Object getBean() {
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -169,8 +169,13 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
EntityBeanIntercept ebi = batch.get(i);
|
||||
Object id = desc.getId(ebi.getOwner());
|
||||
if (!loadedIds.contains(id)) {
|
||||
logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + id + " - expecting when bean has been deleted");
|
||||
ebi.setLazyLoadFailure(id);
|
||||
if (desc.isSoftDelete()) {
|
||||
// assume this is logically deleted (hence not found)
|
||||
desc.setSoftDeleteValue(ebi.getOwner());
|
||||
} else {
|
||||
logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + id + " - expecting when bean has been deleted");
|
||||
ebi.setLazyLoadFailure(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ import com.avaje.ebean.event.changelog.BeanChange;
|
||||
import com.avaje.ebean.event.changelog.ChangeSet;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequest;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.core.PersistDeferredRelationship;
|
||||
import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.RollbackException;
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper of a ScopeTrans request and it's underlying transaction.
|
||||
@@ -145,13 +145,8 @@ public class ScopedTransaction implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDerivedRelationship(DerivedRelationshipData assocBean) {
|
||||
transaction.registerDerivedRelationship(assocBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DerivedRelationshipData> getDerivedRelationship(Object bean) {
|
||||
return transaction.getDerivedRelationship(bean);
|
||||
public void registerDeferred(PersistDeferredRelationship derived) {
|
||||
transaction.registerDeferred(derived);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -7,10 +7,10 @@ import com.avaje.ebean.event.changelog.BeanChange;
|
||||
import com.avaje.ebean.event.changelog.ChangeSet;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequest;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.core.PersistDeferredRelationship;
|
||||
import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Extends Transaction with additional API required on server.
|
||||
@@ -48,15 +48,9 @@ public interface SpiTransaction extends Transaction {
|
||||
void logSummary(String msg);
|
||||
|
||||
/**
|
||||
* Register a "Derived Relationship" (that requires an additional update).
|
||||
* Register a "Deferred Relationship" that requires an additional update later.
|
||||
*/
|
||||
void registerDerivedRelationship(DerivedRelationshipData assocBean);
|
||||
|
||||
/**
|
||||
* Return the list of "Derived Relationships" that must be maintained after
|
||||
* insert.
|
||||
*/
|
||||
List<DerivedRelationshipData> getDerivedRelationship(Object bean);
|
||||
void registerDeferred(PersistDeferredRelationship derived);
|
||||
|
||||
/**
|
||||
* Add a deleting bean to the registered list.
|
||||
|
||||
@@ -150,6 +150,9 @@ public final class BasicTypeConverter implements Serializable {
|
||||
if (value instanceof Boolean) {
|
||||
return (Boolean) value;
|
||||
}
|
||||
if (value instanceof Number) {
|
||||
return ((Number)value).intValue() == 1;
|
||||
}
|
||||
String s = value.toString();
|
||||
return s.equalsIgnoreCase(dbTrueValue);
|
||||
}
|
||||
|
||||
@@ -194,6 +194,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
bootup.addIdGenerators(serverConfig.getIdGenerators());
|
||||
bootup.addPersistControllers(serverConfig.getPersistControllers());
|
||||
bootup.addPostLoaders(serverConfig.getPostLoaders());
|
||||
bootup.addPostConstructListeners(serverConfig.getPostConstructListeners());
|
||||
bootup.addFindControllers(serverConfig.getFindControllers());
|
||||
bootup.addPersistListeners(serverConfig.getPersistListeners());
|
||||
bootup.addQueryAdapters(serverConfig.getQueryAdapters());
|
||||
|
||||
@@ -523,7 +523,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createEntityBean(Class<T> type) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(type);
|
||||
return (T) desc.createEntityBean();
|
||||
return (T) desc.createEntityBean(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
|
||||
/**
|
||||
* Deferred update of a relationship where an Id value is not initially available
|
||||
* so instead we execute this later as a SqlUpdate statement.
|
||||
*/
|
||||
public class PersistDeferredRelationship {
|
||||
|
||||
private final SpiEbeanServer ebeanServer;
|
||||
private final BeanDescriptor<?> beanDescriptor;
|
||||
private final EntityBean assocBean;
|
||||
private final ImportedId importedId;
|
||||
private final EntityBean bean;
|
||||
|
||||
public PersistDeferredRelationship(SpiEbeanServer ebeanServer, BeanDescriptor<?> beanDescriptor, EntityBean assocBean, ImportedId importedId, EntityBean bean) {
|
||||
|
||||
this.ebeanServer = ebeanServer;
|
||||
this.beanDescriptor = beanDescriptor;
|
||||
this.assocBean = assocBean;
|
||||
this.importedId = importedId;
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and execute a SqlUpdate to set the importId value (as it will be available now).
|
||||
* <p>
|
||||
* This is executed later (deferred) until after JDBC batch flush or prior to commit.
|
||||
* </p>
|
||||
*/
|
||||
public void execute(SpiTransaction transaction) {
|
||||
|
||||
String sql = beanDescriptor.getUpdateImportedIdSql(importedId);
|
||||
SqlUpdate sqlUpdate = ebeanServer.createSqlUpdate(sql);
|
||||
|
||||
// bind the set clause for the importedId
|
||||
int pos = importedId.bind(1, sqlUpdate, assocBean);
|
||||
|
||||
// bind the where clause for the bean
|
||||
Object[] idValues = beanDescriptor.getIdBinder().getIdValues(bean);
|
||||
for (int j = 0; j < idValues.length; j++) {
|
||||
sqlUpdate.setParameter(pos + j, idValues[j]);
|
||||
}
|
||||
|
||||
ebeanServer.execute(sqlUpdate, transaction);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.bean.PreGetterCallback;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebean.annotation.DocStoreMode;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PreGetterCallback;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPersistRequest;
|
||||
import com.avaje.ebean.event.changelog.BeanChange;
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.api.TransactionEvent;
|
||||
@@ -19,12 +18,13 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
import com.avaje.ebeaninternal.server.persist.PersistExecute;
|
||||
import com.avaje.ebeaninternal.server.transaction.BeanPersistIdMap;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdate;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateContext;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdates;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdate;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
@@ -180,7 +180,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
/**
|
||||
* Return the document store event that should be used for this request.
|
||||
*
|
||||
* <p>
|
||||
* Used to check if the Transaction has set the mode to IGNORE when doing large batch inserts that we
|
||||
* don't want to send to the doc store.
|
||||
*/
|
||||
@@ -874,8 +874,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
}
|
||||
|
||||
public List<DerivedRelationshipData> getDerivedRelationships() {
|
||||
return transaction.getDerivedRelationship(bean);
|
||||
/**
|
||||
* Register the derived relationships to get executed later (on JDBC batch flush or commit).
|
||||
*/
|
||||
public void deferredRelationship(EntityBean assocBean, ImportedId importedId, EntityBean bean) {
|
||||
transaction.registerDeferred(new PersistDeferredRelationship(ebeanServer, beanDescriptor, assocBean, importedId, bean));
|
||||
}
|
||||
|
||||
private void postInsert() {
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.ServerConfigStartup;
|
||||
@@ -41,38 +42,48 @@ public class BootupClasses implements ClassFilter {
|
||||
|
||||
private final List<Class<?>> entityList = new ArrayList<Class<?>>();
|
||||
|
||||
private final List<Class<?>> scalarTypeList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends ScalarType<?>>> scalarTypeList = new ArrayList<Class<? extends ScalarType<?>>>();
|
||||
|
||||
private final List<Class<?>> scalarConverterList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends ScalarTypeConverter<?, ?>>> scalarConverterList = new ArrayList<Class<? extends ScalarTypeConverter<?, ?>>>();
|
||||
|
||||
private final List<Class<?>> compoundTypeList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends CompoundType<?>>> compoundTypeList = new ArrayList<Class<? extends CompoundType<?>>>();
|
||||
|
||||
private final List<Class<?>> idGeneratorList = new ArrayList<Class<?>>();
|
||||
|
||||
private final List<Class<?>> beanControllerList = new ArrayList<Class<?>>();
|
||||
// The following objects are instantiiated on first request
|
||||
// there is always a candidate list, that holds the class and an
|
||||
// instance list, that holds the instance. Once a class is instantiiated
|
||||
// (or added) it will get removed from the candidate list
|
||||
private final List<Class<? extends IdGenerator>> idGeneratorCandidates = new ArrayList<Class<? extends IdGenerator>>();
|
||||
|
||||
private final List<Class<?>> beanPostLoadList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends BeanPersistController>> beanPersistControllerCandidates = new ArrayList<Class<? extends BeanPersistController>>();
|
||||
|
||||
private final List<Class<?>> beanFindControllerList = new ArrayList<Class<?>>();
|
||||
private final List<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends BeanPostLoad>> beanPostLoadCandidates = new ArrayList<Class<? extends BeanPostLoad>>();
|
||||
|
||||
private final List<Class<?>> beanListenerList = new ArrayList<Class<?>>();
|
||||
private final List<Class<? extends BeanPostConstructListener>> beanPostConstructListenerCandidates = new ArrayList<Class<? extends BeanPostConstructListener>>();
|
||||
|
||||
private final List<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
|
||||
private final List<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
|
||||
private final List<Class<? extends BeanFindController>> beanFindControllerCandidates = new ArrayList<Class<? extends BeanFindController>>();
|
||||
|
||||
private final List<Class<? extends BeanPersistListener>> beanPersistListenerCandidates = new ArrayList<Class<? extends BeanPersistListener>>();
|
||||
|
||||
private final List<Class<? extends BeanQueryAdapter>> beanQueryAdapterCandidates = new ArrayList<Class<? extends BeanQueryAdapter>>();
|
||||
|
||||
private final List<Class<? extends ServerConfigStartup>> serverConfigStartupCandidates = new ArrayList<Class<? extends ServerConfigStartup>>();
|
||||
|
||||
private final List<IdGenerator> idGeneratorInstances = new ArrayList<IdGenerator>();
|
||||
private final List<BeanFindController> findControllerInstances = new ArrayList<BeanFindController>();
|
||||
private final List<BeanPersistController> persistControllerInstances = new ArrayList<BeanPersistController>();
|
||||
private final List<BeanPersistController> beanPersistControllerInstances = new ArrayList<BeanPersistController>();
|
||||
private final List<BeanPostLoad> beanPostLoadInstances = new ArrayList<BeanPostLoad>();
|
||||
private final List<BeanPersistListener> persistListenerInstances = new ArrayList<BeanPersistListener>();
|
||||
private final List<BeanQueryAdapter> queryAdapterInstances = new ArrayList<BeanQueryAdapter>();
|
||||
private final List<BeanPostConstructListener> beanPostConstructListenerInstances = new ArrayList<BeanPostConstructListener>();
|
||||
private final List<BeanFindController> beanFindControllerInstances = new ArrayList<BeanFindController>();
|
||||
private final List<BeanPersistListener> beanPersistListenerInstances = new ArrayList<BeanPersistListener>();
|
||||
private final List<BeanQueryAdapter> beanQueryAdapterInstances = new ArrayList<BeanQueryAdapter>();
|
||||
private final List<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
|
||||
|
||||
private Class<?> changeLogPrepareClass;
|
||||
private Class<?> changeLogListenerClass;
|
||||
private Class<?> changeLogRegisterClass;
|
||||
private Class<?> readAuditPrepareClass;
|
||||
private Class<?> readAuditLoggerClass;
|
||||
// single objects
|
||||
private Class<? extends ChangeLogPrepare> changeLogPrepareClass;
|
||||
private Class<? extends ChangeLogListener> changeLogListenerClass;
|
||||
private Class<? extends ChangeLogRegister> changeLogRegisterClass;
|
||||
private Class<? extends ReadAuditPrepare> readAuditPrepareClass;
|
||||
private Class<? extends ReadAuditLogger> readAuditLoggerClass;
|
||||
|
||||
private ChangeLogPrepare changeLogPrepare;
|
||||
private ChangeLogListener changeLogListener;
|
||||
@@ -96,7 +107,7 @@ public class BootupClasses implements ClassFilter {
|
||||
*/
|
||||
public void runServerConfigStartup(ServerConfig serverConfig) {
|
||||
|
||||
for (Class<?> cls : serverConfigStartupList) {
|
||||
for (Class<?> cls : serverConfigStartupCandidates) {
|
||||
try {
|
||||
ServerConfigStartup newInstance = (ServerConfigStartup) cls.newInstance();
|
||||
newInstance.onStart(serverConfig);
|
||||
@@ -116,113 +127,90 @@ public class BootupClasses implements ClassFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add IdGenerator instances (registered explicitly with the ServerConfig).
|
||||
* Adds the list <code>toAdd</code> to <code>instances</code> and removes any pending
|
||||
* candiate, to prevent duplicate instantiiation.
|
||||
*/
|
||||
public void addIdGenerators(List<IdGenerator> idGenerators) {
|
||||
if (idGenerators != null) {
|
||||
for (IdGenerator c : idGenerators) {
|
||||
this.idGeneratorInstances.add(c);
|
||||
private <T> void add(List<T> toAdd, List<T> instances, List<Class<? extends T>> candidates) {
|
||||
if (toAdd != null) {
|
||||
for (T obj : toAdd) {
|
||||
instances.add(obj);
|
||||
// don't automatically instantiate
|
||||
this.idGeneratorList.remove(c.getClass());
|
||||
candidates.remove(obj.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addQueryAdapters(List<BeanQueryAdapter> queryAdapterInstances) {
|
||||
if (queryAdapterInstances != null) {
|
||||
for (BeanQueryAdapter a : queryAdapterInstances) {
|
||||
this.queryAdapterInstances.add(a);
|
||||
// don't automatically instantiate
|
||||
this.beanQueryAdapterList.remove(a.getClass());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add IdGenerator instances (registered explicitly with the ServerConfig).
|
||||
*/
|
||||
public void addIdGenerators(List<IdGenerator> idGenerators) {
|
||||
add(idGenerators, idGeneratorInstances, idGeneratorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BeanPersistController instances.
|
||||
*/
|
||||
public void addPersistControllers(List<BeanPersistController> beanControllerInstances) {
|
||||
if (beanControllerInstances != null) {
|
||||
for (BeanPersistController c : beanControllerInstances) {
|
||||
this.persistControllerInstances.add(c);
|
||||
// don't automatically instantiate
|
||||
this.beanControllerList.remove(c.getClass());
|
||||
}
|
||||
}
|
||||
public void addPersistControllers(List<BeanPersistController> beanControllers) {
|
||||
add(beanControllers, beanPersistControllerInstances, beanPersistControllerCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BeanPostLoad instances.
|
||||
*/
|
||||
public void addPostLoaders(List<BeanPostLoad> postLoadInstances) {
|
||||
if (postLoadInstances != null) {
|
||||
for (BeanPostLoad c : postLoadInstances) {
|
||||
this.beanPostLoadInstances.add(c);
|
||||
// don't automatically instantiate
|
||||
this.beanPostLoadList.remove(c.getClass());
|
||||
}
|
||||
}
|
||||
public void addPostLoaders(List<BeanPostLoad> postLoaders) {
|
||||
add(postLoaders, beanPostLoadInstances, beanPostLoadCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BeanPostConstructListener instances.
|
||||
*/
|
||||
public void addPostConstructListeners(List<BeanPostConstructListener> postConstructListener) {
|
||||
add(postConstructListener, beanPostConstructListenerInstances, beanPostConstructListenerCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BeanFindController instances.
|
||||
*/
|
||||
public void addFindControllers(List<BeanFindController> findControllers) {
|
||||
if (findControllers != null) {
|
||||
for (BeanFindController c : findControllers) {
|
||||
this.findControllerInstances.add(c);
|
||||
// don't automatically instantiate
|
||||
this.beanFindControllerList.remove(c.getClass());
|
||||
}
|
||||
}
|
||||
add(findControllers, beanFindControllerInstances, beanFindControllerCandidates);
|
||||
}
|
||||
|
||||
public void addPersistListeners(List<BeanPersistListener> listenerInstances) {
|
||||
if (listenerInstances != null) {
|
||||
for (BeanPersistListener l : listenerInstances) {
|
||||
this.persistListenerInstances.add(l);
|
||||
// don't automatically instantiate
|
||||
this.beanListenerList.remove(l.getClass());
|
||||
}
|
||||
}
|
||||
add(listenerInstances, beanPersistListenerInstances, beanPersistListenerCandidates);
|
||||
}
|
||||
|
||||
public void addQueryAdapters(List<BeanQueryAdapter> queryAdapters) {
|
||||
add(queryAdapters, beanQueryAdapterInstances, beanQueryAdapterCandidates);
|
||||
}
|
||||
|
||||
public void addServerConfigStartup(List<ServerConfigStartup> startupInstances) {
|
||||
if (startupInstances != null) {
|
||||
for (ServerConfigStartup l : startupInstances) {
|
||||
this.serverConfigStartupInstances.add(l);
|
||||
// don't automatically instantiate
|
||||
this.serverConfigStartupList.remove(l.getClass());
|
||||
}
|
||||
}
|
||||
add(startupInstances, serverConfigStartupInstances, serverConfigStartupCandidates);
|
||||
}
|
||||
|
||||
public void addChangeLogInstances(ServerConfig serverConfig) {
|
||||
|
||||
readAuditPrepare = serverConfig.getReadAuditPrepare();
|
||||
readAuditLogger = serverConfig.getReadAuditLogger();
|
||||
|
||||
if (readAuditPrepare == null && readAuditPrepareClass != null) {
|
||||
readAuditPrepare = (ReadAuditPrepare)create(readAuditPrepareClass, false);
|
||||
}
|
||||
if (readAuditLogger == null && readAuditLoggerClass != null) {
|
||||
readAuditLogger = (ReadAuditLogger)create(readAuditLoggerClass, false);
|
||||
}
|
||||
|
||||
changeLogPrepare = serverConfig.getChangeLogPrepare();
|
||||
changeLogListener = serverConfig.getChangeLogListener();
|
||||
changeLogRegister = serverConfig.getChangeLogRegister();
|
||||
changeLogPrepare = serverConfig.getChangeLogPrepare();
|
||||
|
||||
// if not already set create the implementations found
|
||||
// via classpath scanning
|
||||
if (readAuditPrepare == null && readAuditPrepareClass != null) {
|
||||
readAuditPrepare = create(readAuditPrepareClass, false);
|
||||
}
|
||||
if (readAuditLogger == null && readAuditLoggerClass != null) {
|
||||
readAuditLogger = create(readAuditLoggerClass, false);
|
||||
}
|
||||
if (changeLogPrepare == null && changeLogPrepareClass != null) {
|
||||
changeLogPrepare = (ChangeLogPrepare)create(changeLogPrepareClass, false);
|
||||
changeLogPrepare = create(changeLogPrepareClass, false);
|
||||
}
|
||||
if (changeLogListener == null && changeLogListenerClass != null) {
|
||||
changeLogListener = (ChangeLogListener)create(changeLogListenerClass, false);
|
||||
changeLogListener = create(changeLogListenerClass, false);
|
||||
}
|
||||
if (changeLogRegister == null && changeLogRegisterClass != null) {
|
||||
changeLogRegister = (ChangeLogRegister)create(changeLogRegisterClass, false);
|
||||
changeLogRegister = create(changeLogRegisterClass, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,10 +221,10 @@ public class BootupClasses implements ClassFilter {
|
||||
* <p>
|
||||
* Use logOnException = true to log the error and carry on.
|
||||
*/
|
||||
private Object create(Class<?> cls, boolean logOnException) {
|
||||
private <T> T create(Class<T> cls, boolean logOnException) {
|
||||
try {
|
||||
// instantiate via found class
|
||||
Constructor constructor = cls.getConstructor();
|
||||
Constructor<T> constructor = cls.getConstructor();
|
||||
return constructor.newInstance();
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
@@ -258,13 +246,18 @@ public class BootupClasses implements ClassFilter {
|
||||
|
||||
/**
|
||||
* Create the instance if it has a default constructor and add it to the list of instances.
|
||||
* It clears the list of classes afterwards, so that each class in the given list is
|
||||
* instantiated only once
|
||||
*/
|
||||
@SuppressWarnings(value = "unchecked")
|
||||
private <T> void createAdd(Class<?> cls, List<T> instances) {
|
||||
Object newInstance = create(cls, true);
|
||||
if (newInstance != null) {
|
||||
instances.add((T)newInstance);
|
||||
private <T> List<T> createAdd(List<T> instances, List<Class<? extends T>> candidates) {
|
||||
for (Class<? extends T> cls : candidates) {
|
||||
T newInstance = create(cls, true);
|
||||
if (newInstance != null) {
|
||||
instances.add(newInstance);
|
||||
}
|
||||
}
|
||||
candidates.clear(); // important, clear class list!
|
||||
return instances;
|
||||
}
|
||||
|
||||
public ChangeLogPrepare getChangeLogPrepare() {
|
||||
@@ -287,51 +280,32 @@ public class BootupClasses implements ClassFilter {
|
||||
return readAuditLogger;
|
||||
}
|
||||
|
||||
public List<BeanQueryAdapter> getBeanQueryAdapters() {
|
||||
// add class registered BeanQueryAdapter to the already created instances
|
||||
for (Class<?> cls : beanQueryAdapterList) {
|
||||
createAdd(cls, queryAdapterInstances);
|
||||
}
|
||||
return queryAdapterInstances;
|
||||
}
|
||||
|
||||
public List<BeanFindController> getBeanFindControllers() {
|
||||
// add class registered BeanFindController to the list of created instances
|
||||
for (Class<?> cls : beanFindControllerList) {
|
||||
createAdd(cls, findControllerInstances);
|
||||
}
|
||||
return findControllerInstances;
|
||||
}
|
||||
|
||||
public List<BeanPersistListener> getBeanPersistListeners() {
|
||||
// add class registered BeanPersistController to the already created instances
|
||||
for (Class<?> cls : beanListenerList) {
|
||||
createAdd(cls, persistListenerInstances);
|
||||
}
|
||||
return persistListenerInstances;
|
||||
public List<IdGenerator> getIdGenerators() {
|
||||
return createAdd(idGeneratorInstances, idGeneratorCandidates);
|
||||
}
|
||||
|
||||
public List<BeanPersistController> getBeanPersistControllers() {
|
||||
// add class registered BeanPersistController to the already created instances
|
||||
for (Class<?> cls : beanControllerList) {
|
||||
createAdd(cls, persistControllerInstances);
|
||||
}
|
||||
return persistControllerInstances;
|
||||
return createAdd(beanPersistControllerInstances, beanPersistControllerCandidates);
|
||||
}
|
||||
|
||||
public List<BeanPostLoad> getBeanPostLoaders() {
|
||||
// add class registered BeanPostLoad to the already created instances
|
||||
for (Class<?> cls : beanPostLoadList) {
|
||||
createAdd(cls, beanPostLoadInstances);
|
||||
}
|
||||
return beanPostLoadInstances;
|
||||
return createAdd(beanPostLoadInstances, beanPostLoadCandidates);
|
||||
}
|
||||
|
||||
public List<IdGenerator> getIdGenerators() {
|
||||
for (Class<?> cls : idGeneratorList) {
|
||||
createAdd(cls, idGeneratorInstances);
|
||||
}
|
||||
return idGeneratorInstances;
|
||||
public List<BeanPostConstructListener> getBeanPostConstructoListeners() {
|
||||
return createAdd(beanPostConstructListenerInstances, beanPostConstructListenerCandidates);
|
||||
}
|
||||
|
||||
public List<BeanFindController> getBeanFindControllers() {
|
||||
return createAdd(beanFindControllerInstances, beanFindControllerCandidates);
|
||||
}
|
||||
|
||||
public List<BeanPersistListener> getBeanPersistListeners() {
|
||||
return createAdd(beanPersistListenerInstances, beanPersistListenerCandidates);
|
||||
}
|
||||
|
||||
public List<BeanQueryAdapter> getBeanQueryAdapters() {
|
||||
return createAdd(beanQueryAdapterInstances, beanQueryAdapterCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,21 +325,21 @@ public class BootupClasses implements ClassFilter {
|
||||
/**
|
||||
* Return the list of ScalarTypes found.
|
||||
*/
|
||||
public List<Class<?>> getScalarTypes() {
|
||||
public List<Class<? extends ScalarType<?>>> getScalarTypes() {
|
||||
return scalarTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public List<Class<?>> getScalarConverters() {
|
||||
public List<Class<? extends ScalarTypeConverter<?, ?>>> getScalarConverters() {
|
||||
return scalarConverterList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public List<Class<?>> getCompoundTypes() {
|
||||
public List<Class<? extends CompoundType<?>>> getCompoundTypes() {
|
||||
return compoundTypeList;
|
||||
}
|
||||
|
||||
@@ -391,6 +365,7 @@ public class BootupClasses implements ClassFilter {
|
||||
* This includes ScalarType, BeanController, BeanFinder and BeanListener.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isInterestingInterface(Class<?> cls) {
|
||||
|
||||
if (Modifier.isAbstract(cls.getModifiers())) {
|
||||
@@ -400,77 +375,87 @@ public class BootupClasses implements ClassFilter {
|
||||
}
|
||||
boolean interesting = false;
|
||||
|
||||
if (IdGenerator.class.isAssignableFrom(cls)) {
|
||||
idGeneratorList.add(cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPersistController.class.isAssignableFrom(cls)) {
|
||||
beanControllerList.add(cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPostLoad.class.isAssignableFrom(cls)) {
|
||||
beanPostLoadList.add(cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
// Types
|
||||
if (ScalarType.class.isAssignableFrom(cls)) {
|
||||
scalarTypeList.add(cls);
|
||||
scalarTypeList.add((Class<? extends ScalarType<?>>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (ScalarTypeConverter.class.isAssignableFrom(cls)) {
|
||||
scalarConverterList.add(cls);
|
||||
scalarConverterList.add((Class<? extends ScalarTypeConverter<?, ?>>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (CompoundType.class.isAssignableFrom(cls)) {
|
||||
compoundTypeList.add(cls);
|
||||
compoundTypeList.add((Class<? extends CompoundType<?>>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (IdGenerator.class.isAssignableFrom(cls)) {
|
||||
idGeneratorCandidates.add((Class<? extends IdGenerator>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
// "Candidates"
|
||||
if (BeanPersistController.class.isAssignableFrom(cls)) {
|
||||
beanPersistControllerCandidates.add((Class<? extends BeanPersistController>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPostLoad.class.isAssignableFrom(cls)) {
|
||||
beanPostLoadCandidates.add((Class<? extends BeanPostLoad>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPostConstructListener.class.isAssignableFrom(cls)) {
|
||||
beanPostConstructListenerCandidates.add((Class<? extends BeanPostConstructListener>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanFindController.class.isAssignableFrom(cls)) {
|
||||
beanFindControllerList.add(cls);
|
||||
beanFindControllerCandidates.add((Class<? extends BeanFindController>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPersistListener.class.isAssignableFrom(cls)) {
|
||||
beanListenerList.add(cls);
|
||||
beanPersistListenerCandidates.add((Class<? extends BeanPersistListener>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanQueryAdapter.class.isAssignableFrom(cls)) {
|
||||
beanQueryAdapterList.add(cls);
|
||||
beanQueryAdapterCandidates.add((Class<? extends BeanQueryAdapter>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (ServerConfigStartup.class.isAssignableFrom(cls)) {
|
||||
serverConfigStartupList.add(cls);
|
||||
serverConfigStartupCandidates.add((Class<? extends ServerConfigStartup>) cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
// single instances
|
||||
// TODO: What should happen, if there is already an other
|
||||
// changeLogListener assigned? (Last wins? / Exception?)
|
||||
if (ChangeLogListener.class.isAssignableFrom(cls)) {
|
||||
changeLogListenerClass = cls;
|
||||
changeLogListenerClass = (Class<? extends ChangeLogListener>) cls;
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (ChangeLogRegister.class.isAssignableFrom(cls)) {
|
||||
changeLogRegisterClass = cls;
|
||||
changeLogRegisterClass = (Class<? extends ChangeLogRegister>) cls;
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (ChangeLogPrepare.class.isAssignableFrom(cls)) {
|
||||
changeLogPrepareClass = cls;
|
||||
changeLogPrepareClass = (Class<? extends ChangeLogPrepare>) cls;
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (ReadAuditPrepare.class.isAssignableFrom(cls)) {
|
||||
readAuditPrepareClass = cls;
|
||||
readAuditPrepareClass = (Class<? extends ReadAuditPrepare>) cls;
|
||||
interesting = true;
|
||||
}
|
||||
if (ReadAuditLogger.class.isAssignableFrom(cls)) {
|
||||
readAuditLoggerClass = cls;
|
||||
readAuditLoggerClass = (Class<? extends ReadAuditLogger>) cls;
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.changelog.BeanChange;
|
||||
@@ -51,6 +52,7 @@ import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequest;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyLists;
|
||||
import com.avaje.ebeaninternal.server.el.ElComparator;
|
||||
@@ -241,6 +243,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
private volatile BeanPersistController persistController;
|
||||
|
||||
private final BeanPostLoad beanPostLoad;
|
||||
private final BeanPostConstructListener beanPostConstructListener;
|
||||
|
||||
/**
|
||||
* Listens for post commit insert update and delete events.
|
||||
@@ -423,6 +426,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.beanFinder = deploy.getBeanFinder();
|
||||
this.persistController = deploy.getPersistController();
|
||||
this.persistListener = deploy.getPersistListener();
|
||||
this.beanPostConstructListener = deploy.getPostConstructListener();
|
||||
this.beanPostLoad = deploy.getPostLoad();
|
||||
this.queryAdapter = deploy.getQueryAdapter();
|
||||
this.changeLogFilter = deploy.getChangeLogFilter();
|
||||
@@ -1408,6 +1412,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
updatePlanCache.put(key, plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Sql update statement to set the importedId value (deferred execution).
|
||||
*/
|
||||
public String getUpdateImportedIdSql(ImportedId prop) {
|
||||
return "update " + baseTable + " set " + prop.importedIdClause() + " where " + idBinder.getBindIdSql(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if updates should only include changed properties. Otherwise
|
||||
* all loaded properties are included in the update.
|
||||
@@ -1550,17 +1561,26 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createBean() {
|
||||
return (T) createEntityBean();
|
||||
return (T) createEntityBean(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new EntityBean.
|
||||
* The parameter <code>isNew</code> controls either this is a new bean (then
|
||||
* {@link BeanPostConstructListener#postCreate(Object)} will be invoked) or
|
||||
* a reference (then {@link BeanPostLoad#postLoad(Object)} will be invoked
|
||||
* on first access (lazy load) or immediately (eager load)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public EntityBean createEntityBean() {
|
||||
public EntityBean createEntityBean(boolean isNew) {
|
||||
try {
|
||||
EntityBean bean = (EntityBean) prototypeEntityBean._ebean_newInstance();
|
||||
|
||||
if (beanPostConstructListener != null) {
|
||||
beanPostConstructListener.autowire(bean); // calls all registered listeners
|
||||
beanPostConstructListener.postConstruct(bean); // calls first the @PostConstruct method and then the listeners
|
||||
}
|
||||
|
||||
if (unloadProperties.length > 0) {
|
||||
// 'unload' any properties initialised in the default constructor
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
@@ -1568,12 +1588,23 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
ebi.setPropertyUnloaded(unloadProperties[i]);
|
||||
}
|
||||
}
|
||||
if (beanPostConstructListener != null && isNew) {
|
||||
beanPostConstructListener.postCreate(bean);
|
||||
// if bean is not new, postLoad will be executed later in the bean's lifecycle
|
||||
}
|
||||
return bean;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new entitybean without invoking {@link BeanPostConstructListener#postCreate(Object)}
|
||||
*/
|
||||
public EntityBean createEntityBean() {
|
||||
return createEntityBean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a reference bean based on the id.
|
||||
@@ -1806,7 +1837,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
* properties that make up the unique id.
|
||||
*/
|
||||
public Object getId(EntityBean bean) {
|
||||
return (idProperty == null) ? null : idProperty.getValue(bean);
|
||||
return (idProperty == null) ? null : idProperty.getValueIntercept(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -107,6 +107,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final PostLoadManager postLoadManager;
|
||||
|
||||
private final PostConstructManager postConstructManager;
|
||||
|
||||
private final BeanFinderManager beanFinderManager;
|
||||
|
||||
private final PersistListenerManager persistListenerManager;
|
||||
@@ -219,6 +221,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
this.beanLifecycleAdapterFactory = new BeanLifecycleAdapterFactory();
|
||||
this.persistControllerManager = new PersistControllerManager(bootupClasses);
|
||||
this.postLoadManager = new PostLoadManager(bootupClasses);
|
||||
this.postConstructManager = new PostConstructManager(bootupClasses);
|
||||
this.persistListenerManager = new PersistListenerManager(bootupClasses);
|
||||
this.beanQueryAdapterManager = new BeanQueryAdapterManager(bootupClasses);
|
||||
this.beanFinderManager = new BeanFinderManager(bootupClasses);
|
||||
@@ -624,10 +627,11 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
int qa = beanQueryAdapterManager.getRegisterCount();
|
||||
int cc = persistControllerManager.getRegisterCount();
|
||||
int pl = postLoadManager.getRegisterCount();
|
||||
int pc = postConstructManager.getRegisterCount();
|
||||
int lc = persistListenerManager.getRegisterCount();
|
||||
int fc = beanFinderManager.getRegisterCount();
|
||||
|
||||
logger.debug("BeanPersistControllers[" + cc + "] BeanFinders[" + fc + "] BeanPersistListeners[" + lc + "] BeanQueryAdapters[" + qa + "] BeanPostLoaders[" + pl + "]");
|
||||
logger.debug("BeanPersistControllers[" + cc + "] BeanFinders[" + fc + "] BeanPersistListeners[" + lc + "] BeanQueryAdapters[" + qa + "] BeanPostLoaders[" + pl + "] BeanPostConstructors[" + pc + "]");
|
||||
}
|
||||
|
||||
private void logStatus() {
|
||||
@@ -1143,6 +1147,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
persistControllerManager.addPersistControllers(descriptor);
|
||||
postLoadManager.addPostLoad(descriptor);
|
||||
postConstructManager.addPostConstructListeners(descriptor);
|
||||
persistListenerManager.addPersistListeners(descriptor);
|
||||
beanQueryAdapterManager.addQueryAdapter(descriptor);
|
||||
beanFinderManager.addFindControllers(descriptor);
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.PostPersist;
|
||||
@@ -16,6 +17,7 @@ import javax.persistence.PreUpdate;
|
||||
|
||||
import com.avaje.ebean.event.BeanPersistAdapter;
|
||||
import com.avaje.ebean.event.BeanPersistRequest;
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
|
||||
@@ -50,6 +52,10 @@ public class BeanLifecycleAdapterFactory {
|
||||
// has postLoad methods
|
||||
deployDesc.addPostLoad(new PostLoadAdapter(methodHolder.postLoads));
|
||||
}
|
||||
if (!methodHolder.postConstructs.isEmpty()) {
|
||||
// has postConstruct methods
|
||||
deployDesc.addPostConstructListener(new PostConstructAdapter(methodHolder.postConstructs));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,6 +71,7 @@ public class BeanLifecycleAdapterFactory {
|
||||
private final List<Method> preDeletes = new ArrayList<Method>();
|
||||
private final List<Method> postDeletes = new ArrayList<Method>();
|
||||
private final List<Method> postLoads = new ArrayList<Method>();
|
||||
private final List<Method> postConstructs = new ArrayList<Method>();
|
||||
|
||||
/**
|
||||
* Has one of the pre or post insert update delete annotated methods.
|
||||
@@ -107,6 +114,9 @@ public class BeanLifecycleAdapterFactory {
|
||||
if (method.isAnnotationPresent(PostLoad.class)) {
|
||||
postLoads.add(method);
|
||||
}
|
||||
if (method.isAnnotationPresent(PostConstruct.class)) {
|
||||
postConstructs.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,4 +251,49 @@ public class BeanLifecycleAdapterFactory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PostConstructAdapter using reflection to invoke lifecycle methods.
|
||||
*/
|
||||
private static class PostConstructAdapter implements BeanPostConstructListener {
|
||||
|
||||
private final Method[] postConstructMethods;
|
||||
|
||||
private PostConstructAdapter(List<Method> postConstructMethods) {
|
||||
this.postConstructMethods = toArray(postConstructMethods);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(Class<?> cls) {
|
||||
// Not used
|
||||
return false;
|
||||
}
|
||||
|
||||
private void invoke(Method method, Object bean) {
|
||||
try {
|
||||
method.invoke(bean);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new PersistenceException("Error invoking lifecycle method", e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new PersistenceException("Error invoking lifecycle method", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postConstruct(Object bean) {
|
||||
for (int i = 0; i < postConstructMethods.length; i++) {
|
||||
invoke(postConstructMethods[i], bean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autowire(Object bean) {
|
||||
// autowire is done by global PostConstructListener only
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreate(Object bean) {
|
||||
// postCreate is done by global PostConstructListener only
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.config.EncryptKey;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.plugin.Property;
|
||||
import com.avaje.ebean.text.StringParser;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
@@ -798,7 +798,7 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
|
||||
if (bean != null) {
|
||||
Object logicalVal = convertToLogicalType(value);
|
||||
setValue((EntityBean) bean, logicalVal);
|
||||
setValueIntercept((EntityBean) bean, logicalVal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,7 +972,7 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
/**
|
||||
* Return the DB column type definition.
|
||||
*/
|
||||
public String renderDbType(DbType dbType, boolean strict) {
|
||||
public String renderDbType(DbPlatformType dbType, boolean strict) {
|
||||
if (dbColumnDefn != null) {
|
||||
return dbColumnDefn;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
private final BeanPersistListener[] chain;
|
||||
|
||||
/**
|
||||
* Construct adding 2 BeanPersistController's.
|
||||
* Construct adding 2 BeanPersistListener's.
|
||||
*/
|
||||
public ChainedBeanPersistListener(BeanPersistListener c1, BeanPersistListener c2) {
|
||||
this(addList(c1, c2));
|
||||
@@ -46,7 +46,7 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct given the list of BeanPersistController's.
|
||||
* Construct given the list of BeanPersistListener's.
|
||||
*/
|
||||
public ChainedBeanPersistListener(List<BeanPersistListener> list) {
|
||||
this.list = list;
|
||||
@@ -54,7 +54,7 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new BeanPersistController and return the resulting chain.
|
||||
* Register a new BeanPersistListener and return the resulting chain.
|
||||
*/
|
||||
public ChainedBeanPersistListener register(BeanPersistListener c) {
|
||||
if (list.contains(c)){
|
||||
@@ -69,7 +69,7 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register a BeanPersistController and return the resulting chain.
|
||||
* De-register a BeanPersistListener and return the resulting chain.
|
||||
*/
|
||||
public ChainedBeanPersistListener deregister(BeanPersistListener c) {
|
||||
if (!list.contains(c)){
|
||||
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles multiple BeanPostLoad's for a given entity type.
|
||||
*/
|
||||
public class ChainedBeanPostConstructListener implements BeanPostConstructListener {
|
||||
|
||||
private final List<BeanPostConstructListener> list;
|
||||
|
||||
private final BeanPostConstructListener[] chain;
|
||||
|
||||
/**
|
||||
* Construct given the list of BeanPostCreate's.
|
||||
*/
|
||||
public ChainedBeanPostConstructListener(List<BeanPostConstructListener> list) {
|
||||
this.list = list;
|
||||
this.chain = list.toArray(new BeanPostConstructListener[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new BeanPostCreate and return the resulting chain.
|
||||
*/
|
||||
public ChainedBeanPostConstructListener register(BeanPostConstructListener c) {
|
||||
if (list.contains(c)) {
|
||||
return this;
|
||||
} else {
|
||||
List<BeanPostConstructListener> newList = new ArrayList<BeanPostConstructListener>();
|
||||
newList.addAll(list);
|
||||
newList.add(c);
|
||||
|
||||
return new ChainedBeanPostConstructListener(newList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register a BeanPostCreate and return the resulting chain.
|
||||
*/
|
||||
public BeanPostConstructListener deregister(BeanPostConstructListener c) {
|
||||
if (!list.contains(c)) {
|
||||
return this;
|
||||
} else {
|
||||
ArrayList<BeanPostConstructListener> newList = new ArrayList<BeanPostConstructListener>();
|
||||
newList.addAll(list);
|
||||
newList.remove(c);
|
||||
|
||||
return new ChainedBeanPostConstructListener(newList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the chain.
|
||||
*/
|
||||
protected int size() {
|
||||
return chain.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(Class<?> cls) {
|
||||
// never called
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire postLoad on all registered BeanPostCreate implementations.
|
||||
*/
|
||||
@Override
|
||||
public void postConstruct(Object bean) {
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
chain[i].postConstruct(bean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void autowire(Object bean) {
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
chain[i].autowire(bean);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postCreate(Object bean) {
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
chain[i].postCreate(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public class ChainedBeanPostLoad implements BeanPostLoad {
|
||||
private final BeanPostLoad[] chain;
|
||||
|
||||
/**
|
||||
* Construct given the list of BeanPersistController's.
|
||||
* Construct given the list of BeanPostLoad's.
|
||||
*/
|
||||
public ChainedBeanPostLoad(List<BeanPostLoad> list) {
|
||||
this.list = list;
|
||||
@@ -23,7 +23,7 @@ public class ChainedBeanPostLoad implements BeanPostLoad {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new BeanPersistController and return the resulting chain.
|
||||
* Register a new BeanPostLoad and return the resulting chain.
|
||||
*/
|
||||
public ChainedBeanPostLoad register(BeanPostLoad c) {
|
||||
if (list.contains(c)){
|
||||
@@ -38,7 +38,7 @@ public class ChainedBeanPostLoad implements BeanPostLoad {
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register a BeanPersistController and return the resulting chain.
|
||||
* De-register a BeanPostLoad and return the resulting chain.
|
||||
*/
|
||||
public ChainedBeanPostLoad deregister(BeanPostLoad c) {
|
||||
if (!list.contains(c)){
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Default implementation for creating BeanControllers.
|
||||
*/
|
||||
public class PostConstructManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PostConstructManager.class);
|
||||
|
||||
private final List<BeanPostConstructListener> list;
|
||||
|
||||
public PostConstructManager(BootupClasses bootupClasses) {
|
||||
this.list = bootupClasses.getBeanPostConstructoListeners();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register BeanPostLoad listeners for a given entity type.
|
||||
*/
|
||||
public void addPostConstructListeners(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanPostConstructListener c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())) {
|
||||
logger.debug("BeanPostLoad on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.addPostConstructListener(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -120,7 +120,7 @@ public final class TableJoin {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of join. LEFT OUTER JOIN etc.
|
||||
* Return the type of join. LEFT JOIN etc.
|
||||
*/
|
||||
public SqlJoinType getType() {
|
||||
return type;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
@@ -46,6 +47,11 @@ public interface ImportedId {
|
||||
*/
|
||||
Object bind(BindableRequest request, EntityBean bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* Bind the imported Id value to the SqlUpdate.
|
||||
*/
|
||||
int bind(int position, SqlUpdate update, EntityBean bean);
|
||||
|
||||
/**
|
||||
* For inserting into ManyToMany intersection.
|
||||
*/
|
||||
@@ -55,4 +61,9 @@ public interface ImportedId {
|
||||
* Used to derive a missing concatenated key from multiple imported keys.
|
||||
*/
|
||||
BeanProperty findMatchImport(String matchDbColumn);
|
||||
|
||||
/**
|
||||
* Return the set importedId clause.
|
||||
*/
|
||||
String importedIdClause();
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanFkeyProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -63,6 +64,34 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String importedIdClause() {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(imported[i].localDbColumn).append(" = ?");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bind(int position, SqlUpdate update, EntityBean bean) {
|
||||
|
||||
int pos = position;
|
||||
|
||||
EntityBean embedded = (EntityBean) foreignAssocOne.getValue(bean);
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (imported[i].owner.isUpdateable()) {
|
||||
Object scalarValue = imported[i].foreignProperty.getValue(embedded);
|
||||
update.setParameter(pos++, scalarValue);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
Object embeddedId = null;
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanFkeyProperty;
|
||||
@@ -110,6 +111,18 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
request.appendColumn(localDbColumn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String importedIdClause() {
|
||||
return localDbColumn + " = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bind(int position, SqlUpdate update, EntityBean bean) {
|
||||
Object value = getIdValue(bean);
|
||||
update.setParameter(position, value);
|
||||
return ++position;
|
||||
}
|
||||
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
Object value = null;
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPostConstructListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogFilter;
|
||||
@@ -22,6 +23,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostConstructListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostLoad;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
@@ -155,6 +157,7 @@ public class DeployBeanDescriptor<T> {
|
||||
private final List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
|
||||
private final List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
|
||||
private final List<BeanPostLoad> postLoaders = new ArrayList<BeanPostLoad>();
|
||||
private final List<BeanPostConstructListener> postConstructListeners = new ArrayList<BeanPostConstructListener>();
|
||||
|
||||
private CacheOptions cacheOptions = CacheOptions.NO_CACHING;
|
||||
|
||||
@@ -175,8 +178,6 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private String name;
|
||||
|
||||
private boolean processedRawSqlExtend;
|
||||
|
||||
private ChangeLogFilter changeLogFilter;
|
||||
|
||||
private String dbComment;
|
||||
@@ -533,6 +534,19 @@ public class DeployBeanDescriptor<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPostCreate(could be a chain of them, 1 or null).
|
||||
*/
|
||||
public BeanPostConstructListener getPostConstructListener() {
|
||||
if (postConstructListeners.isEmpty()) {
|
||||
return null;
|
||||
} else if (postConstructListeners.size() == 1) {
|
||||
return postConstructListeners.get(0);
|
||||
} else {
|
||||
return new ChainedBeanPostConstructListener(postConstructListeners);
|
||||
}
|
||||
}
|
||||
|
||||
public void addPersistController(BeanPersistController controller) {
|
||||
persistControllers.add(controller);
|
||||
}
|
||||
@@ -549,6 +563,10 @@ public class DeployBeanDescriptor<T> {
|
||||
postLoaders.add(postLoad);
|
||||
}
|
||||
|
||||
public void addPostConstructListener(BeanPostConstructListener postConstructListener) {
|
||||
postConstructListeners.add(postConstructListener);
|
||||
}
|
||||
|
||||
public String getDraftTable() {
|
||||
return draftTable;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ public class DeployTableJoin {
|
||||
private String table;
|
||||
|
||||
/**
|
||||
* The type of join. LEFT OUTER etc.
|
||||
* The type of join. LEFT JOIN etc.
|
||||
*/
|
||||
private SqlJoinType type = SqlJoinType.INNER;
|
||||
|
||||
|
||||
+266
-267
@@ -29,294 +29,293 @@ import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
*/
|
||||
public class AnnotationAssocManys extends AnnotationParser {
|
||||
|
||||
private final BeanDescriptorManager factory;
|
||||
private final BeanDescriptorManager factory;
|
||||
|
||||
/**
|
||||
* Create with the DeployInfo.
|
||||
*/
|
||||
public AnnotationAssocManys(DeployBeanInfo<?> info, boolean javaxValidationAnnotations, BeanDescriptorManager factory) {
|
||||
super(info, javaxValidationAnnotations);
|
||||
this.factory = factory;
|
||||
}
|
||||
/**
|
||||
* Create with the DeployInfo.
|
||||
*/
|
||||
public AnnotationAssocManys(DeployBeanInfo<?> info, boolean javaxValidationAnnotations, BeanDescriptorManager factory) {
|
||||
super(info, javaxValidationAnnotations);
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
read((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
read((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void read(DeployBeanPropertyAssocMany<?> prop) {
|
||||
private void read(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
OneToMany oneToMany = get(prop, OneToMany.class);
|
||||
if (oneToMany != null) {
|
||||
readToOne(oneToMany, prop);
|
||||
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
|
||||
if (privateOwned != null){
|
||||
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
|
||||
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
|
||||
}
|
||||
}
|
||||
ManyToMany manyToMany = get(prop, ManyToMany.class);
|
||||
if (manyToMany != null) {
|
||||
readToMany(manyToMany, prop);
|
||||
}
|
||||
OneToMany oneToMany = get(prop, OneToMany.class);
|
||||
if (oneToMany != null) {
|
||||
readToOne(oneToMany, prop);
|
||||
PrivateOwned privateOwned = get(prop, PrivateOwned.class);
|
||||
if (privateOwned != null) {
|
||||
prop.setModifyListenMode(ModifyListenMode.REMOVALS);
|
||||
prop.getCascadeInfo().setDelete(privateOwned.cascadeRemove());
|
||||
}
|
||||
}
|
||||
ManyToMany manyToMany = get(prop, ManyToMany.class);
|
||||
if (manyToMany != null) {
|
||||
readToMany(manyToMany, prop);
|
||||
}
|
||||
|
||||
if (get(prop, HistoryExclude.class) != null) {
|
||||
prop.setExcludedFromHistory();
|
||||
}
|
||||
|
||||
OrderBy orderBy = get(prop, OrderBy.class);
|
||||
if (orderBy != null) {
|
||||
prop.setFetchOrderBy(orderBy.value());
|
||||
}
|
||||
|
||||
MapKey mapKey = get(prop, MapKey.class);
|
||||
if (mapKey != null) {
|
||||
prop.setMapKey(mapKey.name());
|
||||
}
|
||||
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
|
||||
}
|
||||
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
if (prop.isManyToMany()){
|
||||
// expected this
|
||||
readJoinTable(joinTable, prop);
|
||||
|
||||
} else {
|
||||
// OneToMany in theory
|
||||
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
if (prop.getMappedBy() != null){
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.isManyToMany()){
|
||||
manyToManyDefaultJoins(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null){
|
||||
|
||||
// use naming convention to define join (based on the bean name for this side of relationship)
|
||||
// A unidirectional OneToMany or OneToMany with no mappedBy property
|
||||
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()){
|
||||
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
|
||||
}
|
||||
|
||||
// Use the owning bean table to define the join
|
||||
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the joins for a ManyToMany relationship.
|
||||
* <p>
|
||||
* This includes joins to the intersection table and from the intersection table
|
||||
* to the other side of the ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = getFullTableName(joinTable);
|
||||
// set the intersection table
|
||||
DeployTableJoin intJoin = new DeployTableJoin();
|
||||
intJoin.setTable(intTableName);
|
||||
|
||||
// add the source to intersection join columns
|
||||
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
|
||||
|
||||
// set the intersection to dest table join columns
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
|
||||
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full table name
|
||||
*/
|
||||
private String getFullTableName(JoinTable joinTable) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringHelper.isNull(joinTable.catalog())){
|
||||
sb.append(joinTable.catalog()).append(".");
|
||||
}
|
||||
if (!StringHelper.isNull(joinTable.schema())){
|
||||
sb.append(joinTable.schema()).append(".");
|
||||
}
|
||||
sb.append(joinTable.name());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define intersection table and foreign key columns for ManyToMany.
|
||||
* <p>
|
||||
* Some of these (maybe all) have been already defined via @JoinTable
|
||||
* and @JoinColumns etc.
|
||||
* </p>
|
||||
*/
|
||||
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = null;
|
||||
|
||||
DeployTableJoin intJoin = prop.getIntersectionJoin();
|
||||
if (intJoin == null){
|
||||
intJoin = new DeployTableJoin();
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
} else {
|
||||
// intersection table already defined (by @JoinTable)
|
||||
intTableName = intJoin.getTable();
|
||||
}
|
||||
|
||||
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
|
||||
|
||||
final String localTableName = localTable.getUnqualifiedBaseTable();
|
||||
final String otherTableName = otherTable.getUnqualifiedBaseTable();
|
||||
|
||||
if (intTableName == null){
|
||||
// define intersection table name
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
|
||||
intJoin.setTable(intTableName);
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
|
||||
|
||||
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()){
|
||||
// already defined the foreign key columns etc
|
||||
return;
|
||||
}
|
||||
if (!intJoin.hasJoinColumns()){
|
||||
// define foreign key columns
|
||||
BeanProperty[] localIds = localTable.getIdProperties();
|
||||
for (int i = 0; i < localIds.length; i++) {
|
||||
// add the source to intersection join columns
|
||||
String fkCol = localTableName+"_"+localIds[i].getDbColumn();
|
||||
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), fkCol));
|
||||
}
|
||||
}
|
||||
|
||||
if (!destJoin.hasJoinColumns()){
|
||||
// define inverse foreign key columns
|
||||
BeanProperty[] otherIds = otherTable.getIdProperties();
|
||||
for (int i = 0; i < otherIds.length; i++) {
|
||||
// set the intersection to dest table join columns
|
||||
final String fkCol = otherTableName+"_"+otherIds[i].getDbColumn();
|
||||
destJoin.addJoinColumn(new DeployTableJoinColumn(fkCol, otherIds[i].getDbColumn()));
|
||||
}
|
||||
}
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to ["+type+"] from ["+from+"]. Is "+type+" registered?";
|
||||
if (orderBy != null) {
|
||||
prop.setFetchOrderBy(orderBy.value());
|
||||
}
|
||||
|
||||
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
MapKey mapKey = get(prop, MapKey.class);
|
||||
if (mapKey != null) {
|
||||
prop.setMapKey(mapKey.name());
|
||||
}
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
Where where = get(prop, Where.class);
|
||||
if (where != null) {
|
||||
prop.setExtraWhere(where.clause());
|
||||
}
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
// check for manually defined joins
|
||||
BeanTable beanTable = prop.getBeanTable();
|
||||
JoinColumn joinColumn = get(prop, JoinColumn.class);
|
||||
if (joinColumn != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumn, beanTable);
|
||||
}
|
||||
|
||||
// find the other many table (not intersection)
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
JoinColumns joinColumns = get(prop, JoinColumns.class);
|
||||
if (joinColumns != null) {
|
||||
prop.getTableJoin().addJoinColumn(true, joinColumns.value(), beanTable);
|
||||
}
|
||||
|
||||
manyProp.setManyToMany();
|
||||
manyProp.setModifyListenMode(ModifyListenMode.ALL);
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
JoinTable joinTable = get(prop, JoinTable.class);
|
||||
if (joinTable != null) {
|
||||
if (prop.isManyToMany()) {
|
||||
// expected this
|
||||
readJoinTable(joinTable, prop);
|
||||
|
||||
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
} else {
|
||||
// OneToMany in theory
|
||||
prop.getTableJoin().addJoinColumn(true, joinTable.joinColumns(), beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
if (prop.getMappedBy() != null) {
|
||||
// the join is derived by reversing the join information
|
||||
// from the mapped by property.
|
||||
// Refer BeanDescriptorManager.readEntityRelationships()
|
||||
return;
|
||||
}
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
if (prop.isManyToMany()) {
|
||||
manyToManyDefaultJoins(prop);
|
||||
return;
|
||||
}
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
if (!prop.getTableJoin().hasJoinColumns() && beanTable != null) {
|
||||
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
// use naming convention to define join (based on the bean name for this side of relationship)
|
||||
// A unidirectional OneToMany or OneToMany with no mappedBy property
|
||||
|
||||
|
||||
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable){
|
||||
|
||||
TableName lhs = new TableName(lhsTable.getBaseTable());
|
||||
TableName rhs = new TableName(rhsTable.getBaseTable());
|
||||
|
||||
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
|
||||
|
||||
return joinTable.getQualifiedName();
|
||||
}
|
||||
NamingConvention nc = factory.getNamingConvention();
|
||||
|
||||
String fkeyPrefix = null;
|
||||
if (nc.isUseForeignKeyPrefix()) {
|
||||
fkeyPrefix = nc.getColumnFromProperty(descriptor.getBeanType(), descriptor.getName());
|
||||
}
|
||||
|
||||
// Use the owning bean table to define the join
|
||||
BeanTable owningBeanTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
owningBeanTable.createJoinColumn(fkeyPrefix, prop.getTableJoin(), false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the joins for a ManyToMany relationship.
|
||||
* <p>
|
||||
* This includes joins to the intersection table and from the intersection table
|
||||
* to the other side of the ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
private void readJoinTable(JoinTable joinTable, DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = getFullTableName(joinTable);
|
||||
// set the intersection table
|
||||
DeployTableJoin intJoin = new DeployTableJoin();
|
||||
intJoin.setTable(intTableName);
|
||||
|
||||
// add the source to intersection join columns
|
||||
intJoin.addJoinColumn(true, joinTable.joinColumns(), prop.getBeanTable());
|
||||
|
||||
// set the intersection to dest table join columns
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
|
||||
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full table name
|
||||
*/
|
||||
private String getFullTableName(JoinTable joinTable) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!StringHelper.isNull(joinTable.catalog())) {
|
||||
sb.append(joinTable.catalog()).append(".");
|
||||
}
|
||||
if (!StringHelper.isNull(joinTable.schema())) {
|
||||
sb.append(joinTable.schema()).append(".");
|
||||
}
|
||||
sb.append(joinTable.name());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define intersection table and foreign key columns for ManyToMany.
|
||||
* <p>
|
||||
* Some of these (maybe all) have been already defined via @JoinTable
|
||||
* and @JoinColumns etc.
|
||||
* </p>
|
||||
*/
|
||||
private void manyToManyDefaultJoins(DeployBeanPropertyAssocMany<?> prop) {
|
||||
|
||||
String intTableName = null;
|
||||
|
||||
DeployTableJoin intJoin = prop.getIntersectionJoin();
|
||||
if (intJoin == null) {
|
||||
intJoin = new DeployTableJoin();
|
||||
prop.setIntersectionJoin(intJoin);
|
||||
} else {
|
||||
// intersection table already defined (by @JoinTable)
|
||||
intTableName = intJoin.getTable();
|
||||
}
|
||||
|
||||
BeanTable localTable = factory.getBeanTable(descriptor.getBeanType());
|
||||
BeanTable otherTable = factory.getBeanTable(prop.getTargetType());
|
||||
|
||||
final String localTableName = localTable.getUnqualifiedBaseTable();
|
||||
final String otherTableName = otherTable.getUnqualifiedBaseTable();
|
||||
|
||||
if (intTableName == null) {
|
||||
// define intersection table name
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
|
||||
intJoin.setTable(intTableName);
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
|
||||
|
||||
if (intJoin.hasJoinColumns() && destJoin.hasJoinColumns()) {
|
||||
// already defined the foreign key columns etc
|
||||
return;
|
||||
}
|
||||
if (!intJoin.hasJoinColumns()) {
|
||||
// define foreign key columns
|
||||
BeanProperty[] localIds = localTable.getIdProperties();
|
||||
for (int i = 0; i < localIds.length; i++) {
|
||||
// add the source to intersection join columns
|
||||
String fkCol = localTableName + "_" + localIds[i].getDbColumn();
|
||||
intJoin.addJoinColumn(new DeployTableJoinColumn(localIds[i].getDbColumn(), namingConvention.getColumnFromProperty(null, fkCol)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!destJoin.hasJoinColumns()) {
|
||||
// define inverse foreign key columns
|
||||
BeanProperty[] otherIds = otherTable.getIdProperties();
|
||||
for (int i = 0; i < otherIds.length; i++) {
|
||||
// set the intersection to dest table join columns
|
||||
final String fkCol = otherTableName + "_" + otherIds[i].getDbColumn();
|
||||
destJoin.addJoinColumn(new DeployTableJoinColumn(namingConvention.getColumnFromProperty(null, fkCol), otherIds[i].getDbColumn()));
|
||||
}
|
||||
}
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
prop.setInverseJoin(inverseDest);
|
||||
}
|
||||
|
||||
|
||||
private String errorMsgMissingBeanTable(Class<?> type, String from) {
|
||||
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered?";
|
||||
}
|
||||
|
||||
private void readToMany(ManyToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
// find the other many table (not intersection)
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setManyToMany();
|
||||
manyProp.setModifyListenMode(ModifyListenMode.ALL);
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
|
||||
manyProp.setMappedBy(propAnn.mappedBy());
|
||||
manyProp.setFetchType(propAnn.fetch());
|
||||
|
||||
setCascadeTypes(propAnn.cascade(), manyProp.getCascadeInfo());
|
||||
|
||||
Class<?> targetType = propAnn.targetEntity();
|
||||
if (targetType.equals(void.class)) {
|
||||
// via reflection of generics type
|
||||
targetType = manyProp.getTargetType();
|
||||
} else {
|
||||
manyProp.setTargetType(targetType);
|
||||
}
|
||||
|
||||
BeanTable assoc = factory.getBeanTable(targetType);
|
||||
if (assoc == null) {
|
||||
String msg = errorMsgMissingBeanTable(targetType, manyProp.getFullBeanName());
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
|
||||
private String getM2MJoinTableName(BeanTable lhsTable, BeanTable rhsTable) {
|
||||
|
||||
TableName lhs = new TableName(lhsTable.getBaseTable());
|
||||
TableName rhs = new TableName(rhsTable.getBaseTable());
|
||||
|
||||
TableName joinTable = namingConvention.getM2MJoinTableName(lhs, rhs);
|
||||
|
||||
return joinTable.getQualifiedName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
|
||||
@@ -254,7 +254,7 @@ public class DeployUtil {
|
||||
}
|
||||
|
||||
public void setDbJsonBType(DeployBeanProperty prop, DbJsonB dbJsonB) {
|
||||
setDbJsonType(prop, DbType.JSONB, dbJsonB.length());
|
||||
setDbJsonType(prop, DbPlatformType.JSONB, dbJsonB.length());
|
||||
}
|
||||
|
||||
private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength) {
|
||||
@@ -280,9 +280,9 @@ public class DeployUtil {
|
||||
|
||||
switch (dbJsonType) {
|
||||
case JSON:
|
||||
return DbType.JSON;
|
||||
return DbPlatformType.JSON;
|
||||
case JSONB:
|
||||
return DbType.JSONB;
|
||||
return DbPlatformType.JSONB;
|
||||
case VARCHAR:
|
||||
return Types.VARCHAR;
|
||||
case CLOB:
|
||||
@@ -290,7 +290,7 @@ public class DeployUtil {
|
||||
case BLOB:
|
||||
return Types.BLOB;
|
||||
default:
|
||||
return DbType.JSON;
|
||||
return DbPlatformType.JSON;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,11 +323,6 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureRowCount() {
|
||||
return findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return query.findFutureList();
|
||||
@@ -343,11 +338,6 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findRowCount() {
|
||||
return findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findIds() {
|
||||
return query.findIds();
|
||||
|
||||
@@ -53,11 +53,6 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
return rootQuery.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureRowCount() {
|
||||
return findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> findList() {
|
||||
return rootQuery.findList();
|
||||
@@ -73,11 +68,6 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
return rootQuery.findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findRowCount() {
|
||||
return findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> findSet() {
|
||||
return rootQuery.findSet();
|
||||
|
||||
@@ -362,11 +362,6 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
return exprList.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureRowCount() {
|
||||
return findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findIds() {
|
||||
return exprList.findIds();
|
||||
@@ -409,12 +404,7 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
|
||||
@Override
|
||||
public int findCount() {
|
||||
return exprList.findRowCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findRowCount() {
|
||||
return findCount();
|
||||
return exprList.findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -288,6 +288,10 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
throw new IllegalStateException("expecting 3 children for comparison? " + ctx);
|
||||
}
|
||||
String path = getLeftHandSidePath(ctx);
|
||||
String child = child(ctx, 2);
|
||||
if (path.equals(child)) {
|
||||
throw new IllegalArgumentException("Invalid expression "+path+" must be on LHS of expression");
|
||||
}
|
||||
String operator = child(ctx, 1);
|
||||
EqlOperator op = operatorMapping.get(operator);
|
||||
if (op == null) {
|
||||
@@ -295,7 +299,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
}
|
||||
|
||||
// RHS is Path, Literal or Named input parameter
|
||||
helper.addExpression(path, op, child(ctx, 2));
|
||||
helper.addExpression(path, op, child);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@ import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLLexer;
|
||||
import com.avaje.ebeaninternal.server.grammer.antlr.EQLParser;
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.BaseErrorListener;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.Recognizer;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
/**
|
||||
@@ -12,6 +15,8 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
*/
|
||||
public class EqlParser {
|
||||
|
||||
private static final ErrorListener errorListener = new ErrorListener();
|
||||
|
||||
/**
|
||||
* Parse the raw EQL query and apply it to the supplied query.
|
||||
*/
|
||||
@@ -20,6 +25,7 @@ public class EqlParser {
|
||||
EQLLexer lexer = new EQLLexer(new ANTLRInputStream(raw));
|
||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||
EQLParser parser = new EQLParser(tokens);
|
||||
parser.addErrorListener(errorListener);
|
||||
EQLParser.Select_statementContext context = parser.select_statement();
|
||||
|
||||
EqlAdapter<T> adapter = new EqlAdapter<T>(query);
|
||||
@@ -29,4 +35,14 @@ public class EqlParser {
|
||||
|
||||
query.simplifyExpressions();
|
||||
}
|
||||
|
||||
static class ErrorListener extends BaseErrorListener {
|
||||
|
||||
@Override
|
||||
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
|
||||
|
||||
String reportMsg = "line " + line + ":" + charPositionInLine + " " + msg;
|
||||
throw new IllegalArgumentException(reportMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated from /home/rob/github/avaje-ebeanorm/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
// Generated from /home/rob/github/ebean/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
package com.avaje.ebeaninternal.server.grammer.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
// Generated from /home/rob/github/avaje-ebeanorm/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
// Generated from /home/rob/github/ebean/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
package com.avaje.ebeaninternal.server.grammer.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.RuntimeMetaData;
|
||||
import org.antlr.v4.runtime.Vocabulary;
|
||||
import org.antlr.v4.runtime.VocabularyImpl;
|
||||
import org.antlr.v4.runtime.atn.ATN;
|
||||
import org.antlr.v4.runtime.atn.ATNDeserializer;
|
||||
import org.antlr.v4.runtime.atn.LexerATNSimulator;
|
||||
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class EQLLexer extends Lexer {
|
||||
@@ -100,6 +97,12 @@ public class EQLLexer extends Lexer {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void recover(RecognitionException e) {
|
||||
throw new RuntimeException("Error in grammer - " + e.getMessage());
|
||||
}
|
||||
|
||||
|
||||
public EQLLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated from /home/rob/github/avaje-ebeanorm/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
// Generated from /home/rob/github/ebean/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
package com.avaje.ebeaninternal.server.grammer.antlr;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
|
||||
@@ -1,23 +1,13 @@
|
||||
// Generated from /home/rob/github/avaje-ebeanorm/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
// Generated from /home/rob/github/ebean/src/test/resources/EQL.g4 by ANTLR 4.5.3
|
||||
package com.avaje.ebeaninternal.server.grammer.antlr;
|
||||
|
||||
import org.antlr.v4.runtime.NoViableAltException;
|
||||
import org.antlr.v4.runtime.Parser;
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.RecognitionException;
|
||||
import org.antlr.v4.runtime.RuntimeMetaData;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.Vocabulary;
|
||||
import org.antlr.v4.runtime.VocabularyImpl;
|
||||
import org.antlr.v4.runtime.atn.ATN;
|
||||
import org.antlr.v4.runtime.atn.ATNDeserializer;
|
||||
import org.antlr.v4.runtime.atn.ParserATNSimulator;
|
||||
import org.antlr.v4.runtime.atn.PredictionContextCache;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
import org.antlr.v4.runtime.tree.*;
|
||||
import java.util.List;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
|
||||
public class EQLParser extends Parser {
|
||||
@@ -130,6 +120,12 @@ public class EQLParser extends Parser {
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
|
||||
// @Override
|
||||
// public void recover(RecognitionException e) {
|
||||
// throw new RuntimeException("Error in grammer - " + e.getMessage());
|
||||
// }
|
||||
|
||||
public EQLParser(TokenStream input) {
|
||||
super(input);
|
||||
_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
@@ -2178,14 +2174,35 @@ public class EQLParser extends Parser {
|
||||
Comparison_expressionContext _localctx = new Comparison_expressionContext(_ctx, getState());
|
||||
enterRule(_localctx, 72, RULE_comparison_expression);
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(306);
|
||||
match(PATH_VARIABLE);
|
||||
setState(307);
|
||||
comparison_operator();
|
||||
setState(308);
|
||||
value_expression();
|
||||
setState(314);
|
||||
switch (_input.LA(1)) {
|
||||
case PATH_VARIABLE:
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(306);
|
||||
match(PATH_VARIABLE);
|
||||
setState(307);
|
||||
comparison_operator();
|
||||
setState(308);
|
||||
value_expression();
|
||||
}
|
||||
break;
|
||||
case INPUT_VARIABLE:
|
||||
case BOOLEAN_LITERAL:
|
||||
case NUMBER_LITERAL:
|
||||
case STRING_LITERAL:
|
||||
enterOuterAlt(_localctx, 2);
|
||||
{
|
||||
setState(310);
|
||||
value_expression();
|
||||
setState(311);
|
||||
comparison_operator();
|
||||
setState(312);
|
||||
match(PATH_VARIABLE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new NoViableAltException(this);
|
||||
}
|
||||
}
|
||||
catch (RecognitionException re) {
|
||||
@@ -2221,7 +2238,7 @@ public class EQLParser extends Parser {
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(310);
|
||||
setState(316);
|
||||
_la = _input.LA(1);
|
||||
if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << T__44) | (1L << T__45) | (1L << T__46) | (1L << T__47) | (1L << T__48) | (1L << T__49) | (1L << T__50) | (1L << T__51) | (1L << T__52) | (1L << T__53) | (1L << T__54) | (1L << T__55) | (1L << T__56))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@@ -2264,21 +2281,21 @@ public class EQLParser extends Parser {
|
||||
Value_expressionContext _localctx = new Value_expressionContext(_ctx, getState());
|
||||
enterRule(_localctx, 76, RULE_value_expression);
|
||||
try {
|
||||
setState(314);
|
||||
setState(320);
|
||||
switch (_input.LA(1)) {
|
||||
case BOOLEAN_LITERAL:
|
||||
case NUMBER_LITERAL:
|
||||
case STRING_LITERAL:
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(312);
|
||||
setState(318);
|
||||
literal();
|
||||
}
|
||||
break;
|
||||
case INPUT_VARIABLE:
|
||||
enterOuterAlt(_localctx, 2);
|
||||
{
|
||||
setState(313);
|
||||
setState(319);
|
||||
match(INPUT_VARIABLE);
|
||||
}
|
||||
break;
|
||||
@@ -2322,7 +2339,7 @@ public class EQLParser extends Parser {
|
||||
try {
|
||||
enterOuterAlt(_localctx, 1);
|
||||
{
|
||||
setState(316);
|
||||
setState(322);
|
||||
_la = _input.LA(1);
|
||||
if ( !(((((_la - 60)) & ~0x3f) == 0 && ((1L << (_la - 60)) & ((1L << (BOOLEAN_LITERAL - 60)) | (1L << (NUMBER_LITERAL - 60)) | (1L << (STRING_LITERAL - 60)))) != 0)) ) {
|
||||
_errHandler.recoverInline(this);
|
||||
@@ -2343,7 +2360,7 @@ public class EQLParser extends Parser {
|
||||
}
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3D\u0141\4\2\t\2\4"+
|
||||
"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3D\u0147\4\2\t\2\4"+
|
||||
"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
|
||||
"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
|
||||
"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
|
||||
@@ -2365,90 +2382,92 @@ public class EQLParser extends Parser {
|
||||
"\35\3\35\3\35\5\35\u00ff\n\35\3\36\3\36\3\36\3\36\3\36\3\36\3\37\3\37"+
|
||||
"\3\37\3\37\3\37\3\37\3 \3 \3 \3 \3 \5 \u0112\n \3!\3!\3!\3!\3!\3!\3!\3"+
|
||||
"!\5!\u011c\n!\3\"\3\"\3\"\3\"\3\"\5\"\u0123\n\"\3#\3#\3#\3#\3#\3#\3#\3"+
|
||||
"#\5#\u012d\n#\3$\3$\3$\3$\3%\3%\3&\3&\3&\3&\3\'\3\'\3(\3(\5(\u013d\n("+
|
||||
"\3)\3)\3)\2\2*\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,.\60\62\64"+
|
||||
"\668:<>@BDFHJLNP\2\6\3\2\16\17\3\2$+\3\2,;\4\2>?CC\u0141\2S\3\2\2\2\4"+
|
||||
"d\3\2\2\2\6l\3\2\2\2\bn\3\2\2\2\np\3\2\2\2\fs\3\2\2\2\16}\3\2\2\2\20\u0088"+
|
||||
"\3\2\2\2\22\u008a\3\2\2\2\24\u008c\3\2\2\2\26\u0091\3\2\2\2\30\u0094\3"+
|
||||
"\2\2\2\32\u009c\3\2\2\2\34\u00a0\3\2\2\2\36\u00ab\3\2\2\2 \u00ad\3\2\2"+
|
||||
"\2\"\u00b0\3\2\2\2$\u00b5\3\2\2\2&\u00b7\3\2\2\2(\u00bb\3\2\2\2*\u00bf"+
|
||||
"\3\2\2\2,\u00c3\3\2\2\2.\u00cb\3\2\2\2\60\u00d4\3\2\2\2\62\u00dd\3\2\2"+
|
||||
"\2\64\u00ec\3\2\2\2\66\u00ee\3\2\2\28\u00fe\3\2\2\2:\u0100\3\2\2\2<\u0106"+
|
||||
"\3\2\2\2>\u0111\3\2\2\2@\u011b\3\2\2\2B\u0122\3\2\2\2D\u012c\3\2\2\2F"+
|
||||
"\u012e\3\2\2\2H\u0132\3\2\2\2J\u0134\3\2\2\2L\u0138\3\2\2\2N\u013c\3\2"+
|
||||
"\2\2P\u013e\3\2\2\2RT\5\4\3\2SR\3\2\2\2ST\3\2\2\2TX\3\2\2\2UW\5\b\5\2"+
|
||||
"VU\3\2\2\2WZ\3\2\2\2XV\3\2\2\2XY\3\2\2\2Y\\\3\2\2\2ZX\3\2\2\2[]\5\n\6"+
|
||||
"\2\\[\3\2\2\2\\]\3\2\2\2]_\3\2\2\2^`\5\f\7\2_^\3\2\2\2_`\3\2\2\2`b\3\2"+
|
||||
"\2\2ac\5\24\13\2ba\3\2\2\2bc\3\2\2\2c\3\3\2\2\2df\7\3\2\2eg\5\6\4\2fe"+
|
||||
"\3\2\2\2fg\3\2\2\2gh\3\2\2\2hi\7\4\2\2ij\5\34\17\2jk\7\5\2\2k\5\3\2\2"+
|
||||
"\2lm\7\6\2\2m\7\3\2\2\2no\5\30\r\2o\t\3\2\2\2pq\7\7\2\2qr\5,\27\2r\13"+
|
||||
"\3\2\2\2st\7\b\2\2tu\7\t\2\2uz\5\16\b\2vw\7\n\2\2wy\5\16\b\2xv\3\2\2\2"+
|
||||
"y|\3\2\2\2zx\3\2\2\2z{\3\2\2\2{\r\3\2\2\2|z\3\2\2\2}\177\7=\2\2~\u0080"+
|
||||
"\5\22\n\2\177~\3\2\2\2\177\u0080\3\2\2\2\u0080\u0082\3\2\2\2\u0081\u0083"+
|
||||
"\5\20\t\2\u0082\u0081\3\2\2\2\u0082\u0083\3\2\2\2\u0083\17\3\2\2\2\u0084"+
|
||||
"\u0085\7\13\2\2\u0085\u0089\7\f\2\2\u0086\u0087\7\13\2\2\u0087\u0089\7"+
|
||||
"\r\2\2\u0088\u0084\3\2\2\2\u0088\u0086\3\2\2\2\u0089\21\3\2\2\2\u008a"+
|
||||
"\u008b\t\2\2\2\u008b\23\3\2\2\2\u008c\u008d\7\20\2\2\u008d\u008f\7?\2"+
|
||||
"\2\u008e\u0090\5\26\f\2\u008f\u008e\3\2\2\2\u008f\u0090\3\2\2\2\u0090"+
|
||||
"\25\3\2\2\2\u0091\u0092\7\21\2\2\u0092\u0093\7?\2\2\u0093\27\3\2\2\2\u0094"+
|
||||
"\u0096\7\22\2\2\u0095\u0097\5$\23\2\u0096\u0095\3\2\2\2\u0096\u0097\3"+
|
||||
"\2\2\2\u0097\u0098\3\2\2\2\u0098\u009a\7=\2\2\u0099\u009b\5\32\16\2\u009a"+
|
||||
"\u0099\3\2\2\2\u009a\u009b\3\2\2\2\u009b\31\3\2\2\2\u009c\u009d\7\4\2"+
|
||||
"\2\u009d\u009e\5\34\17\2\u009e\u009f\7\5\2\2\u009f\33\3\2\2\2\u00a0\u00a5"+
|
||||
"\5\36\20\2\u00a1\u00a2\7\n\2\2\u00a2\u00a4\5\36\20\2\u00a3\u00a1\3\2\2"+
|
||||
"\2\u00a4\u00a7\3\2\2\2\u00a5\u00a3\3\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\35"+
|
||||
"\3\2\2\2\u00a7\u00a5\3\2\2\2\u00a8\u00ac\7=\2\2\u00a9\u00ac\5 \21\2\u00aa"+
|
||||
"\u00ac\5\"\22\2\u00ab\u00a8\3\2\2\2\u00ab\u00a9\3\2\2\2\u00ab\u00aa\3"+
|
||||
"\2\2\2\u00ac\37\3\2\2\2\u00ad\u00ae\7\23\2\2\u00ae\u00af\5&\24\2\u00af"+
|
||||
"!\3\2\2\2\u00b0\u00b1\7\23\2\2\u00b1\u00b2\5(\25\2\u00b2#\3\2\2\2\u00b3"+
|
||||
"\u00b6\5&\24\2\u00b4\u00b6\5(\25\2\u00b5\u00b3\3\2\2\2\u00b5\u00b4\3\2"+
|
||||
"\2\2\u00b6%\3\2\2\2\u00b7\u00b9\7\24\2\2\u00b8\u00ba\5*\26\2\u00b9\u00b8"+
|
||||
"\3\2\2\2\u00b9\u00ba\3\2\2\2\u00ba\'\3\2\2\2\u00bb\u00bd\7\25\2\2\u00bc"+
|
||||
"\u00be\5*\26\2\u00bd\u00bc\3\2\2\2\u00bd\u00be\3\2\2\2\u00be)\3\2\2\2"+
|
||||
"\u00bf\u00c0\7\4\2\2\u00c0\u00c1\7?\2\2\u00c1\u00c2\7\5\2\2\u00c2+\3\2"+
|
||||
"\2\2\u00c3\u00c8\5.\30\2\u00c4\u00c5\7\26\2\2\u00c5\u00c7\5.\30\2\u00c6"+
|
||||
"\u00c4\3\2\2\2\u00c7\u00ca\3\2\2\2\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2"+
|
||||
"\2\2\u00c9-\3\2\2\2\u00ca\u00c8\3\2\2\2\u00cb\u00d0\5\60\31\2\u00cc\u00cd"+
|
||||
"\7\27\2\2\u00cd\u00cf\5\60\31\2\u00ce\u00cc\3\2\2\2\u00cf\u00d2\3\2\2"+
|
||||
"\2\u00d0\u00ce\3\2\2\2\u00d0\u00d1\3\2\2\2\u00d1/\3\2\2\2\u00d2\u00d0"+
|
||||
"\3\2\2\2\u00d3\u00d5\7\30\2\2\u00d4\u00d3\3\2\2\2\u00d4\u00d5\3\2\2\2"+
|
||||
"\u00d5\u00d6\3\2\2\2\u00d6\u00d7\5\62\32\2\u00d7\61\3\2\2\2\u00d8\u00de"+
|
||||
"\5\64\33\2\u00d9\u00da\7\4\2\2\u00da\u00db\5,\27\2\u00db\u00dc\7\5\2\2"+
|
||||
"\u00dc\u00de\3\2\2\2\u00dd\u00d8\3\2\2\2\u00dd\u00d9\3\2\2\2\u00de\63"+
|
||||
"\3\2\2\2\u00df\u00ed\5J&\2\u00e0\u00ed\5F$\2\u00e1\u00ed\5:\36\2\u00e2"+
|
||||
"\u00ed\5<\37\2\u00e3\u00ed\5\66\34\2\u00e4\u00ed\5> \2\u00e5\u00ed\5@"+
|
||||
"!\2\u00e6\u00ed\5B\"\2\u00e7\u00ed\5D#\2\u00e8\u00e9\7\4\2\2\u00e9\u00ea"+
|
||||
"\5\64\33\2\u00ea\u00eb\7\5\2\2\u00eb\u00ed\3\2\2\2\u00ec\u00df\3\2\2\2"+
|
||||
"\u00ec\u00e0\3\2\2\2\u00ec\u00e1\3\2\2\2\u00ec\u00e2\3\2\2\2\u00ec\u00e3"+
|
||||
"\3\2\2\2\u00ec\u00e4\3\2\2\2\u00ec\u00e5\3\2\2\2\u00ec\u00e6\3\2\2\2\u00ec"+
|
||||
"\u00e7\3\2\2\2\u00ec\u00e8\3\2\2\2\u00ed\65\3\2\2\2\u00ee\u00ef\7=\2\2"+
|
||||
"\u00ef\u00f0\7\31\2\2\u00f0\u00f1\58\35\2\u00f1\67\3\2\2\2\u00f2\u00ff"+
|
||||
"\7<\2\2\u00f3\u00f4\7\4\2\2\u00f4\u00f9\5N(\2\u00f5\u00f6\7\n\2\2\u00f6"+
|
||||
"\u00f8\5N(\2\u00f7\u00f5\3\2\2\2\u00f8\u00fb\3\2\2\2\u00f9\u00f7\3\2\2"+
|
||||
"\2\u00f9\u00fa\3\2\2\2\u00fa\u00fc\3\2\2\2\u00fb\u00f9\3\2\2\2\u00fc\u00fd"+
|
||||
"\7\5\2\2\u00fd\u00ff\3\2\2\2\u00fe\u00f2\3\2\2\2\u00fe\u00f3\3\2\2\2\u00ff"+
|
||||
"9\3\2\2\2\u0100\u0101\7=\2\2\u0101\u0102\7\32\2\2\u0102\u0103\5N(\2\u0103"+
|
||||
"\u0104\7\27\2\2\u0104\u0105\5N(\2\u0105;\3\2\2\2\u0106\u0107\5N(\2\u0107"+
|
||||
"\u0108\7\32\2\2\u0108\u0109\7=\2\2\u0109\u010a\7\27\2\2\u010a\u010b\7"+
|
||||
"=\2\2\u010b=\3\2\2\2\u010c\u010d\7=\2\2\u010d\u010e\7\33\2\2\u010e\u0112"+
|
||||
"\7\34\2\2\u010f\u0110\7=\2\2\u0110\u0112\7\35\2\2\u0111\u010c\3\2\2\2"+
|
||||
"\u0111\u010f\3\2\2\2\u0112?\3\2\2\2\u0113\u0114\7=\2\2\u0114\u0115\7\33"+
|
||||
"\2\2\u0115\u0116\7\30\2\2\u0116\u011c\7\34\2\2\u0117\u0118\7=\2\2\u0118"+
|
||||
"\u011c\7\36\2\2\u0119\u011a\7=\2\2\u011a\u011c\7\37\2\2\u011b\u0113\3"+
|
||||
"\2\2\2\u011b\u0117\3\2\2\2\u011b\u0119\3\2\2\2\u011cA\3\2\2\2\u011d\u011e"+
|
||||
"\7=\2\2\u011e\u011f\7\33\2\2\u011f\u0123\7 \2\2\u0120\u0121\7=\2\2\u0121"+
|
||||
"\u0123\7!\2\2\u0122\u011d\3\2\2\2\u0122\u0120\3\2\2\2\u0123C\3\2\2\2\u0124"+
|
||||
"\u0125\7=\2\2\u0125\u0126\7\33\2\2\u0126\u0127\7\30\2\2\u0127\u012d\7"+
|
||||
" \2\2\u0128\u0129\7=\2\2\u0129\u012d\7\"\2\2\u012a\u012b\7=\2\2\u012b"+
|
||||
"\u012d\7#\2\2\u012c\u0124\3\2\2\2\u012c\u0128\3\2\2\2\u012c\u012a\3\2"+
|
||||
"\2\2\u012dE\3\2\2\2\u012e\u012f\7=\2\2\u012f\u0130\5H%\2\u0130\u0131\5"+
|
||||
"N(\2\u0131G\3\2\2\2\u0132\u0133\t\3\2\2\u0133I\3\2\2\2\u0134\u0135\7="+
|
||||
"\2\2\u0135\u0136\5L\'\2\u0136\u0137\5N(\2\u0137K\3\2\2\2\u0138\u0139\t"+
|
||||
"\4\2\2\u0139M\3\2\2\2\u013a\u013d\5P)\2\u013b\u013d\7<\2\2\u013c\u013a"+
|
||||
"\3\2\2\2\u013c\u013b\3\2\2\2\u013dO\3\2\2\2\u013e\u013f\t\5\2\2\u013f"+
|
||||
"Q\3\2\2\2 SX\\_bfz\177\u0082\u0088\u008f\u0096\u009a\u00a5\u00ab\u00b5"+
|
||||
"\u00b9\u00bd\u00c8\u00d0\u00d4\u00dd\u00ec\u00f9\u00fe\u0111\u011b\u0122"+
|
||||
"\u012c\u013c";
|
||||
"#\5#\u012d\n#\3$\3$\3$\3$\3%\3%\3&\3&\3&\3&\3&\3&\3&\3&\5&\u013d\n&\3"+
|
||||
"\'\3\'\3(\3(\5(\u0143\n(\3)\3)\3)\2\2*\2\4\6\b\n\f\16\20\22\24\26\30\32"+
|
||||
"\34\36 \"$&(*,.\60\62\64\668:<>@BDFHJLNP\2\6\3\2\16\17\3\2$+\3\2,;\4\2"+
|
||||
">?CC\u0148\2S\3\2\2\2\4d\3\2\2\2\6l\3\2\2\2\bn\3\2\2\2\np\3\2\2\2\fs\3"+
|
||||
"\2\2\2\16}\3\2\2\2\20\u0088\3\2\2\2\22\u008a\3\2\2\2\24\u008c\3\2\2\2"+
|
||||
"\26\u0091\3\2\2\2\30\u0094\3\2\2\2\32\u009c\3\2\2\2\34\u00a0\3\2\2\2\36"+
|
||||
"\u00ab\3\2\2\2 \u00ad\3\2\2\2\"\u00b0\3\2\2\2$\u00b5\3\2\2\2&\u00b7\3"+
|
||||
"\2\2\2(\u00bb\3\2\2\2*\u00bf\3\2\2\2,\u00c3\3\2\2\2.\u00cb\3\2\2\2\60"+
|
||||
"\u00d4\3\2\2\2\62\u00dd\3\2\2\2\64\u00ec\3\2\2\2\66\u00ee\3\2\2\28\u00fe"+
|
||||
"\3\2\2\2:\u0100\3\2\2\2<\u0106\3\2\2\2>\u0111\3\2\2\2@\u011b\3\2\2\2B"+
|
||||
"\u0122\3\2\2\2D\u012c\3\2\2\2F\u012e\3\2\2\2H\u0132\3\2\2\2J\u013c\3\2"+
|
||||
"\2\2L\u013e\3\2\2\2N\u0142\3\2\2\2P\u0144\3\2\2\2RT\5\4\3\2SR\3\2\2\2"+
|
||||
"ST\3\2\2\2TX\3\2\2\2UW\5\b\5\2VU\3\2\2\2WZ\3\2\2\2XV\3\2\2\2XY\3\2\2\2"+
|
||||
"Y\\\3\2\2\2ZX\3\2\2\2[]\5\n\6\2\\[\3\2\2\2\\]\3\2\2\2]_\3\2\2\2^`\5\f"+
|
||||
"\7\2_^\3\2\2\2_`\3\2\2\2`b\3\2\2\2ac\5\24\13\2ba\3\2\2\2bc\3\2\2\2c\3"+
|
||||
"\3\2\2\2df\7\3\2\2eg\5\6\4\2fe\3\2\2\2fg\3\2\2\2gh\3\2\2\2hi\7\4\2\2i"+
|
||||
"j\5\34\17\2jk\7\5\2\2k\5\3\2\2\2lm\7\6\2\2m\7\3\2\2\2no\5\30\r\2o\t\3"+
|
||||
"\2\2\2pq\7\7\2\2qr\5,\27\2r\13\3\2\2\2st\7\b\2\2tu\7\t\2\2uz\5\16\b\2"+
|
||||
"vw\7\n\2\2wy\5\16\b\2xv\3\2\2\2y|\3\2\2\2zx\3\2\2\2z{\3\2\2\2{\r\3\2\2"+
|
||||
"\2|z\3\2\2\2}\177\7=\2\2~\u0080\5\22\n\2\177~\3\2\2\2\177\u0080\3\2\2"+
|
||||
"\2\u0080\u0082\3\2\2\2\u0081\u0083\5\20\t\2\u0082\u0081\3\2\2\2\u0082"+
|
||||
"\u0083\3\2\2\2\u0083\17\3\2\2\2\u0084\u0085\7\13\2\2\u0085\u0089\7\f\2"+
|
||||
"\2\u0086\u0087\7\13\2\2\u0087\u0089\7\r\2\2\u0088\u0084\3\2\2\2\u0088"+
|
||||
"\u0086\3\2\2\2\u0089\21\3\2\2\2\u008a\u008b\t\2\2\2\u008b\23\3\2\2\2\u008c"+
|
||||
"\u008d\7\20\2\2\u008d\u008f\7?\2\2\u008e\u0090\5\26\f\2\u008f\u008e\3"+
|
||||
"\2\2\2\u008f\u0090\3\2\2\2\u0090\25\3\2\2\2\u0091\u0092\7\21\2\2\u0092"+
|
||||
"\u0093\7?\2\2\u0093\27\3\2\2\2\u0094\u0096\7\22\2\2\u0095\u0097\5$\23"+
|
||||
"\2\u0096\u0095\3\2\2\2\u0096\u0097\3\2\2\2\u0097\u0098\3\2\2\2\u0098\u009a"+
|
||||
"\7=\2\2\u0099\u009b\5\32\16\2\u009a\u0099\3\2\2\2\u009a\u009b\3\2\2\2"+
|
||||
"\u009b\31\3\2\2\2\u009c\u009d\7\4\2\2\u009d\u009e\5\34\17\2\u009e\u009f"+
|
||||
"\7\5\2\2\u009f\33\3\2\2\2\u00a0\u00a5\5\36\20\2\u00a1\u00a2\7\n\2\2\u00a2"+
|
||||
"\u00a4\5\36\20\2\u00a3\u00a1\3\2\2\2\u00a4\u00a7\3\2\2\2\u00a5\u00a3\3"+
|
||||
"\2\2\2\u00a5\u00a6\3\2\2\2\u00a6\35\3\2\2\2\u00a7\u00a5\3\2\2\2\u00a8"+
|
||||
"\u00ac\7=\2\2\u00a9\u00ac\5 \21\2\u00aa\u00ac\5\"\22\2\u00ab\u00a8\3\2"+
|
||||
"\2\2\u00ab\u00a9\3\2\2\2\u00ab\u00aa\3\2\2\2\u00ac\37\3\2\2\2\u00ad\u00ae"+
|
||||
"\7\23\2\2\u00ae\u00af\5&\24\2\u00af!\3\2\2\2\u00b0\u00b1\7\23\2\2\u00b1"+
|
||||
"\u00b2\5(\25\2\u00b2#\3\2\2\2\u00b3\u00b6\5&\24\2\u00b4\u00b6\5(\25\2"+
|
||||
"\u00b5\u00b3\3\2\2\2\u00b5\u00b4\3\2\2\2\u00b6%\3\2\2\2\u00b7\u00b9\7"+
|
||||
"\24\2\2\u00b8\u00ba\5*\26\2\u00b9\u00b8\3\2\2\2\u00b9\u00ba\3\2\2\2\u00ba"+
|
||||
"\'\3\2\2\2\u00bb\u00bd\7\25\2\2\u00bc\u00be\5*\26\2\u00bd\u00bc\3\2\2"+
|
||||
"\2\u00bd\u00be\3\2\2\2\u00be)\3\2\2\2\u00bf\u00c0\7\4\2\2\u00c0\u00c1"+
|
||||
"\7?\2\2\u00c1\u00c2\7\5\2\2\u00c2+\3\2\2\2\u00c3\u00c8\5.\30\2\u00c4\u00c5"+
|
||||
"\7\26\2\2\u00c5\u00c7\5.\30\2\u00c6\u00c4\3\2\2\2\u00c7\u00ca\3\2\2\2"+
|
||||
"\u00c8\u00c6\3\2\2\2\u00c8\u00c9\3\2\2\2\u00c9-\3\2\2\2\u00ca\u00c8\3"+
|
||||
"\2\2\2\u00cb\u00d0\5\60\31\2\u00cc\u00cd\7\27\2\2\u00cd\u00cf\5\60\31"+
|
||||
"\2\u00ce\u00cc\3\2\2\2\u00cf\u00d2\3\2\2\2\u00d0\u00ce\3\2\2\2\u00d0\u00d1"+
|
||||
"\3\2\2\2\u00d1/\3\2\2\2\u00d2\u00d0\3\2\2\2\u00d3\u00d5\7\30\2\2\u00d4"+
|
||||
"\u00d3\3\2\2\2\u00d4\u00d5\3\2\2\2\u00d5\u00d6\3\2\2\2\u00d6\u00d7\5\62"+
|
||||
"\32\2\u00d7\61\3\2\2\2\u00d8\u00de\5\64\33\2\u00d9\u00da\7\4\2\2\u00da"+
|
||||
"\u00db\5,\27\2\u00db\u00dc\7\5\2\2\u00dc\u00de\3\2\2\2\u00dd\u00d8\3\2"+
|
||||
"\2\2\u00dd\u00d9\3\2\2\2\u00de\63\3\2\2\2\u00df\u00ed\5J&\2\u00e0\u00ed"+
|
||||
"\5F$\2\u00e1\u00ed\5:\36\2\u00e2\u00ed\5<\37\2\u00e3\u00ed\5\66\34\2\u00e4"+
|
||||
"\u00ed\5> \2\u00e5\u00ed\5@!\2\u00e6\u00ed\5B\"\2\u00e7\u00ed\5D#\2\u00e8"+
|
||||
"\u00e9\7\4\2\2\u00e9\u00ea\5\64\33\2\u00ea\u00eb\7\5\2\2\u00eb\u00ed\3"+
|
||||
"\2\2\2\u00ec\u00df\3\2\2\2\u00ec\u00e0\3\2\2\2\u00ec\u00e1\3\2\2\2\u00ec"+
|
||||
"\u00e2\3\2\2\2\u00ec\u00e3\3\2\2\2\u00ec\u00e4\3\2\2\2\u00ec\u00e5\3\2"+
|
||||
"\2\2\u00ec\u00e6\3\2\2\2\u00ec\u00e7\3\2\2\2\u00ec\u00e8\3\2\2\2\u00ed"+
|
||||
"\65\3\2\2\2\u00ee\u00ef\7=\2\2\u00ef\u00f0\7\31\2\2\u00f0\u00f1\58\35"+
|
||||
"\2\u00f1\67\3\2\2\2\u00f2\u00ff\7<\2\2\u00f3\u00f4\7\4\2\2\u00f4\u00f9"+
|
||||
"\5N(\2\u00f5\u00f6\7\n\2\2\u00f6\u00f8\5N(\2\u00f7\u00f5\3\2\2\2\u00f8"+
|
||||
"\u00fb\3\2\2\2\u00f9\u00f7\3\2\2\2\u00f9\u00fa\3\2\2\2\u00fa\u00fc\3\2"+
|
||||
"\2\2\u00fb\u00f9\3\2\2\2\u00fc\u00fd\7\5\2\2\u00fd\u00ff\3\2\2\2\u00fe"+
|
||||
"\u00f2\3\2\2\2\u00fe\u00f3\3\2\2\2\u00ff9\3\2\2\2\u0100\u0101\7=\2\2\u0101"+
|
||||
"\u0102\7\32\2\2\u0102\u0103\5N(\2\u0103\u0104\7\27\2\2\u0104\u0105\5N"+
|
||||
"(\2\u0105;\3\2\2\2\u0106\u0107\5N(\2\u0107\u0108\7\32\2\2\u0108\u0109"+
|
||||
"\7=\2\2\u0109\u010a\7\27\2\2\u010a\u010b\7=\2\2\u010b=\3\2\2\2\u010c\u010d"+
|
||||
"\7=\2\2\u010d\u010e\7\33\2\2\u010e\u0112\7\34\2\2\u010f\u0110\7=\2\2\u0110"+
|
||||
"\u0112\7\35\2\2\u0111\u010c\3\2\2\2\u0111\u010f\3\2\2\2\u0112?\3\2\2\2"+
|
||||
"\u0113\u0114\7=\2\2\u0114\u0115\7\33\2\2\u0115\u0116\7\30\2\2\u0116\u011c"+
|
||||
"\7\34\2\2\u0117\u0118\7=\2\2\u0118\u011c\7\36\2\2\u0119\u011a\7=\2\2\u011a"+
|
||||
"\u011c\7\37\2\2\u011b\u0113\3\2\2\2\u011b\u0117\3\2\2\2\u011b\u0119\3"+
|
||||
"\2\2\2\u011cA\3\2\2\2\u011d\u011e\7=\2\2\u011e\u011f\7\33\2\2\u011f\u0123"+
|
||||
"\7 \2\2\u0120\u0121\7=\2\2\u0121\u0123\7!\2\2\u0122\u011d\3\2\2\2\u0122"+
|
||||
"\u0120\3\2\2\2\u0123C\3\2\2\2\u0124\u0125\7=\2\2\u0125\u0126\7\33\2\2"+
|
||||
"\u0126\u0127\7\30\2\2\u0127\u012d\7 \2\2\u0128\u0129\7=\2\2\u0129\u012d"+
|
||||
"\7\"\2\2\u012a\u012b\7=\2\2\u012b\u012d\7#\2\2\u012c\u0124\3\2\2\2\u012c"+
|
||||
"\u0128\3\2\2\2\u012c\u012a\3\2\2\2\u012dE\3\2\2\2\u012e\u012f\7=\2\2\u012f"+
|
||||
"\u0130\5H%\2\u0130\u0131\5N(\2\u0131G\3\2\2\2\u0132\u0133\t\3\2\2\u0133"+
|
||||
"I\3\2\2\2\u0134\u0135\7=\2\2\u0135\u0136\5L\'\2\u0136\u0137\5N(\2\u0137"+
|
||||
"\u013d\3\2\2\2\u0138\u0139\5N(\2\u0139\u013a\5L\'\2\u013a\u013b\7=\2\2"+
|
||||
"\u013b\u013d\3\2\2\2\u013c\u0134\3\2\2\2\u013c\u0138\3\2\2\2\u013dK\3"+
|
||||
"\2\2\2\u013e\u013f\t\4\2\2\u013fM\3\2\2\2\u0140\u0143\5P)\2\u0141\u0143"+
|
||||
"\7<\2\2\u0142\u0140\3\2\2\2\u0142\u0141\3\2\2\2\u0143O\3\2\2\2\u0144\u0145"+
|
||||
"\t\5\2\2\u0145Q\3\2\2\2!SX\\_bfz\177\u0082\u0088\u008f\u0096\u009a\u00a5"+
|
||||
"\u00ab\u00b5\u00b9\u00bd\u00c8\u00d0\u00d4\u00dd\u00ec\u00f9\u00fe\u0111"+
|
||||
"\u011b\u0122\u012c\u013c\u0142";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.server.core.DbExpressionHandler;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
@@ -321,7 +321,7 @@ public class Binder {
|
||||
b.setBytes((byte[]) data);
|
||||
break;
|
||||
|
||||
case DbType.UUID:
|
||||
case DbPlatformType.UUID:
|
||||
// native UUID support in H2 and Postgres
|
||||
b.setObject(data);
|
||||
break;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.persist.dml;
|
||||
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
|
||||
@@ -49,10 +48,5 @@ public class DeleteHandler extends DmlHandler {
|
||||
checkRowCount(rowCount);
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDerivedRelationship(DerivedRelationshipData assocBean) {
|
||||
throw new RuntimeException("Never called on delete");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
package com.avaje.ebeaninternal.server.persist.dml;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.persist.DmlUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -18,7 +15,6 @@ import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Insert bean handler.
|
||||
@@ -134,30 +130,9 @@ public class InsertHandler extends DmlHandler {
|
||||
}
|
||||
|
||||
checkRowCount(rowCount);
|
||||
executeDerivedRelationships();
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
protected void executeDerivedRelationships() {
|
||||
List<DerivedRelationshipData> derivedRelationships = persistRequest.getDerivedRelationships();
|
||||
if (derivedRelationships != null) {
|
||||
|
||||
SpiEbeanServer ebeanServer = (SpiEbeanServer) persistRequest.getEbeanServer();
|
||||
|
||||
for (int i = 0; i < derivedRelationships.size(); i++) {
|
||||
DerivedRelationshipData derivedRelationshipData = derivedRelationships.get(i);
|
||||
|
||||
BeanDescriptor<?> beanDescriptor = ebeanServer.getBeanDescriptor(derivedRelationshipData.getBean().getClass());
|
||||
|
||||
BeanProperty prop = beanDescriptor.getBeanProperty(derivedRelationshipData.getLogicalName());
|
||||
EntityBean entityBean = (EntityBean) derivedRelationshipData.getBean();
|
||||
entityBean._ebean_getIntercept().markPropertyAsChanged(prop.getPropertyIndex());
|
||||
|
||||
ebeanServer.update(entityBean, transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For non batch insert with generated keys.
|
||||
*/
|
||||
@@ -220,9 +195,4 @@ public class InsertHandler extends DmlHandler {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDerivedRelationship(DerivedRelationshipData derivedRelationship) {
|
||||
persistRequest.getTransaction().registerDerivedRelationship(derivedRelationship);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.persist.dml;
|
||||
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.api.SpiUpdatePlan;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
@@ -74,9 +73,4 @@ public class UpdateHandler extends DmlHandler {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDerivedRelationship(DerivedRelationshipData derivedRelationship) {
|
||||
persistRequest.getTransaction().registerDerivedRelationship(derivedRelationship);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.persist.dmlbind;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Bindable for an ManyToOne or OneToOne associated bean.
|
||||
*/
|
||||
@@ -51,10 +50,8 @@ public class BindableAssocOne implements Bindable {
|
||||
// this is the scenario for a derived foreign key
|
||||
// which will require an additional update
|
||||
// register for post insert of assocBean
|
||||
// update of bean set ... importedId.getLogicalName();
|
||||
// value of assocBean.getId
|
||||
DerivedRelationshipData d = new DerivedRelationshipData(assocBean, assocOne.getName(), bean);
|
||||
request.registerDerivedRelationship(d);
|
||||
// update of bean set importedId
|
||||
request.getPersistRequest().deferredRelationship(assocBean, importedId, bean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.persist.dmlbind;
|
||||
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
@@ -54,8 +53,6 @@ public interface BindableRequest {
|
||||
*/
|
||||
PersistRequestBean<?> getPersistRequest();
|
||||
|
||||
void registerDerivedRelationship(DerivedRelationshipData assocBean);
|
||||
|
||||
/**
|
||||
* Return the system current time in millis. This is expected to the same time used
|
||||
* by multiple generated properties for a single request.
|
||||
|
||||
@@ -83,6 +83,11 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
*/
|
||||
private EntityBean currentBean;
|
||||
|
||||
/**
|
||||
* Caches hasNext for consecutive hasNext() calls.
|
||||
*/
|
||||
private boolean hasNextCache;
|
||||
|
||||
private final BeanPropertyAssocMany<?> lazyLoadManyProperty;
|
||||
|
||||
private Object lazyLoadParentId;
|
||||
@@ -504,6 +509,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (auditFindIterate) {
|
||||
auditIterateNextBean();
|
||||
}
|
||||
hasNextCache = false;
|
||||
return nextBean;
|
||||
}
|
||||
|
||||
@@ -513,7 +519,11 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (noMoreRows || cancelled || loadedBeanCount >= maxRowsLimit) {
|
||||
return false;
|
||||
}
|
||||
return readNextBean();
|
||||
if (hasNextCache) {
|
||||
return true;
|
||||
}
|
||||
hasNextCache = readNextBean();
|
||||
return hasNextCache;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +222,8 @@ public class DefaultDbSqlContext implements DbSqlContext {
|
||||
sb.append(" ");
|
||||
if (joinType == SqlJoinType.OUTER) {
|
||||
if ("join".equals(sqlFormulaJoin.substring(0, 4).toLowerCase())) {
|
||||
// prepend left outer as we are in the 'many' part
|
||||
append(" left outer ");
|
||||
// prepend left as we are in the 'many' part
|
||||
append(" left ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class DefaultSqlRow implements SqlRow {
|
||||
/**
|
||||
* The underlying map of property data.
|
||||
*/
|
||||
final Map<String, Object> map;
|
||||
private final Map<String, Object> map;
|
||||
|
||||
/**
|
||||
* Create with an initialCapacity and loadFactor.
|
||||
@@ -59,14 +59,19 @@ public class DefaultSqlRow implements SqlRow {
|
||||
return map.keySet().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keys internally always lower cased to take out differences in database dictionaries.
|
||||
*/
|
||||
private Object asKey(Object name) {
|
||||
return ((String) name).toLowerCase();
|
||||
}
|
||||
|
||||
public Object remove(Object name) {
|
||||
name = ((String) name).toLowerCase();
|
||||
return map.remove(name);
|
||||
return map.remove(asKey(name));
|
||||
}
|
||||
|
||||
public Object get(Object name) {
|
||||
name = ((String) name).toLowerCase();
|
||||
return map.get(name);
|
||||
return map.get(asKey(name));
|
||||
}
|
||||
|
||||
public Object put(String name, Object value) {
|
||||
@@ -78,66 +83,51 @@ public class DefaultSqlRow implements SqlRow {
|
||||
}
|
||||
|
||||
private Object setInternal(String name, Object newValue) {
|
||||
// MapBean properties are always lowercase
|
||||
name = name.toLowerCase();
|
||||
|
||||
// valueList = null;
|
||||
return map.put(name, newValue);
|
||||
return map.put(name.toLowerCase(), newValue);
|
||||
}
|
||||
|
||||
public UUID getUUID(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toUUID(val);
|
||||
return BasicTypeConverter.toUUID(get(name));
|
||||
}
|
||||
|
||||
public Boolean getBoolean(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toBoolean(val, dbTrueValue);
|
||||
return BasicTypeConverter.toBoolean(get(name), dbTrueValue);
|
||||
}
|
||||
|
||||
public Integer getInteger(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toInteger(val);
|
||||
return BasicTypeConverter.toInteger(get(name));
|
||||
}
|
||||
|
||||
public BigDecimal getBigDecimal(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toBigDecimal(val);
|
||||
return BasicTypeConverter.toBigDecimal(get(name));
|
||||
}
|
||||
|
||||
public Long getLong(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toLong(val);
|
||||
return BasicTypeConverter.toLong(get(name));
|
||||
}
|
||||
|
||||
public Double getDouble(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toDouble(val);
|
||||
return BasicTypeConverter.toDouble(get(name));
|
||||
}
|
||||
|
||||
public Float getFloat(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toFloat(val);
|
||||
return BasicTypeConverter.toFloat(get(name));
|
||||
}
|
||||
|
||||
public String getString(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toString(val);
|
||||
return BasicTypeConverter.toString(get(name));
|
||||
}
|
||||
|
||||
public java.util.Date getUtilDate(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toUtilDate(val);
|
||||
return BasicTypeConverter.toUtilDate(get(name));
|
||||
}
|
||||
|
||||
public Date getDate(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toDate(val);
|
||||
return BasicTypeConverter.toDate(get(name));
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(String name) {
|
||||
Object val = get(name);
|
||||
return BasicTypeConverter.toTimestamp(val);
|
||||
return BasicTypeConverter.toTimestamp(get(name));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -152,8 +142,7 @@ public class DefaultSqlRow implements SqlRow {
|
||||
}
|
||||
|
||||
public boolean containsKey(Object key) {
|
||||
key = ((String) key).toLowerCase();
|
||||
return map.containsKey(key);
|
||||
return map.containsKey(asKey(key));
|
||||
}
|
||||
|
||||
public boolean containsValue(Object value) {
|
||||
|
||||
@@ -47,10 +47,6 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
getFutureCount();
|
||||
}
|
||||
|
||||
public void loadRowCount() {
|
||||
loadCount();
|
||||
}
|
||||
|
||||
public Future<Integer> getFutureCount() {
|
||||
synchronized (monitor) {
|
||||
if (futureRowCount == null) {
|
||||
@@ -60,10 +56,6 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public Future<Integer> getFutureRowCount() {
|
||||
return getFutureCount();
|
||||
}
|
||||
|
||||
public List<T> getList() {
|
||||
synchronized (monitor) {
|
||||
if (list == null) {
|
||||
@@ -73,6 +65,14 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPageIndex() {
|
||||
if (firstRow == 0) {
|
||||
return 0;
|
||||
}
|
||||
return ((firstRow - 1) / maxRows) + 1;
|
||||
}
|
||||
|
||||
public int getTotalPageCount() {
|
||||
|
||||
int rowCount = getTotalCount();
|
||||
@@ -102,10 +102,6 @@ public class LimitOffsetPagedList<T> implements PagedList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public int getTotalRowCount() {
|
||||
return getTotalCount();
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return (firstRow + maxRows) < getTotalCount();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public enum SqlJoinType {
|
||||
/**
|
||||
* It is an outer join.
|
||||
*/
|
||||
OUTER("left outer join"),
|
||||
OUTER("left join"),
|
||||
|
||||
/**
|
||||
* It is automatically determined based on cardinality and optionality.
|
||||
|
||||
@@ -494,9 +494,6 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (desc.isSoftDelete()) {
|
||||
query.addSoftDeletePredicate(desc.getSoftDeletePredicate(baseTableAlias));
|
||||
}
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
children[i].addSoftDeletePredicate(query);
|
||||
}
|
||||
}
|
||||
|
||||
public void addAsOfTableAlias(SpiQuery<?> query) {
|
||||
@@ -522,6 +519,16 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
*/
|
||||
public SqlJoinType appendFromBaseTable(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
SqlJoinType sqlJoinType = appendFromAsJoin(ctx, joinType);
|
||||
if (desc.isSoftDelete()) {
|
||||
// add the soft delete predicate to the join clause
|
||||
ctx.append("and ").append(desc.getSoftDeletePredicate(ctx.getTableAlias(prefix))).append(" ");
|
||||
}
|
||||
return sqlJoinType;
|
||||
}
|
||||
|
||||
private SqlJoinType appendFromAsJoin(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
|
||||
if (nodeBeanProp instanceof BeanPropertyAssocMany<?>) {
|
||||
BeanPropertyAssocMany<?> manyProp = (BeanPropertyAssocMany<?>) nodeBeanProp;
|
||||
if (manyProp.isManyToMany()) {
|
||||
|
||||
@@ -105,7 +105,7 @@ public class SqlTreeNodeExtraJoin implements SqlTreeNode {
|
||||
}
|
||||
|
||||
if (pathContainsMany) {
|
||||
// "promote" to left outer as the path contains a many
|
||||
// "promote" to left join as the path contains a many
|
||||
joinType = SqlJoinType.OUTER;
|
||||
}
|
||||
if (!manyToMany) {
|
||||
|
||||
@@ -1099,11 +1099,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return server.findCount(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findRowCount() {
|
||||
return findCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
|
||||
server.findEachWhile(this, consumer, null);
|
||||
@@ -1177,11 +1172,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return server.findFutureCount(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureRowCount() {
|
||||
return findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagedList<T> findPagedList() {
|
||||
return server.findPagedList(this, null);
|
||||
|
||||
@@ -8,11 +8,11 @@ import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform.OnQueryOnly;
|
||||
import com.avaje.ebean.event.changelog.BeanChange;
|
||||
import com.avaje.ebean.event.changelog.ChangeSet;
|
||||
import com.avaje.ebeaninternal.api.DerivedRelationshipData;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.api.TransactionEvent;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequest;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.core.PersistDeferredRelationship;
|
||||
import com.avaje.ebeaninternal.server.lib.util.Str;
|
||||
import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
import org.slf4j.Logger;
|
||||
@@ -136,8 +136,6 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
|
||||
protected HashMap<String, String> m2mIntersectionSave;
|
||||
|
||||
protected HashMap<Integer, List<DerivedRelationshipData>> derivedRelMap;
|
||||
|
||||
protected Map<String, Object> userObjects;
|
||||
|
||||
protected List<TransactionCallback> callbackList;
|
||||
@@ -146,6 +144,8 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
|
||||
protected TChangeLogHolder changeLogHolder;
|
||||
|
||||
protected List<PersistDeferredRelationship> deferredList;
|
||||
|
||||
/**
|
||||
* The mode for updating doc store indexes for this transaction.
|
||||
* Only set when you want to override the default behavior.
|
||||
@@ -334,26 +334,11 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DerivedRelationshipData> getDerivedRelationship(Object bean) {
|
||||
if (derivedRelMap == null) {
|
||||
return null;
|
||||
public void registerDeferred(PersistDeferredRelationship derived) {
|
||||
if (deferredList == null) {
|
||||
deferredList = new ArrayList<PersistDeferredRelationship>();
|
||||
}
|
||||
return derivedRelMap.get(System.identityHashCode(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerDerivedRelationship(DerivedRelationshipData derivedRelationship) {
|
||||
if (derivedRelMap == null) {
|
||||
derivedRelMap = new HashMap<Integer, List<DerivedRelationshipData>>();
|
||||
}
|
||||
Integer key = System.identityHashCode(derivedRelationship.getAssocBean());
|
||||
|
||||
List<DerivedRelationshipData> list = derivedRelMap.get(key);
|
||||
if (list == null) {
|
||||
list = new ArrayList<DerivedRelationshipData>();
|
||||
derivedRelMap.put(key, list);
|
||||
}
|
||||
list.add(derivedRelationship);
|
||||
deferredList.add(derived);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -715,9 +700,22 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
if (!isActive()) {
|
||||
throw new IllegalStateException(illegalStateMessage);
|
||||
}
|
||||
internalBatchFlush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush the JDBC batch and execute derived relationship statements if necessary.
|
||||
*/
|
||||
private void internalBatchFlush() {
|
||||
if (batchControl != null) {
|
||||
batchControl.flush();
|
||||
}
|
||||
if (deferredList != null) {
|
||||
for (PersistDeferredRelationship deferred : deferredList) {
|
||||
deferred.execute(this);
|
||||
}
|
||||
deferredList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -886,9 +884,7 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
* Batch flush, jdbc commit, trigger registered TransactionCallbacks, notify l2 cache etc.
|
||||
*/
|
||||
private void flushCommitAndNotify() throws SQLException {
|
||||
if (batchControl != null && !batchControl.isEmpty()) {
|
||||
batchControl.flush();
|
||||
}
|
||||
internalBatchFlush();
|
||||
firePreCommit();
|
||||
// only performCommit can throw an exception
|
||||
performCommit();
|
||||
|
||||
@@ -10,8 +10,9 @@ import com.avaje.ebean.config.JsonConfig;
|
||||
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.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.dbmigration.DbOffline;
|
||||
import com.avaje.ebean.plugin.ExtraTypeFactory;
|
||||
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutable;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
|
||||
@@ -65,9 +66,11 @@ import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Currency;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
@@ -208,6 +211,8 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
initialiseJodaTypes(jsonDateTime, config);
|
||||
initialiseJacksonTypes(config);
|
||||
|
||||
loadTypesFromProviders(config, objectMapper);
|
||||
|
||||
if (bootupClasses != null) {
|
||||
initialiseCustomScalarTypes(jsonDateTime, bootupClasses);
|
||||
initialiseScalarConverters(bootupClasses);
|
||||
@@ -215,6 +220,24 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load custom scalar types registered via ExtraTypeFactory and ServiceLoader.
|
||||
*/
|
||||
private void loadTypesFromProviders(ServerConfig config, Object objectMapper) {
|
||||
|
||||
ServiceLoader<ExtraTypeFactory> factories = ServiceLoader.load(ExtraTypeFactory.class);
|
||||
Iterator<ExtraTypeFactory> iterator = factories.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
// use the cacheFactory (via classpath service loader)
|
||||
ExtraTypeFactory plugin = iterator.next();
|
||||
List<? extends ScalarType> types = plugin.createTypes(config, objectMapper);
|
||||
for (ScalarType type : types) {
|
||||
logger.debug("adding ScalarType {}", type.getClass());
|
||||
addCustomType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isPostgres(DatabasePlatform databasePlatform) {
|
||||
return databasePlatform.getName().toLowerCase().startsWith("postgre");
|
||||
}
|
||||
@@ -421,9 +444,9 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
return jsonNodeBlob;
|
||||
case Types.CLOB:
|
||||
return jsonNodeClob;
|
||||
case DbType.JSONB:
|
||||
case DbPlatformType.JSONB:
|
||||
return jsonNodeJsonb;
|
||||
case DbType.JSON:
|
||||
case DbPlatformType.JSON:
|
||||
return jsonNodeJson;
|
||||
default:
|
||||
return jsonNodeJson;
|
||||
@@ -688,27 +711,26 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
|
||||
customScalarTypes.add(longToTimestamp);
|
||||
|
||||
List<Class<?>> foundTypes = bootupClasses.getScalarTypes();
|
||||
List<Class<? extends ScalarType<?>>> foundTypes = bootupClasses.getScalarTypes();
|
||||
|
||||
for (int i = 0; i < foundTypes.size(); i++) {
|
||||
Class<?> cls = foundTypes.get(i);
|
||||
Class<? extends ScalarType<?>> cls = foundTypes.get(i);
|
||||
try {
|
||||
|
||||
ScalarType<?> scalarType;
|
||||
if (objectMapper == null) {
|
||||
scalarType = (ScalarType<?>) cls.newInstance();
|
||||
scalarType = cls.newInstance();
|
||||
} else {
|
||||
try {
|
||||
// first try objectMapper constructor
|
||||
Constructor<?> constructor = cls.getConstructor(ObjectMapper.class);
|
||||
scalarType = (ScalarType<?>) constructor.newInstance((ObjectMapper) objectMapper);
|
||||
Constructor<? extends ScalarType<?>> constructor = cls.getConstructor(ObjectMapper.class);
|
||||
scalarType = constructor.newInstance((ObjectMapper) objectMapper);
|
||||
} catch (NoSuchMethodException e) {
|
||||
scalarType = (ScalarType<?>) cls.newInstance();
|
||||
scalarType = cls.newInstance();
|
||||
}
|
||||
}
|
||||
|
||||
add(scalarType);
|
||||
customScalarTypes.add(scalarType);
|
||||
addCustomType(scalarType);
|
||||
|
||||
} catch (Exception e) {
|
||||
String msg = "Error loading ScalarType [" + cls.getName() + "]";
|
||||
@@ -717,6 +739,11 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
}
|
||||
}
|
||||
|
||||
private void addCustomType(ScalarType<?> scalarType) {
|
||||
add(scalarType);
|
||||
customScalarTypes.add(scalarType);
|
||||
}
|
||||
|
||||
private Object initObjectMapper(ServerConfig serverConfig) {
|
||||
|
||||
Object objectMapper = serverConfig.getObjectMapper();
|
||||
@@ -730,7 +757,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected void initialiseScalarConverters(BootupClasses bootupClasses) {
|
||||
|
||||
List<Class<?>> foundTypes = bootupClasses.getScalarConverters();
|
||||
List<Class<? extends ScalarTypeConverter<?, ?>>> foundTypes = bootupClasses.getScalarConverters();
|
||||
|
||||
for (int i = 0; i < foundTypes.size(); i++) {
|
||||
Class<?> cls = foundTypes.get(i);
|
||||
@@ -766,7 +793,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
|
||||
protected void initialiseCompoundTypes(BootupClasses bootupClasses) {
|
||||
|
||||
List<Class<?>> compoundTypes = bootupClasses.getCompoundTypes();
|
||||
List<Class<? extends CompoundType<?>>> compoundTypes = bootupClasses.getCompoundTypes();
|
||||
for (int j = 0; j < compoundTypes.size(); j++) {
|
||||
|
||||
Class<?> type = compoundTypes.get(j);
|
||||
@@ -939,7 +966,7 @@ public final class DefaultTypeManager implements TypeManager, KnownImmutable {
|
||||
int platformClobType = databasePlatform.getClobDbType();
|
||||
int platformBlobType = databasePlatform.getBlobDbType();
|
||||
|
||||
nativeMap.put(DbType.HSTORE, hstoreType);
|
||||
nativeMap.put(DbPlatformType.HSTORE, hstoreType);
|
||||
|
||||
ScalarType<?> utilDateType = extraTypeFactory.createUtilDate(mode);
|
||||
typeMap.put(java.util.Date.class, utilDateType);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -22,9 +22,9 @@ public class ScalarTypeJsonList {
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docType) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbType.JSONB:
|
||||
case DbPlatformType.JSONB:
|
||||
return new ScalarTypeJsonList.JsonB(docType);
|
||||
case DbType.JSON:
|
||||
case DbPlatformType.JSON:
|
||||
return new ScalarTypeJsonList.Json(docType);
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class ScalarTypeJsonList {
|
||||
*/
|
||||
private static class Json extends ScalarTypeJsonList.PgBase {
|
||||
public Json(DocPropertyType docType) {
|
||||
super(DbType.JSON, PostgresHelper.JSON_TYPE, docType);
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ScalarTypeJsonList {
|
||||
*/
|
||||
private static class JsonB extends ScalarTypeJsonList.PgBase {
|
||||
public JsonB(DocPropertyType docType) {
|
||||
super(DbType.JSONB, PostgresHelper.JSONB_TYPE, docType);
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebeaninternal.util.EncodeUtil;
|
||||
@@ -41,9 +41,9 @@ public abstract class ScalarTypeJsonMap extends ScalarTypeBase<Map> {
|
||||
return BLOB;
|
||||
case Types.CLOB:
|
||||
return CLOB;
|
||||
case DbType.JSONB:
|
||||
case DbPlatformType.JSONB:
|
||||
return postgres ? JSONB : CLOB;
|
||||
case DbType.JSON:
|
||||
case DbPlatformType.JSON:
|
||||
return postgres ? JSON : CLOB;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown dbType " + dbType);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
@@ -30,7 +30,7 @@ public abstract class ScalarTypeJsonMapPostgres extends ScalarTypeJsonMap {
|
||||
public static class JSON extends ScalarTypeJsonMapPostgres {
|
||||
|
||||
public JSON() {
|
||||
super(DbType.JSON, PostgresHelper.JSON_TYPE);
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public abstract class ScalarTypeJsonMapPostgres extends ScalarTypeJsonMap {
|
||||
public static class JSONB extends ScalarTypeJsonMapPostgres {
|
||||
|
||||
public JSONB() {
|
||||
super(DbType.JSONB, PostgresHelper.JSONB_TYPE);
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@@ -33,7 +33,7 @@ public abstract class ScalarTypeJsonNodePostgres extends ScalarTypeJsonNode {
|
||||
public static class JSON extends ScalarTypeJsonNodePostgres {
|
||||
|
||||
public JSON(ObjectMapper objectMapper) {
|
||||
super(objectMapper, DbType.JSON, PostgresHelper.JSON_TYPE);
|
||||
super(objectMapper, DbPlatformType.JSON, PostgresHelper.JSON_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class ScalarTypeJsonNodePostgres extends ScalarTypeJsonNode {
|
||||
public static class JSONB extends ScalarTypeJsonNodePostgres {
|
||||
|
||||
public JSONB(ObjectMapper objectMapper) {
|
||||
super(objectMapper, DbType.JSONB, PostgresHelper.JSONB_TYPE);
|
||||
super(objectMapper, DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
@@ -45,9 +45,9 @@ public class ScalarTypeJsonObjectMapper {
|
||||
private static String getPostgresType(boolean postgres, int dbType) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbType.JSON:
|
||||
case DbPlatformType.JSON:
|
||||
return PostgresHelper.JSON_TYPE;
|
||||
case DbType.JSONB:
|
||||
case DbPlatformType.JSONB:
|
||||
return PostgresHelper.JSONB_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -25,9 +25,9 @@ public class ScalarTypeJsonSet {
|
||||
public static ScalarType<?> typeFor(boolean postgres, int dbType, DocPropertyType docPropertyType) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbType.JSONB:
|
||||
case DbPlatformType.JSONB:
|
||||
return new ScalarTypeJsonSet.JsonB(docPropertyType);
|
||||
case DbType.JSON:
|
||||
case DbPlatformType.JSON:
|
||||
return new ScalarTypeJsonSet.Json(docPropertyType);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class ScalarTypeJsonSet {
|
||||
*/
|
||||
private static class Json extends ScalarTypeJsonSet.PgBase {
|
||||
public Json(DocPropertyType docPropertyType) {
|
||||
super(DbType.JSON, PostgresHelper.JSON_TYPE, docPropertyType);
|
||||
super(DbPlatformType.JSON, PostgresHelper.JSON_TYPE, docPropertyType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ScalarTypeJsonSet {
|
||||
*/
|
||||
private static class JsonB extends ScalarTypeJsonSet.PgBase {
|
||||
public JsonB(DocPropertyType docPropertyType) {
|
||||
super(DbType.JSONB, PostgresHelper.JSONB_TYPE, docPropertyType);
|
||||
super(DbPlatformType.JSONB, PostgresHelper.JSONB_TYPE, docPropertyType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
@@ -20,7 +20,7 @@ import java.util.Map;
|
||||
public class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
|
||||
|
||||
public ScalarTypePostgresHstore() {
|
||||
super(Map.class, false, DbType.HSTORE);
|
||||
super(Map.class, false, DbPlatformType.HSTORE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyType;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -22,7 +22,7 @@ public abstract class ScalarTypeUUIDBase extends ScalarTypeBase<UUID> implements
|
||||
|
||||
@Override
|
||||
public int getLogicalType() {
|
||||
return DbType.UUID;
|
||||
return DbPlatformType.UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.type;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.UUID;
|
||||
@@ -11,7 +11,7 @@ import java.util.UUID;
|
||||
public class ScalarTypeUUIDNative extends ScalarTypeUUIDBase {
|
||||
|
||||
public ScalarTypeUUIDNative() {
|
||||
super(false, DbType.UUID);
|
||||
super(false, DbPlatformType.UUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user