Compare commits

...
Author SHA1 Message Date
rbygrave d490966025 [maven-release-plugin] prepare release avaje-ebeanorm-4.7.3 2015-06-24 23:50:02 +12:00
rbygrave 5bc0b01a6c #308 - Deprecate BeanFinder ... preference now to use BeanFindController 2015-06-24 23:42:35 +12:00
rbygrave 2bd14db8f7 #308 - Add BeanFindController 2015-06-24 23:36:34 +12:00
rbygrave 17a0933860 #308 - Add BeanFindController 2015-06-24 23:12:34 +12:00
rbygrave 5bb8384567 No effective change - format only 2015-06-24 22:44:08 +12:00
rbygrave 29a6bbb6e6 #312 - Ability to remove deregister BeanPersistListeners removed 2015-06-24 22:32:12 +12:00
rbygrave 46a1324f58 [maven-release-plugin] prepare for next development iteration 2015-06-22 00:22:45 +12:00
rbygrave 8f7199b586 [maven-release-plugin] prepare release avaje-ebeanorm-4.7.2 2015-06-22 00:22:23 +12:00
rbygrave d2c3142de4 WIP on Finder 2015-06-22 00:20:01 +12:00
rbygrave 721a50219d #307 - Add back support for JsonValueAdapter and JsonReadOptions into 4.x 2015-06-21 01:46:23 +12:00
Rob Bygrave f0b8270e5e Update README.md 2015-06-18 00:11:04 +12:00
rbygrave 92232c2afb [maven-release-plugin] prepare for next development iteration 2015-06-17 23:18:58 +12:00
rbygrave 5e68b1a25e [maven-release-plugin] prepare release avaje-ebeanorm-4.7.1 2015-06-17 23:18:36 +12:00
rbygrave 041324d177 #310 - Child bean with @Id long id = 0 ... when cascade saved from parent ... tries to update instead of insert resulting in OptimisticLockingException 2015-06-17 23:16:02 +12:00
rbygrave 7d02a42276 #309 - ScalarTypeConverters for Java8 time datatypes not working 2015-06-17 21:13:48 +12:00
rbygrave 2a900165f0 #305 - ENH: Add EbeanServerFactory.createWithContextClassLoader() to support OSGi 2015-06-03 20:47:58 +12:00
rbygrave e7c40e9552 No effective change - update javadoc on annotations 2015-06-01 12:26:59 +12:00
rbygrave 0d92807308 No effective change - change test code to use Long as @Version on BasicDomain 2015-06-01 12:14:20 +12:00
rbygrave 16f7de30c6 No effective change - format code 2015-06-01 12:11:53 +12:00
rbygrave 3d250b0eca No effective change - format code, tidy 2015-05-30 21:42:50 +12:00
rbygrave 8403adac90 #298 - JndiDataSourceLookup assumes java: prefix 2015-05-30 20:54:51 +12:00
rbygrave c006aa3f48 No effective change - inline String messages 2015-05-30 20:54:12 +12:00
rbygrave dcb7054248 #303 - Change beginTransaction() to use REQUIRED scope by default 2015-05-30 20:10:56 +12:00
rbygrave 12833bc918 Bump pom version to 4.7.1-SNAPSHOT 2015-05-30 19:43:15 +12:00
rbygrave 71d805bc17 #302 - Postgres specific - Rename @ColumnHstore to @DbHstore (deprecate @ColumnHstore ) 2015-05-30 19:41:54 +12:00
rbygrave ab8704e2c9 Bump version in README 2015-05-29 21:52:43 +12:00
rbygrave 327e2baae7 No effective change - format only 2015-05-29 21:52:00 +12:00
rbygrave 6e89c551d5 [maven-release-plugin] prepare for next development iteration 2015-05-29 21:17:29 +12:00
rbygrave 0a3941227f [maven-release-plugin] prepare release avaje-ebeanorm-4.6.3 2015-05-29 21:17:08 +12:00
rbygrave 0013cb1a76 #301 - MySQL specific issue - java.sql.SQLException: Streaming result set com.mysql.jdbc.RowDataDynamic@3ef4415f is still active. No statements may be issued when any streaming result sets a re open and in use on a given connection. Ensure that you have called .close() on any active streaming result sets before attempting more queries 2015-05-29 21:13:30 +12:00
rbygrave 8fe91f66c0 #300 - Stateless update with deleteMissingChildren and JDBC batched inserts on those children ... can delete newly inserted child 2015-05-29 20:51:23 +12:00
rbygrave 053fdf4abb No effective change - format and tidy 2015-05-29 20:49:55 +12:00
rbygrave 24be907dc5 No effective change - improved logging when PooledConnection.close() throws exception 2015-05-29 20:39:54 +12:00
rbygrave 6aa915b420 Fix test for cross database use 2015-05-29 20:38:38 +12:00
rbygrave 40d87af5b1 Fix test for cross database use 2015-05-29 20:38:07 +12:00
rbygrave 75082fe0c0 Fix test for cross database use 2015-05-29 20:37:12 +12:00
rbygrave 7d43f5a3d7 Fix test for cross database use 2015-05-29 20:36:51 +12:00
rbygrave 99203a35a2 No effective change - reformat and tidy 2015-05-29 00:40:47 +12:00
rbygrave 67f427b83e #299 - ENH: Add support for mapping Jackson JsonNode as JSON content to DB including Postgres JSON and JSON types 2015-05-28 22:54:32 +12:00
rbygrave f5a2cf8ff9 #297 - ENH: Add support for mapping Map<String,Object> as JSON content to DB including Postgres JSON and JSON types. 2015-05-28 00:02:57 +12:00
rbygrave 4e1cda691f No effective change - reformat and tidy 2015-05-19 01:35:27 +12:00
rbygrave 64b01324d1 No effective change - reformat and tidy 2015-05-19 01:25:51 +12:00
rbygrave 3cba238073 No effective change - reformat and tidy 2015-05-18 23:23:11 +12:00
rbygrave b5b4a4639f No effective change - reformat and tidy 2015-05-18 22:17:28 +12:00
rbygrave 2d0a179c3b No effective change - reformat and tidy 2015-05-15 00:09:19 +12:00
rbygrave 40f7a0088d No effective change - add tests for ConvertInetAddressesTest and DefaultTypeFactoryTest 2015-05-14 23:22:19 +12:00
rbygrave 6a02a8d69f No effective change - code format and tidy 2015-05-14 22:42:37 +12:00
rbygrave ed18cbcabf No effective change - add test for ConvertInetAddresses 2015-05-14 21:57:38 +12:00
Rob Bygrave 3ce4f2fb35 Merge pull request #294 from andersha/add_distinct_db2
add distinct to db2
2015-05-14 21:35:59 +12:00
Anders H. Abrahamsen 962a27f838 add distinct to db2 2015-05-13 15:52:50 +02:00
rbygrave 2b583cf707 Update README.md 2015-05-13 23:09:49 +12:00
rbygrave ef9ade4f5c [maven-release-plugin] prepare for next development iteration 2015-05-13 22:56:09 +12:00
rbygrave b1b7774a23 [maven-release-plugin] prepare release avaje-ebeanorm-4.6.2 2015-05-13 22:55:48 +12:00
rbygrave c6632bbc25 No effective change - code tidy, remove unused 2015-05-13 22:51:28 +12:00
rbygrave 8c12fc762c No effective change - code tidy, remove unused 2015-05-13 22:30:40 +12:00
rbygrave 8cb0b13ccb No effective change - code tidy, remove unused 2015-05-13 22:01:10 +12:00
rbygrave c2faffb6f4 No effective change - code tidy 2015-05-13 21:58:19 +12:00
rbygrave e17d823c17 No effective change - code tidy 2015-05-13 21:41:23 +12:00
rbygrave 9bf9338ba9 Fix for #293 - Invalid result rows when ManyToMany "fetch joined" with additional child OneToMany or ManyToMany child relationship fetched 2015-05-13 21:01:00 +12:00
rbygrave 0da764ed0c Test for #293 - Invalid result rows when ManyToMany "fetch joined" with additional child OneToMany or ManyToMany child relationship fetched 2015-05-13 21:00:10 +12:00
rbygrave 43003f4a3a No effective change - adjust test to miss cache 2015-05-13 20:54:54 +12:00
rbygrave 7081d3f54a No effective change - remove unused writer Method (left over from dynamic proxy support) 2015-05-13 20:53:51 +12:00
rbygrave cce2c2e28f No effective change - remove unused writer Method (left over from dynamic proxy support) 2015-05-13 20:52:58 +12:00
rbygrave 61ecf16978 No effective change - reformat 2015-05-11 23:59:41 +12:00
rbygrave 9ff4e63c32 #290 - Tries to register abstract class that implements custom ScalarType interface 2015-05-11 23:51:23 +12:00
rbygrave a13fd55f64 [maven-release-plugin] prepare for next development iteration 2015-05-09 08:58:08 +12:00
239 changed files with 10512 additions and 7182 deletions
+7 -1
View File
@@ -12,5 +12,11 @@ Maven Dependency
<dependency>
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm</artifactId>
<version>4.5.5</version>
<version>4.7.1</version>
</dependency>
[Maven central - avaje-ebeanorm](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.avaje.ebeanorm%22%20AND%20a%3A%22avaje-ebeanorm%22 "maven central ebeanorm")
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cavaje-ebeanorm "maven central ebeanorm")
+21 -12
View File
@@ -9,7 +9,7 @@
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm</artifactId>
<version>4.6.1</version>
<version>4.7.3</version>
<packaging>jar</packaging>
<name>avaje-ebeanorm</name>
@@ -55,12 +55,21 @@
<version>1.7.7</version>
</dependency>
<!-- provided scope for JsonNode support -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
<scope>provided</scope>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.4.3</version>
<version>2.5.3</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
@@ -68,6 +77,7 @@
<scope>provided</scope>
</dependency>
<!-- provided scope to read validation annotations Size etc -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
@@ -89,6 +99,14 @@
<scope>provided</scope>
</dependency>
<!-- Provided scope for Postgres JSON/JSONB support -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1201-jdbc41</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
@@ -124,13 +142,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
@@ -254,8 +265,6 @@
<configuration>
<doctitle>Ebean 4</doctitle>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
<!-- <excludePackageNames>com.avaje.ebeaninternal.*:com.avaje.ebean.util</excludePackageNames> -->
<!--<additionalparam>-Xdoclint:none</additionalparam>-->
<source>1.8</source>
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
<excludePackageNames>com.avaje.ebeaninternal.*:com.avaje.ebean.util</excludePackageNames>
+4 -1
View File
@@ -315,7 +315,10 @@ public final class Ebean {
}
/**
* Start a new explicit transaction.
* Start a transaction with 'REQUIRED' semantics.
* <p>
* With REQUIRED semantics if an active transaction already exists that transaction will be used.
* </p>
* <p>
* The transaction is stored in a ThreadLocal variable and typically you only
* need to use the returned Transaction <em>IF</em> you wish to do things like
@@ -509,7 +509,10 @@ public interface EbeanServer {
Transaction createTransaction(TxIsolation isolation);
/**
* Start a new explicit transaction putting it into a ThreadLocal.
* Start a transaction with 'REQUIRED' semantics.
* <p>
* With REQUIRED semantics if an active transaction already exists that transaction will be used.
* </p>
* <p>
* The transaction is stored in a ThreadLocal variable and typically you only
* need to use the returned Transaction <em>IF</em> you wish to do things like
@@ -3,6 +3,7 @@ package com.avaje.ebean;
import com.avaje.ebean.common.SpiContainer;
import com.avaje.ebean.config.ContainerConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
import javax.persistence.PersistenceException;
import java.lang.reflect.Constructor;
@@ -75,6 +76,32 @@ public class EbeanServerFactory {
return server;
}
/**
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
*/
public static synchronized EbeanServer createWithContextClassLoader(ServerConfig config, ClassLoader classLoader) {
ClassLoader currentContextLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
try {
return EbeanServerFactory.create(config);
} finally {
// set the currentContextLoader back
Thread.currentThread().setContextClassLoader(currentContextLoader);
}
}
/**
* Shutdown gracefully all EbeanServers cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
* </p>
*/
public static synchronized void shutdown() {
ShutdownManager.shutdown();
}
private static EbeanServer createInternal(ServerConfig config) {
@@ -55,4 +55,4 @@ public @interface CacheStrategy {
*/
String warmingQuery() default "";
};
}
@@ -44,4 +44,4 @@ public @interface CacheTuning {
* </p>
*/
int maxSecsToLive() default 0;
};
}
@@ -6,8 +6,10 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* Deprecated - please use @DbHstore instead.
* @see DbHstore
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnHstore {
@@ -18,14 +18,17 @@ import java.lang.annotation.Target;
* timestamp value after the insert has occurred. You need to fetch the entity
* back to get the inserted timestamp if you want to used it.
* </p>
*
* <pre class="code">
* &#064;Column(insertable = false, updateable = false)
* Timestamp cretimestamp;
* </pre>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @CreatedTimestamp
* Timestamp whenCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CreatedTimestamp {
};
}
@@ -0,0 +1,26 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used for mapping a Map<String,String> type property to Postgres HSTORE data type.
* <p>
* The Map property should have keys and values of type String.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @DbHstore
* Map<String, String> tags;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbHstore {
}
@@ -0,0 +1,44 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a property holding JSON content.
* <p>
* By default the content will be stored in a DB Clob except on Postgres where DB JSON type is used.
* </p>
* <h3>Example:</h3>
* <pre>{@code
*
* // Store as JSON on Postgres or Clob on other databases
* @DbJson
* Map<String,Object> content;
*
* }</pre>
*
* <h3>Example with JSONB storage</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJson(storage = DbJsonType.JSONB)
* Map<String,Object> content;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbJson {
/**
* Specify the database type used to store the JSON content.
*/
DbJsonType storage() default DbJsonType.JSON;
/**
* For VARCHAR storage specify the column length (defaults to 3000).
*/
int length() default 0;
}
@@ -0,0 +1,39 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a property holding JSON content.
* <p>
* The content will be stored on Postgres using it's JSONB type and as Clob for other databases.
* </p>
* <p>
* This is equivalent to using <code>@DbJson(storage = DbJsonType.JSONB)</code>
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJsonB
* Map<String,Object> content;
*
* }</pre>
*
* <h3>Equivalent to:</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJson(storage = DbJsonType.JSONB)
* Map<String,Object> content;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbJsonB {
}
@@ -0,0 +1,32 @@
package com.avaje.ebean.annotation;
/**
* Specify the DB storage type used to store JSON content.
*/
public enum DbJsonType {
/**
* Store as JSON on Postgres and for other databases store as CLOB.
*/
JSON,
/**
* Store as JSONB on Postgres and for other databases store as CLOB.
*/
JSONB,
/**
* Store as database VARCHAR.
*/
VARCHAR,
/**
* Store as database CLOB.
*/
CLOB,
/**
* Store as database BLOB.
*/
BLOB
}
@@ -28,4 +28,4 @@ public @interface EmbeddedColumns {
*/
String columns() default "";
};
}
@@ -21,4 +21,4 @@ public @interface Encrypted {
* Used to specify the DB column length.
*/
int dbLength() default 0;
};
}
@@ -87,4 +87,4 @@ public @interface EnumMapping {
* The length of DB column if mapping to string values.
*/
int length() default 0;
};
}
@@ -8,19 +8,21 @@ import java.lang.annotation.Target;
/**
* Enables you to specify a value to use to persist for an enum value.
*
* <pre class="code">
* <pre>{@code
*
* public enum Status {
* &#064;EnumValue(&quot;N&quot;)
*
* @EnumValue("N")
* NEW,
*
* &#064;EnumValue(&quot;A&quot;)
* @EnumValue("A")
* ACTIVE,
*
* &#064;EnumValue(&quot;I&quot;)
* @EnumValue("I")
* INACTIVE,
* }
*
* </pre>
* }</pre>
* <p>
* This is an alternative to using the JPA standard approach or Ebean's
* {@link EnumMapping} annotation.
@@ -43,4 +45,4 @@ public @interface EnumValue {
* </p>
*/
String value();
};
}
@@ -12,17 +12,17 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface Expose {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code true}.
*/
public boolean serialize() default true;
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code true}.
*/
boolean serialize() default true;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code true}.
*/
public boolean deserialize() default true;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code true}.
*/
boolean deserialize() default true;
}
@@ -39,30 +39,31 @@ import com.avaje.ebean.Query;
* queries - it needs to be explicitly included.
* </p>
*
* <pre class="code">
* <pre>{@code
*
* // find by Id
* Order o1 = Ebean.find(Order.class)
* .select(&quot;id, totalAmount&quot;)
* .select("id, totalAmount")
* .setId(1).findUnique();
*
* // find list ... using totalAmount in the where clause
* List&lt;Order&gt; list = Ebean.find(Order.class)
* .select(&quot;id, totalAmount&quot;)
* List<Order> list = Ebean.find(Order.class)
* .select("id, totalAmount")
* .where()
* .eq(&quot;status&quot;, Order.Status.NEW)
* .gt(&quot;totalAmount&quot;, 10)
* .eq("status", Order.Status.NEW)
* .gt("totalAmount", 10)
* .findList();
*
* // as a join from customer
* List&lt;Customer&gt; l0 = Ebean.find(Customer.class)
* .select(&quot;id, name&quot;)
* .join(&quot;orders&quot;, &quot;status, totalAmount&quot;)
* List<Customer> l0 = Ebean.find(Customer.class)
* .select("id, name")
* .fetch("orders", "status, totalAmount")
* .where()
* .gt(&quot;id&quot;, 0)
* .gt(&quot;orders.totalAmount&quot;, 10)
* .gt("id", 0)
* .gt("orders.totalAmount", 10)
* .findList();
*
* </pre>
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@@ -94,10 +95,12 @@ public @interface Formula {
* user.
* </p>
*
* <pre class="code">
* <pre>{@code
*
* join (select user_id, count(*) as topic_count from f_topic group by user_id) as _tc on _tc.user_id = ${ta}.id
* </pre>
*
* }</pre>
*/
String join() default "";
};
}
@@ -14,11 +14,11 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface Index {
/**
* Name of the index
*
* @return index name
*/
String value() default "";
/**
* Name of the index
*
* @return index name
*/
String value() default "";
}
@@ -34,4 +34,4 @@ public @interface NamedUpdate {
*/
boolean notifyCache() default true;
};
}
@@ -17,4 +17,4 @@ public @interface NamedUpdates {
*/
NamedUpdate[] value();
};
}
@@ -31,4 +31,4 @@ public @interface PrivateOwned {
*/
boolean cascadeRemove() default true;
};
}
@@ -21,4 +21,4 @@ public @interface Sql {
*/
SqlSelect[] select() default { @SqlSelect };
};
}
@@ -295,4 +295,4 @@ public @interface SqlSelect {
* Set this to true to have debug output when Ebean parses the sql-select.
*/
boolean debug() default false;
};
}
@@ -125,4 +125,4 @@ public @interface Transactional {
*/
Class<? extends Throwable>[] noRollbackFor() default {};
};
}
@@ -31,4 +31,4 @@ public @interface UpdateMode {
*/
boolean updateChangesOnly() default true;
};
}
@@ -13,4 +13,4 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface UpdatedTimestamp {
};
}
@@ -9,26 +9,29 @@ import java.lang.annotation.Target;
* Add an Literal to add to the where clause when a many property (List, Set or
* Map) is loaded or refreshed.
*
* <pre class="code">
* <pre>{@code
*
* // on a OneToMany property...
*
* &#064;OneToMany
* &#064;Where(clause = &quot;deleted='y'&quot;)
* List&lt;Topic&gt; topics;
* </pre>
* @OneToMany
* @Where(clause = "deleted='y'")
* List<Topic> topics;
*
* }</pre>
*
* <p>
* Note that you can include "${ta}" as a place holder for the table alias if
* you need to include the table alias in the clause.
* </p>
*
* <pre class="code">
* <pre>{@code
* // ... including the ${ta} table alias placeholder...
*
* &#064;OneToMany
* &#064;Where(clause = &quot;${ta}.deleted='y'&quot;)
* List&lt;Topic&gt; topics;
* </pre>
* @OneToMany
* @Where(clause = "${ta}.deleted='y'")
* List<Topic> topics;
*
* }</pre>
*
* <p>
* This will be added to the where clause when lazy loading the OneToMany
@@ -48,4 +51,4 @@ public @interface Where {
*/
String clause();
};
}
@@ -69,7 +69,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
if (list == null) {
list = new ArrayList<E>();
}
list.add((E) bean);
if (bean != null) {
list.add((E) bean);
}
}
public boolean checkEmptyLazyLoad() {
@@ -154,7 +156,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
public String toString() {
StringBuffer sb = new StringBuffer(50);
StringBuilder sb = new StringBuilder(50);
sb.append("BeanList ");
if (isReadOnly()) {
sb.append("readOnly ");
@@ -348,7 +350,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = (Object) it.next();
Object o = it.next();
if (list.remove(o)) {
modifyRemoval(o);
changed = true;
@@ -366,7 +368,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
boolean changed = false;
Iterator<E> it = list.iterator();
while (it.hasNext()) {
Object o = (Object) it.next();
Object o = it.next();
if (!c.contains(o)) {
it.remove();
modifyRemoval(o);
@@ -52,12 +52,20 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
return !touched && (map == null || map.isEmpty());
}
@SuppressWarnings("unchecked")
public void internalPutNull() {
if (map == null) {
map = new LinkedHashMap<K, E>();
}
}
@SuppressWarnings("unchecked")
public void internalPut(Object key, Object bean) {
if (map == null) {
map = new LinkedHashMap<K, E>();
}
map.put((K)key, (E)bean);
if (key != null) {
map.put((K) key, (E) bean);
}
}
public void internalAdd(Object bean) {
@@ -62,7 +62,9 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
if (set == null) {
set = new LinkedHashSet<E>();
}
set.add((E) bean);
if (bean != null) {
set.add((E) bean);
}
}
/**
@@ -143,15 +145,8 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
return set;
}
/**
* Returns the underlying set.
*/
public Object getActualCollection() {
return set;
}
public String toString() {
StringBuffer sb = new StringBuffer(50);
StringBuilder sb = new StringBuilder(50);
sb.append("BeanSet ");
if (isReadOnly()) {
sb.append("readOnly ");
@@ -274,7 +269,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = (Object) it.next();
Object o = it.next();
if (set.remove(o)) {
modifyRemoval(o);
changed = true;
@@ -231,6 +231,7 @@ public class ServerConfig {
private boolean uuidStoreAsBinary;
private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
@@ -291,6 +292,7 @@ public class ServerConfig {
private int queryCacheMaxSize = 1000;
private int queryCacheMaxIdleTime = 600;
private int queryCacheMaxTimeToLive = 60*60*6;
private Object objectMapper;
/**
* Construct a Server Configuration for programmatically creating an EbeanServer.
@@ -1539,6 +1541,14 @@ public class ServerConfig {
persistControllers.add(beanPersistController);
}
public List<BeanFindController> getFindControllers() {
return findControllers;
}
public void setFindControllers(List<BeanFindController> findControllers) {
this.findControllers = findControllers;
}
/**
* Return the BeanPersistController instances.
*/
@@ -1818,8 +1828,7 @@ public class ServerConfig {
String classNames = properties.get("classes", null);
if (classNames == null) {
return null;
return classes;
}
List<Class<?>> classes = new ArrayList<Class<?>>();
@@ -1864,4 +1873,12 @@ public class ServerConfig {
return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
}
public Object getObjectMapper() {
return objectMapper;
}
public void setObjectMapper(Object objectMapper) {
this.objectMapper = objectMapper;
}
}
@@ -39,6 +39,12 @@ public class DatabasePlatform {
COMMIT
}
/**
* Set to true for MySql, no other jdbc drivers need this workaround.
*/
protected boolean useExtraTransactionOnIterateSecondaryQueries;
/**
* The behaviour used when ending a read only transaction at read committed isolation level.
*/
@@ -153,6 +159,17 @@ public class DatabasePlatform {
return name;
}
/**
* Return true if the JDBC driver does not allow additional queries to execute
* when a resultSet is being 'streamed' as is the case with findEach() etc.
* <p>
* Honestly, this is a workaround for a stupid MySql JDBC driver limitation.
* </p>
*/
public boolean useExtraTransactionOnIterateSecondaryQueries() {
return useExtraTransactionOnIterateSecondaryQueries;
}
/**
* Return a DB Sequence based IdGenerator.
*
@@ -7,6 +7,9 @@ public class Db2SqlLimiter implements SqlLimiter {
StringBuilder sb = new StringBuilder(512);
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(request.getDbSql());
int maxRows = request.getMaxRows();
@@ -8,6 +8,36 @@ package com.avaje.ebean.config.dbplatform;
*/
public class DbType {
/**
* Type to map Map content to Postgres HSTORE.
*/
public static final int HSTORE = 5000;
/**
* Type to map JSON content to Clob or Postgres JSON type.
*/
public static final int JSON = 5001;
/**
* Type to map JSON content to Clob or Postgres JSONB type.
*/
public static final int JSONB = 5002;
/**
* Type to map JSON content to VARCHAR.
*/
public static final int JSONVarchar = 5003;
/**
* Type to map JSON content to Clob.
*/
public static final int JSONClob = 5004;
/**
* Type to map JSON content to Blob.
*/
public static final int JSONBlob = 5005;
/**
* The data type name (VARCHAR, INTEGER ...)
*/
@@ -36,6 +36,13 @@ public class DbTypeMap {
put(Types.BLOB, new DbType("blob"));
put(Types.CLOB, new DbType("clob"));
put(DbType.JSON, new DbType("clob")); // Postgres maps this to JSON
put(DbType.JSONB, new DbType("clob")); // Postgres maps this to JSONB
put(DbType.JSONClob, new DbType("clob"));
put(DbType.JSONBlob, new DbType("blob"));
put(DbType.JSONVarchar, new DbType("varchar", 1000));
put(Types.LONGVARBINARY, new DbType("longvarbinary"));
put(Types.LONGVARCHAR, new DbType("lonvarchar"));
put(Types.VARBINARY, new DbType("varbinary", 255));
@@ -20,6 +20,7 @@ public class MySqlPlatform extends DatabasePlatform {
public MySqlPlatform() {
super();
this.name = "mysql";
this.useExtraTransactionOnIterateSecondaryQueries = true;
this.likeClause = "like ? escape''";
this.selectCountWithAlias = true;
this.dbEncrypt = new MySqlDbEncrypt();
@@ -13,11 +13,6 @@ import java.sql.Types;
*/
public class PostgresPlatform extends DatabasePlatform {
/**
* Unique jdbc type id defined for hstore type.
*/
public static final int TYPE_HSTORE = 4001;
public PostgresPlatform() {
super();
this.name = "postgres";
@@ -43,8 +38,10 @@ public class PostgresPlatform extends DatabasePlatform {
this.openQuote = "\"";
this.closeQuote = "\"";
dbTypeMap.put(TYPE_HSTORE, new DbType("hstore"));
dbTypeMap.put(DbType.HSTORE, new DbType("hstore"));
dbTypeMap.put(DbType.JSON, new DbType("json"));
dbTypeMap.put(DbType.JSONB, new DbType("jsonb"));
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
dbTypeMap.put(Types.DOUBLE, new DbType("float"));
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
@@ -0,0 +1,54 @@
package com.avaje.ebean.event;
import com.avaje.ebean.bean.BeanCollection;
/**
* Used to override the finding implementation for a bean.
* <p>
* For beans that are not in a JDBC data source you can implement this handle
* bean finding. For example, read a log file building each entry as a bean and
* returning that.
* </p>
* <p>
* There are a number of internal BeanFinders in Ebean to return meta data from
* Ebean at runtime such as query execution statistics etc. See the beans in
* com.avaje.ebean.meta and finders in com.avaje.ebean.server.meta.
* </p>
*/
public interface BeanFindController {
/**
* Return true if this BeanPersistController should be registered for events
* on this entity type.
*/
boolean isRegisterFor(Class<?> cls);
/**
* Return true if this controller should intercept and process this find request.
*
* Return false to allow the default behavior to process the request.
*/
boolean isInterceptFind(BeanQueryRequest<?> request);
/**
* Find a bean using its id or unique predicate.
*/
<T> T find(BeanQueryRequest<T> request);
/**
* Return true if this controller should intercept and process this findMany request.
*
* Return false to allow the default behavior to process the request.
*/
boolean isInterceptFindMany(BeanQueryRequest<?> request);
/**
* Return a List, Set or Map for the given find request.
* <p>
* Note the returning object is cast to a List Set or Map so you do need to
* get the return type right.
* </p>
*/
<T> BeanCollection<T> findMany(BeanQueryRequest<T> request);
}
@@ -3,6 +3,8 @@ package com.avaje.ebean.event;
import com.avaje.ebean.bean.BeanCollection;
/**
* Deprecated in favor of using BeanFindController.
*
* Used to override the finding implementation for a bean.
* <p>
* For beans that are not in a JDBC data source you can implement this handle
@@ -14,6 +16,7 @@ import com.avaje.ebean.bean.BeanCollection;
* Ebean at runtime such as query execution statistics etc. See the beans in
* com.avaje.ebean.meta and finders in com.avaje.ebean.server.meta.
* </p>
* @deprecated
*/
public interface BeanFinder<T> {
@@ -35,14 +35,29 @@ public class EJson {
public static void write(Object object, JsonGenerator jsonGenerator) throws IOException {
EJsonWriter.write(object, jsonGenerator);
}
/**
* Parse the json and return as a Map additionally specifying if the returned map should
* be modify aware meaning that it can detect when it has been modified.
*/
public static Map<String,Object> parseObject(String json, boolean modifyAware) throws IOException {
return EJsonReader.parseObject(json, modifyAware);
}
/**
* Parse the json and return as a Map.
*/
public static Map<String,Object> parseObject(String json) throws IOException {
return EJsonReader.parseObject(json);
}
/**
* Parse the json and return as a Map taking a reader.
*/
public static Map<String,Object> parseObject(Reader reader, boolean modifyAware) throws IOException {
return EJsonReader.parseObject(reader, modifyAware);
}
/**
* Parse the json and return as a Map taking a reader.
*/
@@ -9,6 +9,10 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import com.avaje.ebeaninternal.server.type.ModifyAwareFlag;
import com.avaje.ebeaninternal.server.type.ModifyAwareList;
import com.avaje.ebeaninternal.server.type.ModifyAwareMap;
import com.avaje.ebeaninternal.server.type.ModifyAwareOwner;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
@@ -16,7 +20,12 @@ import com.fasterxml.jackson.core.JsonToken;
class EJsonReader {
static JsonFactory json = new JsonFactory();
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(String json, boolean modifyAware) throws IOException {
return (Map<String, Object>) parse(json, modifyAware);
}
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(String json) throws IOException {
return (Map<String, Object>) parse(json);
@@ -26,7 +35,12 @@ class EJsonReader {
static Map<String, Object> parseObject(Reader reader) throws IOException {
return (Map<String, Object>) parse(reader);
}
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(Reader reader, boolean modifyAware) throws IOException {
return (Map<String, Object>) parse(reader, modifyAware);
}
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(JsonParser parser) throws IOException {
return (Map<String, Object>) parse(parser);
@@ -34,7 +48,7 @@ class EJsonReader {
@SuppressWarnings("unchecked")
static Map<String, Object> parseObject(JsonParser parser, JsonToken token) throws IOException {
return (Map<String, Object>)parse(parser, token);
return (Map<String, Object>)parse(parser, token, false);
}
@SuppressWarnings("unchecked")
@@ -56,40 +70,58 @@ class EJsonReader {
return parse(new StringReader(json));
}
static Object parse(String json, boolean modifyAware) throws IOException {
return parse(new StringReader(json), modifyAware);
}
static Object parse(Reader reader) throws IOException {
return parse(json.createParser(reader));
}
static Object parse(JsonParser parser) throws IOException {
return parse(parser, null);
static Object parse(Reader reader, boolean modifyAware) throws IOException {
return parse(json.createParser(reader), modifyAware);
}
static Object parse(JsonParser parser, JsonToken token) throws IOException {
return new EJsonReader(parser).parseJson(token);
static Object parse(JsonParser parser) throws IOException {
return parse(parser, null, false);
}
static Object parse(JsonParser parser, boolean modifyAware) throws IOException {
return parse(parser, null, modifyAware);
}
static Object parse(JsonParser parser, JsonToken token, boolean modifyAware) throws IOException {
return new EJsonReader(parser, modifyAware).parseJson(token);
}
private final JsonParser parser;
private final boolean modifyAware;
private final ModifyAwareFlag modifyAwareOwner;
private int depth;
private Stack stack;
private Context currentContext;
EJsonReader(JsonParser parser) {
EJsonReader(JsonParser parser, boolean modifyAware) {
this.parser = parser;
this.modifyAware = modifyAware;
this.modifyAwareOwner = (modifyAware) ? new ModifyAwareFlag() : null;
}
private void startArray() {
depth++;
stack.push(currentContext);
currentContext = new ArrayContext();
currentContext = modifyAware ? new ArrayContext(modifyAwareOwner) : new ArrayContext();
}
private void startObject() {
depth++;
stack.push(currentContext);
currentContext = new ObjectContext();
currentContext = modifyAware ? new ObjectContext(modifyAwareOwner) : new ObjectContext();
}
private void endArray() {
@@ -105,6 +137,9 @@ class EJsonReader {
if (!stack.isEmpty()) {
currentContext = stack.pop(currentContext);
}
if (modifyAwareOwner != null) {
modifyAwareOwner.resetMarkedDirty();
}
}
private void setValue(Object value) {
@@ -235,10 +270,18 @@ class EJsonReader {
private static class ObjectContext extends Context {
private final Map<String, Object> map = new LinkedHashMap<String, Object>();
private final Map<String, Object> map;
private String key;
ObjectContext() {
map = new LinkedHashMap<String, Object>();
}
ObjectContext(ModifyAwareOwner owner) {
map = new ModifyAwareMap<String, Object>(owner, new LinkedHashMap<String, Object>());
}
public void popContext(Context temp) {
setValue(temp.getValue());
}
@@ -262,7 +305,15 @@ class EJsonReader {
private static class ArrayContext extends Context {
private final List<Object> values = new ArrayList<Object>();
private final List<Object> values;
ArrayContext() {
values = new ArrayList<Object>();
}
ArrayContext(ModifyAwareOwner owner) {
values = new ModifyAwareList<Object>(owner, new ArrayList<Object>());
}
public void popContext(Context temp) {
values.add(temp.getValue());
@@ -21,6 +21,13 @@ public interface JsonContext {
*/
<T> T toBean(Class<T> rootType, String json) throws JsonIOException;
/**
* Convert json string input into a Bean of a specific type additionally using JsonReadOptions.
*
* @throws JsonIOException When IOException occurs
*/
<T> T toBean(Class<T> rootType, String json, JsonReadOptions options) throws JsonIOException;
/**
* Convert json reader input into a Bean of a specific type.
*
@@ -28,6 +35,13 @@ public interface JsonContext {
*/
<T> T toBean(Class<T> rootType, Reader json) throws JsonIOException;
/**
* Convert json reader input into a Bean of a specific type additionally using JsonReadOptions.
*
* @throws JsonIOException When IOException occurs
*/
<T> T toBean(Class<T> rootType, Reader json, JsonReadOptions options) throws JsonIOException;
/**
* Convert json parser input into a Bean of a specific type.
*
@@ -35,6 +49,13 @@ public interface JsonContext {
*/
<T> T toBean(Class<T> cls, JsonParser parser) throws JsonIOException;
/**
* Convert json parser input into a Bean of a specific type additionally using JsonReadOptions..
*
* @throws JsonIOException When IOException occurs
*/
<T> T toBean(Class<T> cls, JsonParser parser, JsonReadOptions options) throws JsonIOException;
/**
* Convert json string input into a list of beans of a specific type.
*
@@ -42,6 +63,13 @@ public interface JsonContext {
*/
<T> List<T> toList(Class<T> rootType, String json) throws JsonIOException;
/**
* Convert json string input into a list of beans of a specific type additionally using JsonReadOptions.
*
* @throws JsonIOException When IOException occurs
*/
<T> List<T> toList(Class<T> rootType, String json, JsonReadOptions options) throws JsonIOException;
/**
* Convert json reader input into a list of beans of a specific type.
*
@@ -49,12 +77,26 @@ public interface JsonContext {
*/
<T> List<T> toList(Class<T> rootType, Reader json) throws JsonIOException;
/**
* Convert json reader input into a list of beans of a specific type additionally using JsonReadOptions.
*
* @throws JsonIOException When IOException occurs
*/
<T> List<T> toList(Class<T> rootType, Reader json, JsonReadOptions options) throws JsonIOException;
/**
* Convert json parser input into a list of beans of a specific type.
*
* @throws JsonIOException When IOException occurs
*/
<T> List<T> toList(Class<T> cls, JsonParser src) throws JsonIOException;
<T> List<T> toList(Class<T> cls, JsonParser json) throws JsonIOException;
/**
* Convert json parser input into a list of beans of a specific type additionally using JsonReadOptions.
*
* @throws JsonIOException When IOException occurs
*/
<T> List<T> toList(Class<T> cls, JsonParser json, JsonReadOptions options) throws JsonIOException;
/**
* Use the genericType to determine if this should be converted into a List or
@@ -0,0 +1,30 @@
package com.avaje.ebean.text.json;
import java.util.Map;
/**
* Provides for custom handling of json content as it is read.
* <p>
* This visit method is called after all the known properties of the bean have
* been processed. Any JSON elements that could not be mapped to known bean
* properties are available in the unmapped Map.
* </p>
*
* @param <T> The type of entity bean
*/
public interface JsonReadBeanVisitor<T> {
/**
* Visit the bean that has just been processed.
* <p>
* This provides a method of customising the bean and processing any custom
* JSON content.
* </p>
*
* @param bean the bean being processed
* @param unmapped Map of any JSON elements that didn't map to known bean properties
*/
void visit(T bean, Map<String, Object> unmapped);
}
@@ -0,0 +1,47 @@
package com.avaje.ebean.text.json;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Provides the ability to customise the reading of JSON content.
* <p>
* You can register JsonReadBeanVisitors to customise the processing of the
* beans as they are processed and handle any custom JSON elements that
* could not be mapped to bean properties.
* </p>
*/
public class JsonReadOptions {
protected Map<String, JsonReadBeanVisitor<?>> visitorMap;
/**
* Default constructor.
*/
public JsonReadOptions() {
this.visitorMap = new LinkedHashMap<String, JsonReadBeanVisitor<?>>();
}
/**
* Return the map of JsonReadBeanVisitor's.
*/
public Map<String, JsonReadBeanVisitor<?>> getVisitorMap() {
return visitorMap;
}
/**
* Register a JsonReadBeanVisitor for the root level.
*/
public JsonReadOptions addRootVisitor(JsonReadBeanVisitor<?> visitor) {
return addVisitor(null, visitor);
}
/**
* Register a JsonReadBeanVisitor for a given path.
*/
public JsonReadOptions addVisitor(String path, JsonReadBeanVisitor<?> visitor) {
visitorMap.put(path, visitor);
return this;
}
}
@@ -11,16 +11,16 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
*/
public interface LoadBeanBuffer {
public int getBatchSize();
int getBatchSize();
public List<EntityBeanIntercept> getBatch();
List<EntityBeanIntercept> getBatch();
public BeanDescriptor<?> getBeanDescriptor();
BeanDescriptor<?> getBeanDescriptor();
public PersistenceContext getPersistenceContext();
PersistenceContext getPersistenceContext();
public String getFullPath();
String getFullPath();
public void configureQuery(SpiQuery<?> query, String lazyLoadProperty);
void configureQuery(SpiQuery<?> query, String lazyLoadProperty);
}
@@ -14,13 +14,13 @@ public interface LoadContext {
/**
* Return the minimum batch size when using QueryIterator with query joins.
*/
public int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
/**
* Execute any secondary (+query) queries if there are any defined.
* @param parentRequest the originating query request
*/
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
/**
* Register any secondary queries (+query or +lazy) with their
@@ -30,17 +30,17 @@ public interface LoadContext {
* defined query for +query and +lazy execution.
* </p>
*/
public void registerSecondaryQueries(SpiQuery<?> query);
void registerSecondaryQueries(SpiQuery<?> query);
/**
* Return the node for a given path which is used by autofetch profiling.
*/
public ObjectGraphNode getObjectGraphNode(String path);
ObjectGraphNode getObjectGraphNode(String path);
/**
* Return the persistence context used by this query and future lazy loading.
*/
public PersistenceContext getPersistenceContext();
PersistenceContext getPersistenceContext();
/**
* Set the persistence context used by this query and future lazy loading.
@@ -48,16 +48,16 @@ public interface LoadContext {
* Used by query iterator when processing large result sets.
* </p>
*/
public void resetPersistenceContext(PersistenceContext persistenceContext);
void resetPersistenceContext(PersistenceContext persistenceContext);
/**
* Register a Bean for lazy loading.
*/
public void register(String path, EntityBeanIntercept ebi);
void register(String path, EntityBeanIntercept ebi);
/**
* Register a collection for lazy loading.
*/
public void register(String path, BeanCollection<?> bc);
void register(String path, BeanCollection<?> bc);
}
@@ -13,20 +13,20 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
*/
public interface LoadManyBuffer {
public int getBatchSize();
int getBatchSize();
public List<BeanCollection<?>> getBatch();
List<BeanCollection<?>> getBatch();
public BeanPropertyAssocMany<?> getBeanProperty();
BeanPropertyAssocMany<?> getBeanProperty();
public ObjectGraphNode getObjectGraphNode();
ObjectGraphNode getObjectGraphNode();
public BeanDescriptor<?> getBeanDescriptor();
BeanDescriptor<?> getBeanDescriptor();
public PersistenceContext getPersistenceContext();
PersistenceContext getPersistenceContext();
public String getFullPath();
String getFullPath();
public void configureQuery(SpiQuery<?> query);
void configureQuery(SpiQuery<?> query);
}
@@ -48,4 +48,11 @@ public abstract class LoadRequest {
return transaction;
}
/**
* Return true if the parent query is a findIterate() type query.
* So one of - findIterate(), findEach(), findEachWhile() or findVisit().
*/
public boolean isParentFindIterate() {
return parentRequest != null && parentRequest.getQuery().getType() == SpiQuery.Type.ITERATE;
}
}
@@ -14,5 +14,5 @@ public interface LoadSecondaryQuery {
/**
* Execute the secondary query with a given batch size.
*/
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
}
@@ -10,5 +10,5 @@ public interface SpiBackgroundExecutor extends BackgroundExecutor {
/**
* Shutdown any associated thread pools.
*/
public void shutdown();
void shutdown();
}
@@ -4,7 +4,7 @@ import com.avaje.ebean.CallableSql;
public interface SpiCallableSql extends CallableSql {
public BindParams getBindParams();
BindParams getBindParams();
public TransactionEventTable getTransactionEventTable();
TransactionEventTable getTransactionEventTable();
}
@@ -9,6 +9,7 @@ import com.avaje.ebean.config.dbplatform.DatabasePlatform;
* author: Richard Vowles - http://gplus.to/RichardVowles
*/
public interface SpiEbeanPlugin {
/**
* initializes the plugin.
*
@@ -16,7 +17,10 @@ public interface SpiEbeanPlugin {
* @param dbPlatform - the database we are using - this is available from the server, but it is provided for convenience
* @param serverConfig - the configured server information. It allows access to pre-collected information (but not the collector PropertySource, yet)
*/
public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig);
void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig);
public void execute(boolean online);
/**
* Execute the plugin (generate DDL for example).
*/
void execute(boolean online);
}
@@ -26,22 +26,22 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
/**
* For internal use, shutdown of the server invoked by JVM Shutdown.
*/
public void shutdownManaged();
void shutdownManaged();
/**
* Return true if query origins should be collected.
*/
public boolean isCollectQueryOrigins();
boolean isCollectQueryOrigins();
/**
* Return the server configuration.
*/
public ServerConfig getServerConfig();
ServerConfig getServerConfig();
/**
* Return the DatabasePlatform for this server.
*/
public DatabasePlatform getDatabasePlatform();
DatabasePlatform getDatabasePlatform();
/**
* Return a JDBC driver specific handler for batching.
@@ -49,7 +49,7 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
* Required for Oracle specific batch handling.
* </p>
*/
public PstmtBatch getPstmtBatch();
PstmtBatch getPstmtBatch();
/**
* Create an object to represent the current CallStack.
@@ -58,47 +58,47 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
* graph costing.
* </p>
*/
public CallStack createCallStack();
CallStack createCallStack();
/**
* Return the PersistenceContextScope to use defined at query or server level.
*/
public PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query);
PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query);
/**
* Return the DDL generator.
*/
public DdlGenerator getDdlGenerator();
DdlGenerator getDdlGenerator();
/**
* Return the AutoFetchListener.
*/
public AutoFetchManager getAutoFetchManager();
AutoFetchManager getAutoFetchManager();
/**
* Clear the query execution statistics.
*/
public void clearQueryStatistics();
void clearQueryStatistics();
/**
* Return all the descriptors.
*/
public List<BeanDescriptor<?>> getBeanDescriptors();
List<BeanDescriptor<?>> getBeanDescriptors();
/**
* Return the BeanDescriptor for a given type of bean.
*/
public <T> BeanDescriptor<T> getBeanDescriptor(Class<T> type);
<T> BeanDescriptor<T> getBeanDescriptor(Class<T> type);
/**
* Return BeanDescriptor using it's unique id.
*/
public BeanDescriptor<?> getBeanDescriptorById(String descriptorId);
BeanDescriptor<?> getBeanDescriptorById(String descriptorId);
/**
* Return BeanDescriptors mapped to this table.
*/
public List<BeanDescriptor<?>> getBeanDescriptors(String tableName);
List<BeanDescriptor<?>> getBeanDescriptors(String tableName);
/**
* Process committed changes from another framework.
@@ -108,7 +108,7 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
* this to maintain its cache and text indexes appropriately.
* </p>
*/
public void externalModification(TransactionEventTable event);
void externalModification(TransactionEventTable event);
/**
* Create a ServerTransaction.
@@ -116,44 +116,44 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
* To specify to use the default transaction isolation use a value of -1.
* </p>
*/
public SpiTransaction createServerTransaction(boolean isExplicit, int isolationLevel);
SpiTransaction createServerTransaction(boolean isExplicit, int isolationLevel);
/**
* Return the current transaction or null if there is no current transaction.
*/
public SpiTransaction getCurrentServerTransaction();
SpiTransaction getCurrentServerTransaction();
/**
* Create a ScopeTrans for a method for the given scope definition.
*/
public ScopeTrans createScopeTrans(TxScope txScope);
ScopeTrans createScopeTrans(TxScope txScope);
/**
* Create a ServerTransaction for query purposes.
*/
public SpiTransaction createQueryTransaction();
SpiTransaction createQueryTransaction();
/**
* An event from another server in the cluster used to notify local
* BeanListeners of remote inserts updates and deletes.
*/
public void remoteTransactionEvent(RemoteTransactionEvent event);
void remoteTransactionEvent(RemoteTransactionEvent event);
/**
* Create a query request object.
*/
public <T> SpiOrmQueryRequest<T> createQueryRequest(BeanDescriptor<T> desc, SpiQuery<T> q,
<T> SpiOrmQueryRequest<T> createQueryRequest(BeanDescriptor<T> desc, SpiQuery<T> q,
Transaction t);
/**
* Compile a query.
*/
public <T> CQuery<T> compileQuery(Query<T> query, Transaction t);
<T> CQuery<T> compileQuery(Query<T> query, Transaction t);
/**
* Return the queryEngine for this server.
*/
public CQueryEngine getQueryEngine();
CQueryEngine getQueryEngine();
/**
* Execute the findId's query but without copying the query.
@@ -162,37 +162,37 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
* the query has finished (if executing in a background thread).
* </p>
*/
public <T> List<Object> findIdsWithCopy(Query<T> query, Transaction t);
<T> List<Object> findIdsWithCopy(Query<T> query, Transaction t);
/**
* Execute the findRowCount query but without copying the query.
*/
public <T> int findRowCountWithCopy(Query<T> query, Transaction t);
<T> int findRowCountWithCopy(Query<T> query, Transaction t);
/**
* Load a batch of Associated One Beans.
*/
public void loadBean(LoadBeanRequest loadRequest);
void loadBean(LoadBeanRequest loadRequest);
/**
* Lazy load a batch of Many's.
*/
public void loadMany(LoadManyRequest loadRequest);
void loadMany(LoadManyRequest loadRequest);
/**
* Return the default batch size for lazy loading.
*/
public int getLazyLoadBatchSize();
int getLazyLoadBatchSize();
/**
* Return true if the type is known as an Entity or Xml type or a List Set or
* Map of known bean types.
*/
public boolean isSupportedType(java.lang.reflect.Type genericType);
boolean isSupportedType(java.lang.reflect.Type genericType);
/**
* Collect query statistics by ObjectGraphNode. Used for Lazy loading reporting.
*/
public void collectQueryStats(ObjectGraphNode objectGraphNode, long loadedBeanCount, long timeMicros);
void collectQueryStats(ObjectGraphNode objectGraphNode, long loadedBeanCount, long timeMicros);
}
@@ -16,7 +16,7 @@ public interface SpiExpression extends Expression {
* Predicates on Many properties require an extra independent join clause.
* </p>
*/
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins);
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins);
/**
* Calculate a hash value used to identify a query for AutoFetch tuning.
@@ -25,7 +25,7 @@ public interface SpiExpression extends Expression {
* from an AutoFetch perspective and get different tuning.
* </p>
*/
public void queryAutoFetchHash(HashQueryPlanBuilder builder);
void queryAutoFetchHash(HashQueryPlanBuilder builder);
/**
* Calculate a hash value for the expression.
@@ -36,12 +36,12 @@ public interface SpiExpression extends Expression {
* case the query execution plan can be reused.
* </p>
*/
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
/**
* Return the hash value for the values that will be bound.
*/
public int queryBindHash();
int queryBindHash();
/**
* Add some sql to the query.
@@ -56,7 +56,7 @@ public interface SpiExpression extends Expression {
* @param request
* the associated request.
*/
public void addSql(SpiExpressionRequest request);
void addSql(SpiExpressionRequest request);
/**
* Add the parameter values to be set against query. For each ? place holder
@@ -65,5 +65,5 @@ public interface SpiExpression extends Expression {
* @param request
* the associated request.
*/
public void addBindValues(SpiExpressionRequest request);
void addBindValues(SpiExpressionRequest request);
}
@@ -7,6 +7,6 @@ public interface SpiExpressionFactory extends ExpressionFactory {
/**
* Create another expression factory with a given sub path.
*/
public ExpressionFactory createExpressionFactory();
ExpressionFactory createExpressionFactory();
}
@@ -16,17 +16,17 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
/**
* Return the underlying list of expressions.
*/
public List<SpiExpression> getUnderlyingList();
List<SpiExpression> getUnderlyingList();
/**
* Return a copy of the ExpressionList with the path trimmed for filterMany() expressions.
*/
public SpiExpressionList<?> trimPath(int prefixTrim);
SpiExpressionList<?> trimPath(int prefixTrim);
/**
* Restore the ExpressionFactory after deserialisation.
*/
public void setExpressionFactory(ExpressionFactory expr);
void setExpressionFactory(ExpressionFactory expr);
/**
* Process "Many" properties populating ManyWhereJoins.
@@ -34,12 +34,12 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
* Predicates on Many properties require an extra independent join clause.
* </p>
*/
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoins);
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoins);
/**
* Return true if this list is empty.
*/
public boolean isEmpty();
boolean isEmpty();
/**
* Concatenate the expression sql into a String.
@@ -48,7 +48,7 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
* with bind parameters.
* </p>
*/
public String buildSql(SpiExpressionRequest request);
String buildSql(SpiExpressionRequest request);
/**
* Combine the expression bind values into a list.
@@ -59,12 +59,12 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
*
* @return the list of all the bind values in order.
*/
public ArrayList<Object> buildBindValues(SpiExpressionRequest request);
ArrayList<Object> buildBindValues(SpiExpressionRequest request);
/**
* Calculate a hash based on the expressions but excluding the actual bind
* values.
*/
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
}
@@ -13,45 +13,45 @@ public interface SpiExpressionRequest {
/**
* Parse the logical property name to the deployment name.
*/
public String parseDeploy(String logicalProp);
String parseDeploy(String logicalProp);
/**
* Return the bean descriptor for the root type.
*/
public BeanDescriptor<?> getBeanDescriptor();
BeanDescriptor<?> getBeanDescriptor();
/**
* Return the associated QueryRequest.
*/
public SpiOrmQueryRequest<?> getQueryRequest();
SpiOrmQueryRequest<?> getQueryRequest();
/**
* Append to the expression sql.
*/
public SpiExpressionRequest append(String sql);
SpiExpressionRequest append(String sql);
/**
* Add a bind value to this request.
*/
public void addBindValue(Object bindValue);
void addBindValue(Object bindValue);
/**
* Return the accumulated expression sql for all expressions in this request.
*/
public String getSql();
String getSql();
/**
* Return the ordered list of bind values for all expressions in this request.
*/
public ArrayList<Object> getBindValues();
ArrayList<Object> getBindValues();
/**
* Increments the parameter index and returns that value.
*/
public int nextParameter();
int nextParameter();
/**
* Append a DB Like clause.
*/
public void appendLike();
void appendLike();
}
File diff suppressed because it is too large Load Diff
@@ -10,68 +10,68 @@ import com.avaje.ebean.SqlQueryListener;
*/
public interface SpiSqlQuery extends SqlQuery {
/**
* Return the named or positioned parameters.
*/
public BindParams getBindParams();
/**
* Return the named or positioned parameters.
*/
BindParams getBindParams();
/**
* return the query.
*/
public String getQuery();
/**
* return the query.
*/
String getQuery();
/**
* Return the queryListener.
*/
public SqlQueryListener getListener();
/**
* Return the first row to fetch.
*/
public int getFirstRow();
/**
* Return the maximum number of rows to fetch.
*/
public int getMaxRows();
/**
* Return the number of rows after which background fetching occurs.
*/
public int getBackgroundFetchAfter();
/**
* Return the key property for maps.
*/
public String getMapKey();
/**
* Return the query timeout.
*/
public int getTimeout();
/**
* Return the queryListener.
*/
SqlQueryListener getListener();
/**
* Return the hint for Statement.setFetchSize().
*/
public int getBufferFetchSizeHint();
/**
* Return the first row to fetch.
*/
int getFirstRow();
/**
* Return true if this is a future fetch type query.
*/
public boolean isFutureFetch();
/**
* Return the maximum number of rows to fetch.
*/
int getMaxRows();
/**
* Set to true if this is a future fetch type query.
*/
public void setFutureFetch(boolean futureFetch);
/**
* Return the number of rows after which background fetching occurs.
*/
int getBackgroundFetchAfter();
/**
* Set the PreparedStatement for the purposes of supporting cancel.
*/
public void setPreparedStatement(PreparedStatement pstmt);
/**
* Return true if the query has been cancelled.
*/
public boolean isCancelled();
/**
* Return the key property for maps.
*/
String getMapKey();
/**
* Return the query timeout.
*/
int getTimeout();
/**
* Return the hint for Statement.setFetchSize().
*/
int getBufferFetchSizeHint();
/**
* Return true if this is a future fetch type query.
*/
boolean isFutureFetch();
/**
* Set to true if this is a future fetch type query.
*/
void setFutureFetch(boolean futureFetch);
/**
* Set the PreparedStatement for the purposes of supporting cancel.
*/
void setPreparedStatement(PreparedStatement pstmt);
/**
* Return true if the query has been cancelled.
*/
boolean isCancelled();
}
@@ -4,7 +4,7 @@ import com.avaje.ebean.SqlUpdate;
public interface SpiSqlUpdate extends SqlUpdate {
public BindParams getBindParams();
BindParams getBindParams();
public void setGeneratedSql(String sql);
void setGeneratedSql(String sql);
}
@@ -20,45 +20,45 @@ public interface SpiTransaction extends Transaction {
/**
* End the transaction when had query only use.
*/
public void endQueryOnly();
void endQueryOnly();
/**
* Return the string prefix with the transactin id and label used in logging.
*/
public String getLogPrefix();
String getLogPrefix();
/**
* Return true if generated SQL and Bind values should be logged to the
* transaction log.
*/
public boolean isLogSql();
boolean isLogSql();
/**
* Return true if summary level events should be logged to the transaction
* log.
*/
public boolean isLogSummary();
boolean isLogSummary();
/**
* Log a message to the SQL logger.
*/
public void logSql(String msg);
void logSql(String msg);
/**
* Log a message to the SUMMARY logger.
*/
public void logSummary(String msg);
void logSummary(String msg);
/**
* Register a "Derived Relationship" (that requires an additional update).
*/
public void registerDerivedRelationship(DerivedRelationshipData assocBean);
void registerDerivedRelationship(DerivedRelationshipData assocBean);
/**
* Return the list of "Derived Relationships" that must be maintained after
* insert.
*/
public List<DerivedRelationshipData> getDerivedRelationship(Object bean);
List<DerivedRelationshipData> getDerivedRelationship(Object bean);
/**
* Add a deleting bean to the registered list.
@@ -66,22 +66,22 @@ public interface SpiTransaction extends Transaction {
* This is to handle bi-directional relationships where both sides Cascade.
* </p>
*/
public void registerDeleteBean(Integer hash);
void registerDeleteBean(Integer hash);
/**
* Unregister the hash of the bean.
*/
public void unregisterDeleteBean(Integer hash);
void unregisterDeleteBean(Integer hash);
/**
* Return true if this is a bean that has already been saved/deleted.
*/
public boolean isRegisteredDeleteBean(Integer hash);
boolean isRegisteredDeleteBean(Integer hash);
/**
* Unregister the persisted bean.
*/
public void unregisterBean(Object bean);
void unregisterBean(Object bean);
/**
* Return true if this is a bean that has already been persisted in the
@@ -91,13 +91,13 @@ public interface SpiTransaction extends Transaction {
* This will register the bean if it is not already.
* </p>
*/
public boolean isRegisteredBean(Object bean);
boolean isRegisteredBean(Object bean);
/**
* Returns a String used to identify the transaction. This id is used for
* Transaction logging.
*/
public String getId();
String getId();
/**
* Return the batchSize specifically set for this transaction or 0.
@@ -105,7 +105,7 @@ public interface SpiTransaction extends Transaction {
* Returning 0 implies to use the system wide default batch size.
* </p>
*/
public int getBatchSize();
int getBatchSize();
/**
* Modify and return the current 'depth' of the transaction.
@@ -119,18 +119,18 @@ public interface SpiTransaction extends Transaction {
* executed first during save.
* </p>
*/
public int depth(int diff);
int depth(int diff);
/**
* Return the current depth.
*/
public int depth();
int depth();
/**
* Return true if this transaction was created explicitly via
* <code>Ebean.beginTransaction()</code>.
*/
public boolean isExplicit();
boolean isExplicit();
/**
* Get the object that holds the event details.
@@ -140,29 +140,29 @@ public interface SpiTransaction extends Transaction {
* around the cluster (if you have a cluster).
* </p>
*/
public TransactionEvent getEvent();
TransactionEvent getEvent();
/**
* Whether persistCascade is on for save and delete.
*/
public boolean isPersistCascade();
boolean isPersistCascade();
/**
* Return true if this request should be batched. Conversely returns false
* if this request should be executed immediately.
*/
public boolean isBatchThisRequest(PersistRequest.Type type);
boolean isBatchThisRequest(PersistRequest.Type type);
/**
* Return the queue used to batch up persist requests.
*/
public BatchControl getBatchControl();
BatchControl getBatchControl();
/**
* Set the queue used to batch up persist requests. There should only be one
* PersistQueue set per transaction.
*/
public void setBatchControl(BatchControl control);
void setBatchControl(BatchControl control);
/**
* Return the persistence context associated with this transaction.
@@ -172,7 +172,7 @@ public interface SpiTransaction extends Transaction {
* behaviour.
* </p>
*/
public PersistenceContext getPersistenceContext();
PersistenceContext getPersistenceContext();
/**
* Set the persistence context to this transaction.
@@ -185,47 +185,46 @@ public interface SpiTransaction extends Transaction {
* PersistenceContext with multiple transactions.
* </p>
*/
public void setPersistenceContext(PersistenceContext context);
void setPersistenceContext(PersistenceContext context);
/**
* Return the underlying Connection for internal use.
* <p>
* If the connection is made public from Transaction and the user code calls
* If the connection is made from Transaction and the user code calls
* that method we can no longer trust the query only status of a
* Transaction.
* </p>
*/
public Connection getInternalConnection();
Connection getInternalConnection();
/**
* Return true if the manyToMany intersection should be persisted for this particular relationship direction.
*/
public boolean isSaveAssocManyIntersection(String intersectionTable, String beanName);
boolean isSaveAssocManyIntersection(String intersectionTable, String beanName);
/**
* Return true if batch mode got escalated for this request (and associated cascades).
*/
public boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request);
boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request);
/**
* If batch mode was turned on for the request then flush the batch.
*/
public void flushBatchOnCascade();
void flushBatchOnCascade();
/**
* Mark the transaction explicitly as not being query only.
*/
public void markNotQueryOnly();
void markNotQueryOnly();
/**
* Potentially escalate batch mode on saving or deleting a collection.
*/
public void checkBatchEscalationOnCollection();
void checkBatchEscalationOnCollection();
/**
* Flush batch if we escalated batch mode on saving or deleting a collection.
*/
public void flushBatchOnCollection();
void flushBatchOnCollection();
}
@@ -2,5 +2,5 @@ package com.avaje.ebeaninternal.api;
public interface SpiTransactionScopeManager {
public void replace(SpiTransaction t);
void replace(SpiTransaction t);
}
@@ -11,66 +11,66 @@ public interface SpiUpdate<T> extends Update<T> {
* The type of the update request.
*/
enum OrmUpdateType {
INSERT{
INSERT {
public String toString() {
return "Insert";
}
},
UPDATE{
UPDATE {
public String toString() {
return "Update";
}
},
DELETE{
},
DELETE {
public String toString() {
return "Delete";
}
},
UNKNOWN{
UNKNOWN {
public String toString() {
return "Unknown";
}
};
}
}
/**
* Return the type of bean being updated.
*/
public Class<?> getBeanType();
Class<?> getBeanType();
/**
* Return the type of this - insert, update or delete.
*/
public OrmUpdateType getOrmUpdateType();
OrmUpdateType getOrmUpdateType();
/**
* Return the name of the table being modified.
*/
public String getBaseTable();
String getBaseTable();
/**
* Return the update statement. This could be either sql or an orm update with bean types and property names.
*/
public String getUpdateStatement();
String getUpdateStatement();
/**
* Return the timeout in seconds.
*/
public int getTimeout();
int getTimeout();
/**
* Return true if the cache should be notified to invalidate objects.
*/
public boolean isNotifyCache();
boolean isNotifyCache();
/**
* Return the bind parameters.
*/
public BindParams getBindParams();
BindParams getBindParams();
/**
* Set the generated sql used.
*/
public void setGeneratedSql(String sql);
void setGeneratedSql(String sql);
}
@@ -16,8 +16,6 @@ import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
* <p>
* The plans are cached by the BeanDescriptors.
* </>
*
* @author rbygrave
*/
public interface SpiUpdatePlan {
@@ -28,48 +26,42 @@ public interface SpiUpdatePlan {
* deployment.
* </p>
*/
public boolean isEmptySetClause();
boolean isEmptySetClause();
/**
* Bind given the request and bean. The bean could be the oldValues bean
* when binding a update or delete where clause with ALL concurrency mode.
*/
public void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
/**
* Return the time this plan was created.
*/
public long getTimeCreated();
long getTimeCreated();
/**
* Return the time this plan was last used.
*/
public Long getTimeLastUsed();
Long getTimeLastUsed();
/**
* Return the hash key for this plan.
*/
public Integer getKey();
Integer getKey();
/**
* Return the concurrency mode for this plan.
*/
public ConcurrencyMode getMode();
ConcurrencyMode getMode();
/**
* Return the update SQL statement.
*/
public String getSql();
String getSql();
/**
* Return the set of bindable update properties.
*/
public Bindable getSet();
// /**
// * Return the properties that where changed and should be included in the
// * update statement.
// */
// public Set<String> getProperties();
Bindable getSet();
}
@@ -65,10 +65,10 @@ public class TransactionEvent implements Serializable {
}
/**
* For BeanListeners the requests they are interested in.
* Return the list of PersistRequestBean's for this transaction.
*/
public TransactionEventBeans getEventBeans() {
return eventBeans;
public List<PersistRequestBean<?>> getPersistRequestBeans() {
return (eventBeans == null) ? null : eventBeans.getRequests();
}
public TransactionEventTable getEventTables() {
@@ -1,6 +1,7 @@
package com.avaje.ebeaninternal.server.core;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
@@ -8,18 +9,13 @@ import javax.persistence.Embeddable;
import javax.persistence.Entity;
import javax.persistence.Table;
import com.avaje.ebean.event.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.ScalarTypeConverter;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebean.event.ServerConfigStartup;
import com.avaje.ebean.event.TransactionEventListener;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.util.ClassPathSearchMatcher;
@@ -29,364 +25,373 @@ import com.avaje.ebeaninternal.server.util.ClassPathSearchMatcher;
*/
public class BootupClasses implements ClassPathSearchMatcher {
private static final Logger logger = LoggerFactory.getLogger(BootupClasses.class);
private static final Logger logger = LoggerFactory.getLogger(BootupClasses.class);
private ArrayList<Class<?>> embeddableList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> embeddableList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> entityList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> entityList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> scalarTypeList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> scalarTypeList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> scalarConverterList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> scalarConverterList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> compoundTypeList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanControllerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> compoundTypeList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> transactionEventListenerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanControllerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanFinderList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> transactionEventListenerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanListenerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanFinderList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanFindControllerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> beanListenerList = new ArrayList<Class<?>>();
private ArrayList<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
private ArrayList<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
private ArrayList<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
private ArrayList<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
private List<BeanFindController> findControllerInstances = new ArrayList<BeanFindController>();
private List<BeanPersistController> persistControllerInstances = new ArrayList<BeanPersistController>();
private List<BeanPersistListener> persistListenerInstances = new ArrayList<BeanPersistListener>();
private List<BeanQueryAdapter> queryAdapterInstances = new ArrayList<BeanQueryAdapter>();
private List<TransactionEventListener> transactionEventListenerInstances = new ArrayList<TransactionEventListener>();
private List<BeanPersistController> persistControllerInstances = new ArrayList<BeanPersistController>();
private List<BeanPersistListener> persistListenerInstances = new ArrayList<BeanPersistListener>();
private List<BeanQueryAdapter> queryAdapterInstances = new ArrayList<BeanQueryAdapter>();
private List<TransactionEventListener> transactionEventListenerInstances = new ArrayList<TransactionEventListener>();
public BootupClasses() {
}
public BootupClasses() {
public BootupClasses(List<Class<?>> list) {
if (list != null) {
for (Class<?> cls : list) {
isMatch(cls);
}
}
}
/**
* Run any ServerConfigStartup listeners.
*/
public void runServerConfigStartup(ServerConfig serverConfig) {
for (Class<?> cls : serverConfigStartupList) {
try {
ServerConfigStartup newInstance = (ServerConfigStartup) cls.newInstance();
newInstance.onStart(serverConfig);
} catch (Exception e) {
String msg = "Error creating BeanQueryAdapter " + cls;
logger.error(msg, e);
}
}
}
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 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());
}
}
}
/**
* 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 TransactionEventListeners instances.
*/
public void addTransactionEventListeners(List<TransactionEventListener> transactionEventListeners) {
if (transactionEventListeners != null) {
for (TransactionEventListener c : transactionEventListeners) {
this.transactionEventListenerInstances.add(c);
// don't automatically instantiate
this.transactionEventListenerList.remove(c.getClass());
}
}
}
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());
}
}
}
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());
}
}
}
public List<BeanQueryAdapter> getBeanQueryAdapters() {
// add class registered BeanQueryAdapter to the
// already created instances
for (Class<?> cls : beanQueryAdapterList) {
try {
BeanQueryAdapter newInstance = (BeanQueryAdapter) cls.newInstance();
queryAdapterInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanQueryAdapter " + cls;
logger.error(msg, e);
}
}
public BootupClasses(List<Class<?>> list) {
if (list != null) {
for (Class<?> cls : list) {
isMatch(cls);
}
}
return queryAdapterInstances;
}
public List<BeanFindController> getBeanFindControllers() {
// add class registered BeanFindController to the
// list of created instances
for (Class<?> cls : beanFindControllerList) {
try {
BeanFindController newInstance = (BeanFindController) cls.newInstance();
findControllerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanPersistController " + cls;
logger.error(msg, e);
}
}
private BootupClasses(BootupClasses parent) {
this.embeddableList.addAll(parent.embeddableList);
this.entityList.addAll(parent.entityList);
this.scalarTypeList.addAll(parent.scalarTypeList);
this.scalarConverterList.addAll(parent.scalarConverterList);
this.compoundTypeList.addAll(parent.compoundTypeList);
this.beanControllerList.addAll(parent.beanControllerList);
this.transactionEventListenerList.addAll(parent.transactionEventListenerList);
this.beanFinderList.addAll(parent.beanFinderList);
this.beanListenerList.addAll(parent.beanListenerList);
this.beanQueryAdapterList.addAll(parent.beanQueryAdapterList);
this.serverConfigStartupList.addAll(parent.serverConfigStartupList);
return findControllerInstances;
}
public List<BeanPersistListener> getBeanPersistListeners() {
// add class registered BeanPersistController to the
// already created instances
for (Class<?> cls : beanListenerList) {
try {
BeanPersistListener newInstance = (BeanPersistListener) cls.newInstance();
persistListenerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanPersistController " + cls;
logger.error(msg, e);
}
}
/**
* Create a copy of this object so that classes can be added to it.
*/
public BootupClasses createCopy() {
return new BootupClasses(this);
return persistListenerInstances;
}
public List<BeanPersistController> getBeanPersistControllers() {
// add class registered BeanPersistController to the
// already created instances
for (Class<?> cls : beanControllerList) {
try {
BeanPersistController newInstance = (BeanPersistController) cls.newInstance();
persistControllerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanPersistController " + cls;
logger.error(msg, e);
}
}
/**
* Run any ServerConfigStartup listeners.
*/
public void runServerConfigStartup(ServerConfig serverConfig) {
for (Class<?> cls : serverConfigStartupList) {
try {
ServerConfigStartup newInstance = (ServerConfigStartup) cls.newInstance();
newInstance.onStart(serverConfig);
} catch (Exception e) {
String msg = "Error creating BeanQueryAdapter " + cls;
logger.error(msg, e);
}
}
}
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());
}
}
return persistControllerInstances;
}
public List<TransactionEventListener> getTransactionEventListeners() {
// add class registered TransactionEventListener to the
// already created instances
for (Class<?> cls : transactionEventListenerList) {
try {
TransactionEventListener newInstance = (TransactionEventListener) cls.newInstance();
transactionEventListenerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating TransactionEventListener " + cls;
logger.error(msg, e);
}
}
/**
* 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());
}
}
return transactionEventListenerInstances;
}
/**
* Return the list of Embeddable classes.
*/
public List<Class<?>> getEmbeddables() {
return embeddableList;
}
/**
* Return the list of entity classes.
*/
public List<Class<?>> getEntities() {
return entityList;
}
/**
* Return the list of ScalarTypes found.
*/
public List<Class<?>> getScalarTypes() {
return scalarTypeList;
}
/**
* Return the list of ScalarConverters found.
*/
public List<Class<?>> getScalarConverters() {
return scalarConverterList;
}
/**
* Return the list of ScalarConverters found.
*/
public List<Class<?>> getCompoundTypes() {
return compoundTypeList;
}
/**
* Return the list of BeanControllers found.
*/
public List<Class<?>> getBeanControllers() {
return beanControllerList;
}
/**
* Return the list of TransactionEventListeners found
*/
public List<Class<?>> getTransactionEventListenerList() {
return transactionEventListenerList;
}
/**
* Return the list of BeanFinders found.
*/
public List<Class<?>> getBeanFinders() {
return beanFinderList;
}
/**
* Return the list of BeanListeners found.
*/
public List<Class<?>> getBeanListeners() {
return beanListenerList;
}
public boolean isMatch(Class<?> cls) {
if (isEmbeddable(cls)) {
embeddableList.add(cls);
} else if (isEntity(cls)) {
entityList.add(cls);
} else {
return isInterestingInterface(cls);
}
/**
* Add TransactionEventListeners instances.
*/
public void addTransactionEventListeners(List<TransactionEventListener> transactionEventListeners) {
if (transactionEventListeners != null) {
for (TransactionEventListener c : transactionEventListeners) {
this.transactionEventListenerInstances.add(c);
// don't automatically instantiate
this.transactionEventListenerList.remove(c.getClass());
}
}
return true;
}
/**
* Look for interesting interfaces.
* <p>
* This includes ScalarType, BeanController, BeanFinder and BeanListener.
* </p>
*/
private boolean isInterestingInterface(Class<?> cls) {
if (Modifier.isAbstract(cls.getModifiers())) {
// do not include abstract classes as we can
// not instantiate them
return false;
}
boolean interesting = false;
if (BeanPersistController.class.isAssignableFrom(cls)) {
beanControllerList.add(cls);
interesting = true;
}
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());
}
}
}
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());
}
}
}
public List<BeanQueryAdapter> getBeanQueryAdapters() {
// add class registered BeanQueryAdapter to the
// already created instances
for (Class<?> cls : beanQueryAdapterList) {
try {
BeanQueryAdapter newInstance = (BeanQueryAdapter) cls.newInstance();
queryAdapterInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanQueryAdapter " + cls;
logger.error(msg, e);
}
}
return queryAdapterInstances;
if (TransactionEventListener.class.isAssignableFrom(cls)) {
transactionEventListenerList.add(cls);
interesting = true;
}
public List<BeanPersistListener> getBeanPersistListeners() {
// add class registered BeanPersistController to the
// already created instances
for (Class<?> cls : beanListenerList) {
try {
BeanPersistListener newInstance = (BeanPersistListener) cls.newInstance();
persistListenerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanPersistController " + cls;
logger.error(msg, e);
}
}
return persistListenerInstances;
if (ScalarType.class.isAssignableFrom(cls)) {
scalarTypeList.add(cls);
interesting = true;
}
public List<BeanPersistController> getBeanPersistControllers() {
// add class registered BeanPersistController to the
// already created instances
for (Class<?> cls : beanControllerList) {
try {
BeanPersistController newInstance = (BeanPersistController) cls.newInstance();
persistControllerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating BeanPersistController " + cls;
logger.error(msg, e);
}
}
return persistControllerInstances;
if (ScalarTypeConverter.class.isAssignableFrom(cls)) {
scalarConverterList.add(cls);
interesting = true;
}
public List<TransactionEventListener> getTransactionEventListeners() {
// add class registered TransactionEventListener to the
// already created instances
for (Class<?> cls : transactionEventListenerList) {
try {
TransactionEventListener newInstance = (TransactionEventListener) cls.newInstance();
transactionEventListenerInstances.add(newInstance);
} catch (Exception e) {
String msg = "Error creating TransactionEventListener " + cls;
logger.error(msg, e);
}
}
return transactionEventListenerInstances;
}
/**
* Return the list of Embeddable classes.
*/
public ArrayList<Class<?>> getEmbeddables() {
return embeddableList;
if (CompoundType.class.isAssignableFrom(cls)) {
compoundTypeList.add(cls);
interesting = true;
}
/**
* Return the list of entity classes.
*/
public ArrayList<Class<?>> getEntities() {
return entityList;
if (BeanFinder.class.isAssignableFrom(cls)) {
beanFinderList.add(cls);
interesting = true;
}
/**
* Return the list of ScalarTypes found.
*/
public ArrayList<Class<?>> getScalarTypes() {
return scalarTypeList;
if (BeanFindController.class.isAssignableFrom(cls)) {
beanFindControllerList.add(cls);
interesting = true;
}
/**
* Return the list of ScalarConverters found.
*/
public ArrayList<Class<?>> getScalarConverters() {
return scalarConverterList;
if (BeanPersistListener.class.isAssignableFrom(cls)) {
beanListenerList.add(cls);
interesting = true;
}
/**
* Return the list of ScalarConverters found.
*/
public ArrayList<Class<?>> getCompoundTypes() {
return compoundTypeList;
}
/**
* Return the list of BeanControllers found.
*/
public ArrayList<Class<?>> getBeanControllers() {
return beanControllerList;
if (BeanQueryAdapter.class.isAssignableFrom(cls)) {
beanQueryAdapterList.add(cls);
interesting = true;
}
/**
* Return the list of TransactionEventListeners found
*/
public ArrayList<Class<?>> getTransactionEventListenerList() {
return transactionEventListenerList;
if (ServerConfigStartup.class.isAssignableFrom(cls)) {
serverConfigStartupList.add(cls);
interesting = true;
}
/**
* Return the list of BeanFinders found.
*/
public ArrayList<Class<?>> getBeanFinders() {
return beanFinderList;
return interesting;
}
private boolean isEntity(Class<?> cls) {
Annotation ann = cls.getAnnotation(Entity.class);
if (ann != null) {
return true;
}
ann = cls.getAnnotation(Table.class);
return ann != null;
}
/**
* Return the list of BeanListeners found.
*/
public ArrayList<Class<?>> getBeanListeners() {
return beanListenerList;
}
private boolean isEmbeddable(Class<?> cls) {
public boolean isMatch(Class<?> cls) {
if (isEmbeddable(cls)) {
embeddableList.add(cls);
} else if (isEntity(cls)) {
entityList.add(cls);
} else if (isInterestingInterface(cls)) {
return true;
} else {
return false;
}
return true;
}
/**
* Look for interesting interfaces.
* <p>
* This includes ScalarType, BeanController, BeanFinder and BeanListener.
* </p>
*/
private boolean isInterestingInterface(Class<?> cls) {
boolean interesting = false;
if (BeanPersistController.class.isAssignableFrom(cls)) {
beanControllerList.add(cls);
interesting = true;
}
if (TransactionEventListener.class.isAssignableFrom(cls)) {
transactionEventListenerList.add(cls);
interesting = true;
}
if (ScalarType.class.isAssignableFrom(cls)) {
scalarTypeList.add(cls);
interesting = true;
}
if (ScalarTypeConverter.class.isAssignableFrom(cls)) {
scalarConverterList.add(cls);
interesting = true;
}
if (CompoundType.class.isAssignableFrom(cls)) {
compoundTypeList.add(cls);
interesting = true;
}
if (BeanFinder.class.isAssignableFrom(cls)) {
beanFinderList.add(cls);
interesting = true;
}
if (BeanPersistListener.class.isAssignableFrom(cls)) {
beanListenerList.add(cls);
interesting = true;
}
if (BeanQueryAdapter.class.isAssignableFrom(cls)) {
beanQueryAdapterList.add(cls);
interesting = true;
}
if (ServerConfigStartup.class.isAssignableFrom(cls)){
serverConfigStartupList.add(cls);
interesting = true;
}
return interesting;
}
private boolean isEntity(Class<?> cls) {
Annotation ann = cls.getAnnotation(Entity.class);
if (ann != null) {
return true;
}
ann = cls.getAnnotation(Table.class);
if (ann != null) {
return true;
}
return false;
}
private boolean isEmbeddable(Class<?> cls) {
Annotation ann = cls.getAnnotation(Embeddable.class);
if (ann != null) {
return true;
}
return false;
}
Annotation ann = cls.getAnnotation(Embeddable.class);
return ann != null;
}
}
@@ -80,7 +80,9 @@ public class DatabasePlatformFactory {
if (dbName.equals("mysql")) {
return new MySqlPlatform();
}
if (dbName.equals("h2")) {
return new H2Platform();
}
if (dbName.equals("sqlite")) {
return new SQLitePlatform();
}
@@ -5,6 +5,7 @@ import java.util.List;
import javax.persistence.EntityNotFoundException;
import com.avaje.ebeaninternal.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -15,11 +16,6 @@ import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebean.bean.ObjectGraphNode;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebeaninternal.api.LoadBeanBuffer;
import com.avaje.ebeaninternal.api.LoadBeanRequest;
import com.avaje.ebeaninternal.api.LoadManyRequest;
import com.avaje.ebeaninternal.api.LoadManyBuffer;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.api.SpiQuery.Mode;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
@@ -36,8 +32,11 @@ public class DefaultBeanLoader {
private final DefaultServer server;
private final boolean onIterateUseExtraTxn;
protected DefaultBeanLoader(DefaultServer server) {
this.server = server;
this.onIterateUseExtraTxn = server.getDatabasePlatform().useExtraTransactionOnIterateSecondaryQueries();
}
/**
@@ -143,7 +142,17 @@ public class DefaultBeanLoader {
query.select(many.getTargetIdProperty());
}
server.findList(query, loadRequest.getTransaction());
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createQueryTransaction();
try {
server.findList(query, extraTxn);
} finally {
extraTxn.end();
}
} else {
server.findList(query, loadRequest.getTransaction());
}
// check for BeanCollection's that where never processed
// in the +query or +lazy load due to no rows (predicates)
@@ -332,7 +341,18 @@ public class DefaultBeanLoader {
query.where().idIn(idList);
}
List<?> list = server.findList(query, loadRequest.getTransaction());
List<?> list;
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createQueryTransaction();
try {
list = server.findList(query, extraTxn);
} finally {
extraTxn.end();
}
} else {
list = server.findList(query, loadRequest.getTransaction());
}
if (loadRequest.isLoadCache()) {
for (int i = 0; i < list.size(); i++) {
@@ -233,6 +233,7 @@ public class DefaultContainer implements SpiContainer {
BootupClasses bootupClasses = getBootupClasses1(serverConfig);
bootupClasses.addPersistControllers(serverConfig.getPersistControllers());
bootupClasses.addFindControllers(serverConfig.getFindControllers());
bootupClasses.addTransactionEventListeners(serverConfig.getTransactionEventListeners());
bootupClasses.addPersistListeners(serverConfig.getPersistListeners());
bootupClasses.addQueryAdapters(serverConfig.getQueryAdapters());
@@ -300,8 +301,7 @@ public class DefaultContainer implements SpiContainer {
if (config.getDataSourceJndiName() != null) {
ds = jndiDataSourceFactory.lookup(config.getDataSourceJndiName());
if (ds == null) {
String m = "JNDI lookup for DataSource " + config.getDataSourceJndiName() + " returned null.";
throw new PersistenceException(m);
throw new PersistenceException("JNDI lookup for DataSource " + config.getDataSourceJndiName() + " returned null.");
} else {
return ds;
}
@@ -309,14 +309,13 @@ public class DefaultContainer implements SpiContainer {
DataSourceConfig dsConfig = config.getDataSourceConfig();
if (dsConfig == null) {
String m = "No DataSourceConfig definded for " + config.getName();
String m = "No DataSourceConfig defined for " + config.getName();
throw new PersistenceException(m);
}
if (dsConfig.isOffline()) {
if (config.getDatabasePlatformName() == null) {
String m = "You MUST specify a DatabasePlatformName on ServerConfig when offline";
throw new PersistenceException(m);
throw new PersistenceException("You MUST specify a DatabasePlatformName on ServerConfig when offline");
}
return null;
}
@@ -198,19 +198,20 @@ public final class DefaultServer implements SpiEbeanServer {
this.beanLoader = new DefaultBeanLoader(this);
this.jsonContext = config.createJsonContext(this);
loadAndInitializePlugins(config);
// load normal plugins late and call setup on all
loadAndInitializePlugins(config.getServerConfig());
// Register with the JVM Shutdown hook
ShutdownManager.registerEbeanServer(this);
}
protected void loadAndInitializePlugins(InternalConfiguration config) {
protected void loadAndInitializePlugins(ServerConfig config) {
List<SpiEbeanPlugin> spiPlugins = new ArrayList<SpiEbeanPlugin>();
for (SpiEbeanPlugin plugin : ServiceLoader.load(SpiEbeanPlugin.class)) {
spiPlugins.add(plugin);
plugin.setup(this, this.getDatabasePlatform(), config.getServerConfig());
plugin.setup(this, this.getDatabasePlatform(), config);
if (plugin instanceof DdlGenerator) {
// backwards compatible
@@ -222,18 +223,24 @@ public final class DefaultServer implements SpiEbeanServer {
// ServiceLoader not finding ddlGenerator (typically OSGi)
ddlGenerator = new DdlGenerator();
spiPlugins.add(ddlGenerator);
ddlGenerator.setup(this, this.getDatabasePlatform(), config.getServerConfig());
ddlGenerator.setup(this, this.getDatabasePlatform(), config);
}
ebeanPlugins = Collections.unmodifiableList(spiPlugins);
}
/**
* Return the list of registered plugins.
*/
public List<SpiEbeanPlugin> getSpiEbeanPlugins() {
return ebeanPlugins;
}
/**
* Execute all the plugins with an online flag indicating the DB is up or not.
*/
public void executePlugins(boolean online) {
for(SpiEbeanPlugin plugin : ebeanPlugins) {
for (SpiEbeanPlugin plugin : ebeanPlugins) {
plugin.execute(online);
}
}
@@ -756,16 +763,16 @@ public final class DefaultServer implements SpiEbeanServer {
}
/**
* Start a transaction.
* Start a transaction with 'REQUIRED' semantics.
* <p>
* If a transaction already exists that transaction will be used.
* </p>
* <p>
* Note that the transaction is stored in a ThreadLocal variable.
* </p>
*/
public Transaction beginTransaction() {
// start an explicit transaction
SpiTransaction t = transactionManager.createTransaction(true, -1);
transactionScopeManager.set(t);
return t;
return beginTransaction(TxScope.required());
}
public Transaction beginTransaction(TxScope scope) {
@@ -1318,7 +1325,7 @@ public final class DefaultServer implements SpiEbeanServer {
public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
request.initTransIfRequired();
request.findVisit(visitor);
@@ -1327,7 +1334,7 @@ public final class DefaultServer implements SpiEbeanServer {
public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
request.initTransIfRequired();
request.findEach(consumer);
@@ -1336,7 +1343,7 @@ public final class DefaultServer implements SpiEbeanServer {
public <T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
request.initTransIfRequired();
request.findEachWhile(consumer);
@@ -1345,7 +1352,7 @@ public final class DefaultServer implements SpiEbeanServer {
public <T> QueryIterator<T> findIterate(Query<T> query, Transaction t) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
try {
request.initTransIfRequired();
@@ -182,7 +182,7 @@ public class InternalConfiguration {
}
public OrmQueryEngine createOrmQueryEngine() {
return new DefaultOrmQueryEngine(beanDescriptorManager, cQueryEngine);
return new DefaultOrmQueryEngine(cQueryEngine);
}
public Persister createPersister(SpiEbeanServer server) {
@@ -11,34 +11,27 @@ import javax.sql.DataSource;
*/
public class JndiDataSourceLookup {
private static final String DEFAULT_PREFIX = "java:comp/env/jdbc/";
public JndiDataSourceLookup() {
}
public JndiDataSourceLookup() {
}
/**
* Return the DataSource by JNDI lookup.
* <p>
* If name is null the 'default' dataSource is returned.
* </p>
*/
public DataSource lookup(String jndiName) {
/**
* Return the DataSource by JNDI lookup.
* <p>
* If name is null the 'default' dataSource is returned.
* </p>
*/
public DataSource lookup(String jndiName) {
try {
if (!jndiName.startsWith("java:")){
jndiName = DEFAULT_PREFIX + jndiName;
}
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(jndiName);
if (ds == null) {
throw new PersistenceException("JNDI DataSource [" + jndiName + "] not found?");
}
return ds;
try {
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(jndiName);
if (ds == null) {
throw new PersistenceException("JNDI DataSource [" + jndiName + "] not found?");
}
return ds;
} catch (NamingException ex) {
throw new PersistenceException(ex);
}
}
} catch (NamingException ex) {
throw new PersistenceException(ex);
}
}
}
@@ -9,7 +9,7 @@ import javax.persistence.PersistenceException;
import com.avaje.ebean.*;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebean.event.BeanFindController;
import com.avaje.ebean.event.BeanQueryRequest;
import com.avaje.ebeaninternal.api.BeanIdList;
import com.avaje.ebeaninternal.api.HashQuery;
@@ -40,7 +40,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
private final SpiQuery<T> query;
private final BeanFinder<T> finder;
private final BeanFindController finder;
private final Boolean readOnly;
@@ -315,7 +315,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
/**
* Return a bean specific finder if one has been set.
*/
public BeanFinder<T> getBeanFinder() {
public BeanFindController getBeanFinder() {
return finder;
}
@@ -10,16 +10,12 @@ import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebean.config.EncryptKey;
import com.avaje.ebean.config.dbplatform.IdGenerator;
import com.avaje.ebean.config.dbplatform.IdType;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebean.event.*;
import com.avaje.ebean.meta.MetaBeanInfo;
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
import com.avaje.ebeaninternal.api.*;
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
import com.avaje.ebeaninternal.server.cache.CachedBeanData;
import com.avaje.ebeaninternal.server.cache.CachedManyIds;
import com.avaje.ebeaninternal.server.core.CacheOptions;
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
import com.avaje.ebeaninternal.server.core.InternString;
@@ -28,17 +24,18 @@ import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyLists;
import com.avaje.ebeaninternal.server.el.*;
import com.avaje.ebeaninternal.server.persist.DmlUtil;
import com.avaje.ebeaninternal.server.query.CQueryPlan;
import com.avaje.ebeaninternal.server.query.CQueryPlanStats.Snapshot;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.util.SortByClause;
import com.avaje.ebeaninternal.util.SortByClause.Property;
import com.avaje.ebeaninternal.util.SortByClauseParser;
import com.fasterxml.jackson.core.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -104,18 +101,11 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
private final boolean autoFetchTunable;
private final String lazyFetchIncludes;
/**
* The concurrency mode for beans of this type.
*/
private final ConcurrencyMode concurrencyMode;
/**
* The tables this bean is dependent on.
*/
private final String[] dependantTables;
private final CompoundUniqueContraint[] compoundUniqueConstraints;
/**
@@ -127,7 +117,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
* Map of BeanProperty Linked so as to preserve order.
*/
private final LinkedHashMap<String, BeanProperty> propMap;
private final LinkedHashMap<String, BeanProperty> propMapByDbColumn;
/**
* The type of bean this describes.
@@ -161,7 +150,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
/**
* If set overrides the find implementation. Server side only.
*/
private final BeanFinder<T> beanFinder;
private final BeanFindController beanFinder;
/**
* The table joins for this bean.
@@ -222,7 +211,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
private final BeanPropertyAssocOne<?>[] propertiesOneImportedSave;
private final BeanPropertyAssocOne<?>[] propertiesOneImportedDelete;
private final BeanPropertyAssocOne<?>[] propertiesOneExported;
//private final BeanPropertyAssocOne<?>[] propertiesOneExported;
private final BeanPropertyAssocOne<?>[] propertiesOneExportedSave;
private final BeanPropertyAssocOne<?>[] propertiesOneExportedDelete;
@@ -339,11 +328,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
this.sequenceInitialValue = deploy.getSequenceInitialValue();
this.sequenceAllocationSize = deploy.getSequenceAllocationSize();
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
this.lazyFetchIncludes = InternString.intern(deploy.getLazyFetchIncludes());
this.concurrencyMode = deploy.getConcurrencyMode();
this.updateChangesOnly = deploy.isUpdateChangesOnly();
this.dependantTables = deploy.getDependantTables();
this.compoundUniqueConstraints = deploy.getCompoundUniqueConstraints();
this.baseTable = InternString.intern(deploy.getBaseTable());
@@ -356,7 +342,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
this.idProperty = listHelper.getId();
this.versionProperty = listHelper.getVersionProperty();
this.propMap = listHelper.getPropertyMap();
this.propMapByDbColumn = getReverseMap(propMap);
this.propertiesTransient = listHelper.getTransients();
this.propertiesNonTransient = listHelper.getNonTransients();
this.propertiesBaseScalar = listHelper.getBaseScalar();
@@ -366,7 +351,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
this.propertiesMutable = listHelper.getMutable();
this.unidirectional = listHelper.getUnidirectional();
this.propertiesOne = listHelper.getOnes();
this.propertiesOneExported = listHelper.getOneExported();
//this.propertiesOneExported = listHelper.getOneExported();
this.propertiesOneExportedSave = listHelper.getOneExportedSave();
this.propertiesOneExportedDelete = listHelper.getOneExportedDelete();
this.propertiesOneImported = listHelper.getOneImported();
@@ -649,10 +634,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
return (queryUseCache != null) ? queryUseCache.booleanValue() : isBeanCaching();
}
public T cacheNaturalKey(SpiQuery<T> query, SpiTransaction t) {
return cacheHelp.naturalKeyLookup(query, t);
}
/**
* Return the cache options.
*/
@@ -718,13 +699,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
cacheHelp.setUseCache(useCache);
}
/**
* Return true if there is currently query caching for this type of bean.
*/
public boolean isQueryCaching() {
return cacheHelp.isQueryCaching();
}
/**
* Return true if there is currently bean caching for this type of bean.
*/
@@ -786,20 +760,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
cacheHelp.manyPropClear(propertyName);
}
/**
* Return the CachedManyIds for a given bean and property. Returns null if not in the cache.
*/
public CachedManyIds cacheManyPropGet(Object parentId, String propertyName) {
return cacheHelp.manyPropGet(parentId, propertyName);
}
/**
* Clear the bean cache.
*/
public void cacheBeanClear() {
cacheHelp.beanCacheClear();
}
public void cacheBeanPut(T bean) {
cacheBeanPutData((EntityBean)bean);
}
@@ -1534,14 +1494,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
return EntityType.EMBEDDED.equals(entityType);
}
/**
* Return the tables this bean is dependent on. This implies that if any of
* these tables are modified then cached beans may be invalidated.
*/
public String[] getDependantTables() {
return dependantTables;
}
/**
* Return the compound unique constraints.
*/
@@ -1559,7 +1511,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
/**
* Return the beanFinder. Usually null unless overriding the finder.
*/
public BeanFinder<T> getBeanFinder() {
public BeanFindController getBeanFinder() {
return beanFinder;
}
@@ -1573,18 +1525,15 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
/**
* De-register the BeanPersistListener.
*/
@SuppressWarnings("unchecked")
public void deregister(BeanPersistListener listener) {
// volatile read...
BeanPersistListener currListener = persistListener;
if (currListener == null) {
// nothing to deregister
} else {
BeanPersistListener deregListener = listener;
if (currListener instanceof ChainedBeanPersistListener) {
BeanPersistListener currentListener = persistListener;
if (currentListener != null) {
if (currentListener instanceof ChainedBeanPersistListener) {
// remove it from the existing chain
persistListener = ((ChainedBeanPersistListener) currListener).deregister(deregListener);
} else if (currListener.equals(deregListener)) {
persistListener = ((ChainedBeanPersistListener) currentListener).deregister(listener);
} else if (currentListener.equals(listener)) {
persistListener = null;
}
}
@@ -1594,13 +1543,14 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
* De-register the BeanPersistController.
*/
public void deregister(BeanPersistController controller) {
// volatile read...
BeanPersistController c = persistController;
if (c != null) {
if (c instanceof ChainedBeanPersistController) {
BeanPersistController currentController = persistController;
if (currentController != null) {
if (currentController instanceof ChainedBeanPersistController) {
// remove it from the existing chain
persistController = ((ChainedBeanPersistController) c).deregister(controller);
} else if (c.equals(controller)) {
persistController = ((ChainedBeanPersistController) currentController).deregister(controller);
} else if (currentController.equals(controller)) {
persistController = null;
}
}
@@ -1614,16 +1564,16 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
if (newPersistListener.isRegisterFor(beanType)) {
// volatile read...
BeanPersistListener currListener = persistListener;
if (currListener == null) {
BeanPersistListener currentListener = persistListener;
if (currentListener == null) {
persistListener = newPersistListener;
} else {
if (currListener instanceof ChainedBeanPersistListener) {
if (currentListener instanceof ChainedBeanPersistListener) {
// add it to the existing chain
persistListener = ((ChainedBeanPersistListener) currListener).register(newPersistListener);
persistListener = ((ChainedBeanPersistListener) currentListener).register(newPersistListener);
} else {
// build new chain of the 2
persistListener = new ChainedBeanPersistListener(currListener, newPersistListener);
persistListener = new ChainedBeanPersistListener(currentListener, newPersistListener);
}
}
}
@@ -1636,16 +1586,16 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
if (newController.isRegisterFor(beanType)) {
// volatile read...
BeanPersistController c = persistController;
if (c == null) {
BeanPersistController currentController = persistController;
if (currentController == null) {
persistController = newController;
} else {
if (c instanceof ChainedBeanPersistController) {
if (currentController instanceof ChainedBeanPersistController) {
// add it to the existing chain
persistController = ((ChainedBeanPersistController) c).register(newController);
persistController = ((ChainedBeanPersistController) currentController).register(newController);
} else {
// build new chain of the 2
persistController = new ChainedBeanPersistController(c, newController);
persistController = new ChainedBeanPersistController(currentController, newController);
}
}
}
@@ -1717,20 +1667,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
return selectLastInsertedId;
}
/**
* Return the IdGenerator.
*/
public IdGenerator getIdGenerator() {
return idGenerator;
}
/**
* Return the includes for getReference().
*/
public String getLazyFetchIncludes() {
return lazyFetchIncludes;
}
/**
* Return the TableJoins.
* <p>
@@ -1793,7 +1729,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
// not using Id generator so just base on isLoaded()
return !ebi.isLoaded();
}
if (!hasIdProperty(ebi)) {
if (!hasIdValue(ebi.getOwner())) {
// No Id property means it must be an insert
return true;
}
@@ -1808,9 +1744,9 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
public boolean hasIdPropertyOnly(EntityBeanIntercept ebi) {
return ebi.hasIdOnly(idPropertyIndex);
}
public boolean hasIdProperty(EntityBeanIntercept ebi) {
return idPropertyIndex > -1 && ebi.isLoadedProperty(idPropertyIndex);
public boolean hasIdValue(EntityBean bean) {
return (idProperty != null && !DmlUtil.isNullOrZero(idProperty.getValue(bean)));
}
public boolean hasVersionProperty(EntityBeanIntercept ebi) {
@@ -1823,14 +1759,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
public void checkMutableProperties(EntityBeanIntercept ebi) {
for (int i = 0; i < propertiesMutable.length; i++) {
BeanProperty beanProperty = propertiesMutable[i];
if (ebi.isDirtyProperty(beanProperty.getPropertyIndex())) {
// already marked as dirty
} else if (ebi.isLoadedProperty(beanProperty.getPropertyIndex())) {
int propertyIndex = beanProperty.getPropertyIndex();
if (!ebi.isDirtyProperty(propertyIndex) && ebi.isLoadedProperty(propertyIndex)) {
Object value = beanProperty.getValue(ebi.getOwner());
if (value == null || beanProperty.isDirtyValue(value)) {
// mutable scalar value which is considered dirty so mark
// it as such so that it is included in an update
ebi.markPropertyAsChanged(beanProperty.getPropertyIndex());
ebi.markPropertyAsChanged(propertyIndex);
}
}
}
@@ -1973,11 +1908,11 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
jsonHelp.jsonWriteProperties(writeJson, bean);
}
public T jsonRead(JsonParser parser, String path) throws IOException {
return jsonHelp.jsonRead(parser, path);
public T jsonRead(ReadJson jsonRead, String path) throws IOException {
return jsonHelp.jsonRead(jsonRead, path);
}
protected T jsonReadObject(JsonParser parser, String path) throws IOException {
return jsonHelp.jsonReadObject(parser, path);
protected T jsonReadObject(ReadJson jsonRead, String path) throws IOException {
return jsonHelp.jsonReadObject(jsonRead, path);
}
}
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.json.EJson;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson.WriteBean;
import com.fasterxml.jackson.core.JsonParseException;
@@ -9,6 +10,8 @@ import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
public class BeanDescriptorJsonHelp<T> {
@@ -50,8 +53,9 @@ public class BeanDescriptorJsonHelp<T> {
@SuppressWarnings("unchecked")
public T jsonRead(JsonParser parser, String path) throws IOException {
public T jsonRead(ReadJson jsonRead, String path) throws IOException {
JsonParser parser = jsonRead.getParser();
if (parser.getCurrentToken() == JsonToken.START_OBJECT) {
// start object token read by Jackson already
} else {
@@ -66,7 +70,7 @@ public class BeanDescriptorJsonHelp<T> {
}
if (desc.inheritInfo == null) {
return jsonReadObject(parser, path);
return jsonReadObject(jsonRead, path);
}
// check for the discriminator value to determine the correct sub type
@@ -83,8 +87,8 @@ public class BeanDescriptorJsonHelp<T> {
BeanProperty property = desc.getBeanProperty(propName);
if (property != null) {
EntityBean bean = desc.createEntityBean();
property.jsonRead(parser, bean);
return jsonReadProperties(parser, bean);
property.jsonRead(jsonRead, bean);
return jsonReadProperties(jsonRead, bean, path);
}
String msg = "Error reading inheritance discriminator, expected property ["+discColumn+"] but got [" + propName + "] ?";
throw new JsonParseException(msg, parser.getCurrentLocation());
@@ -95,29 +99,39 @@ public class BeanDescriptorJsonHelp<T> {
// determine the sub type for this particular json object
InheritInfo localInheritInfo = inheritInfo.readType(discValue);
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
return (T) localDescriptor.jsonReadObject(parser, path);
return (T) localDescriptor.jsonReadObject(jsonRead, path);
}
protected T jsonReadObject(JsonParser parser, String path) throws IOException {
protected T jsonReadObject(ReadJson readJson, String path) throws IOException {
EntityBean bean = desc.createEntityBean();
return jsonReadProperties(parser, bean);
return jsonReadProperties(readJson, bean, path);
}
@SuppressWarnings("unchecked")
protected T jsonReadProperties(JsonParser parser, EntityBean bean) throws IOException {
protected T jsonReadProperties(ReadJson readJson, EntityBean bean, String path) throws IOException {
if (path != null) {
readJson.pushPath(path);
}
// unmapped properties, send to JsonReadBeanVisitor later
Map<String,Object> unmappedProperties = null;
do {
JsonParser parser = readJson.getParser();
JsonToken event = parser.nextToken();
if (JsonToken.FIELD_NAME == event) {
String key = parser.getCurrentName();
BeanProperty p = desc.getBeanProperty(key);
if (p != null) {
p.jsonRead(parser, bean);
p.jsonRead(readJson, bean);
} else {
// unknown property ... read and ignore
EJson.parse(parser);
// read an unmapped property
if (unmappedProperties == null) {
unmappedProperties = new LinkedHashMap<String, Object>();
}
unmappedProperties.put(key, EJson.parse(parser));
}
} else if (JsonToken.END_OBJECT == event) {
@@ -128,6 +142,13 @@ public class BeanDescriptorJsonHelp<T> {
}
} while (true);
// visit JsonReadBeanVisitor (if registered for this path)
readJson.beanVisitor(bean, unmappedProperties);
if (path != null) {
readJson.popPath();
}
return (T)bean;
}
@@ -14,7 +14,6 @@ import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbIdentity;
import com.avaje.ebean.config.dbplatform.IdGenerator;
import com.avaje.ebean.config.dbplatform.IdType;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.TransactionEventTable;
import com.avaje.ebeaninternal.server.core.*;
@@ -104,8 +103,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private List<BeanDescriptor<?>> immutableDescriptorList;
private final Set<Integer> descriptorUniqueIds = new HashSet<Integer>();
private final DbIdentity dbIdentity;
private final DataSource dataSource;
@@ -163,8 +160,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
this.persistControllerManager = new PersistControllerManager(bootupClasses);
this.persistListenerManager = new PersistListenerManager(bootupClasses);
this.beanQueryAdapterManager = new BeanQueryAdapterManager(bootupClasses);
this.beanFinderManager = new DefaultBeanFinderManager();
this.beanFinderManager = new BeanFinderManager(bootupClasses);
this.reflectFactory = createReflectionFactory();
this.transientProperties = new TransientProperties();
@@ -286,9 +282,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (BeanDescriptor<?> desc : descMap.values()) {
String baseTable = desc.getBaseTable();
if (baseTable == null) {
} else {
if (baseTable != null) {
baseTable = baseTable.toLowerCase();
List<BeanDescriptor<?>> list = tableToDescMap.get(baseTable);
@@ -363,8 +357,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
BeanDescriptor<?> idBeanDescriptor = embId.getIdBeanDescriptor();
Class<?> idType = idBeanDescriptor.getBeanType();
try {
idType.getDeclaredMethod("hashCode", new Class[] {});
idType.getDeclaredMethod("equals", new Class[] { Object.class });
idType.getDeclaredMethod("hashCode");
idType.getDeclaredMethod("equals", Object.class);
} catch (NoSuchMethodException e) {
checkMissingHashCodeOrEquals(e, idType, d.getBeanType());
}
@@ -385,18 +379,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
return immutableDescriptorList;
}
public Map<Class<?>, BeanTable> getBeanTables() {
return beanTableMap;
}
public BeanTable getBeanTable(Class<?> type) {
return beanTableMap.get(type);
}
public Map<String, BeanDescriptor<?>> getBeanDescriptors() {
return descMap;
}
@SuppressWarnings("unchecked")
public <T> BeanManager<T> getBeanManager(Class<T> entityType) {
@@ -419,7 +405,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
int qa = beanQueryAdapterManager.getRegisterCount();
int cc = persistControllerManager.getRegisterCount();
int lc = persistListenerManager.getRegisterCount();
int fc = beanFinderManager.createBeanFinders(bootupClasses.getBeanFinders());
int fc = beanFinderManager.getRegisterCount();
logger.debug("BeanPersistControllers[" + cc + "] BeanFinders[" + fc + "] BeanPersistListeners[" + lc + "] BeanQueryAdapters[" + qa + "]");
}
@@ -447,7 +433,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private void readEmbeddedDeployment() {
ArrayList<Class<?>> embeddedClasses = bootupClasses.getEmbeddables();
List<Class<?>> embeddedClasses = bootupClasses.getEmbeddables();
for (int i = 0; i < embeddedClasses.size(); i++) {
Class<?> cls = embeddedClasses.get(i);
if (logger.isTraceEnabled()) {
@@ -468,7 +454,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private void readEntityDeploymentInitial() {
ArrayList<Class<?>> entityClasses = bootupClasses.getEntities();
List<Class<?>> entityClasses = bootupClasses.getEntities();
for (Class<?> entityClass : entityClasses) {
DeployBeanInfo<?> info = createDeployBeanInfo(entityClass);
@@ -539,9 +525,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
BeanDescriptor<?> desc = getBeanDescriptor(deployDesc.getBeanType());
for (DRawSqlMeta rawSqlMeta : deployDesc.getRawSqlMeta()) {
if (rawSqlMeta.getQuery() == null) {
} else {
if (rawSqlMeta.getQuery() != null) {
DeployNamedQuery nq = new DRawSqlSelectBuilder(namingConvention, desc, rawSqlMeta).parse();
desc.addNamedQuery(nq);
}
@@ -603,15 +587,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private Integer getUniqueHash(DeployBeanDescriptor<?> deployBeanDescriptor) {
int hashCode = deployBeanDescriptor.getFullName().hashCode();
for (int i = 0; i < 100000; i++) {
Integer key = Integer.valueOf(hashCode + i);
if (!descriptorUniqueIds.contains(key)) {
return key;
}
}
throw new RuntimeException("Failed to generate a unique hash for " + deployBeanDescriptor.getFullName());
return deployBeanDescriptor.getFullName().hashCode();
}
private void secondaryPropsJoins(DeployBeanInfo<?> info) {
@@ -646,7 +622,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (DeployBeanPropertyAssocOne<?> oneProp : info.getDescriptor().propertiesAssocOne()) {
if (!oneProp.isTransient()) {
if (oneProp.getMappedBy() != null) {
checkMappedByOneToOne(info, oneProp);
checkMappedByOneToOne(oneProp);
}
}
}
@@ -654,7 +630,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (DeployBeanPropertyAssocMany<?> manyProp : info.getDescriptor().propertiesAssocMany()) {
if (!manyProp.isTransient()) {
if (manyProp.isManyToMany()) {
checkMappedByManyToMany(info, manyProp);
checkMappedByManyToMany(manyProp);
} else {
checkMappedByOneToMany(info, manyProp);
}
@@ -724,7 +700,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
// search for this in the possible matches
for (String possibleMappedBy : matchSet) {
String possibleLower = possibleMappedBy.toLowerCase();
if (possibleLower.indexOf(searchName) > -1) {
if (possibleLower.contains(searchName)) {
// we have a match..
prop.setMappedBy(possibleMappedBy);
@@ -809,7 +785,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
private void checkMappedByOneToOne(DeployBeanInfo<?> info, DeployBeanPropertyAssocOne<?> prop) {
private void checkMappedByOneToOne(DeployBeanPropertyAssocOne<?> prop) {
// check that the mappedBy property is valid and read
// its associated join information if it is available
@@ -901,7 +877,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
/**
* For mappedBy copy the joins from the other side.
*/
private void checkMappedByManyToMany(DeployBeanInfo<?> info, DeployBeanPropertyAssocMany<?> prop) {
private void checkMappedByManyToMany(DeployBeanPropertyAssocMany<?> prop) {
// get the bean descriptor that holds the mappedBy property
String mappedBy = prop.getMappedBy();
@@ -957,17 +933,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private <T> void setBeanControllerFinderListener(DeployBeanDescriptor<T> descriptor) {
Class<T> beanType = descriptor.getBeanType();
persistControllerManager.addPersistControllers(descriptor);
persistListenerManager.addPersistListeners(descriptor);
beanQueryAdapterManager.addQueryAdapter(descriptor);
BeanFinder<T> beanFinder = beanFinderManager.getBeanFinder(beanType);
if (beanFinder != null) {
descriptor.setBeanFinder(beanFinder);
logger.debug("BeanFinder on[" + descriptor.getFullName() + "] " + beanFinder.getClass().getName());
}
beanFinderManager.addFindControllers(descriptor);
}
/**
@@ -1029,10 +998,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private <T> IdType setIdGeneration(DeployBeanDescriptor<T> desc) {
if (desc.propertiesId().size() == 0) {
// bean doen't have an Id property
if (!desc.isBaseTableType() || desc.getBeanFinder() != null) {
// using BeanFinder so perhaps valid without an id
} else {
// bean doesn't have an Id property
if (desc.isBaseTableType() && desc.getBeanFinder() == null) {
// expecting an id property
logger.warn(Message.msg("deploy.nouid", desc.getFullName()));
}
@@ -1120,7 +1087,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private void setScalarType(DeployBeanDescriptor<?> deployDesc) {
for (DeployBeanProperty prop : deployDesc.propertiesAll()) {
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
if (!(prop instanceof DeployBeanPropertyAssoc<?>)) {
deployUtil.setScalarType(prop);
}
}
@@ -1228,7 +1195,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (Dnode namedQueryXml : namedQueries) {
String name = (String) namedQueryXml.getAttribute("name");
String name = namedQueryXml.getAttribute("name");
Dnode query = namedQueryXml.find("query");
if (query == null) {
logger.warn("orm.xml " + deployDesc.getFullName() + " named-query missing query element?");
@@ -1271,7 +1238,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
BeanPropertiesReader reflectProps = new BeanPropertiesReader(beanType);
BeanPropertyInfo beanReflect = reflectFactory.create(beanType);
desc.setBeanReflect(beanReflect);
desc.setProperties(reflectProps.getProperties());
for (DeployBeanProperty prop : desc.propertiesAll()) {
@@ -1283,7 +1249,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
} else {
int propertyIndex = pos.intValue();
final int propertyIndex = pos;
prop.setPropertyIndex(propertyIndex);
prop.setGetter(beanReflect.getGetter(propName, propertyIndex));
prop.setSetter(beanReflect.getSetter(propName, propertyIndex));
@@ -1295,16 +1261,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
* Return true if this is a persistent field (not transient or static).
*/
private boolean isPersistentField(DeployBeanProperty prop) {
Field field = prop.getField();
int modifiers = field.getModifiers();
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) {
return false;
}
if (field.isAnnotationPresent(Transient.class)) {
return false;
}
return true;
return !(Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) && !field.isAnnotationPresent(Transient.class);
}
/**
@@ -0,0 +1,45 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.event.BeanFindController;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebean.event.BeanQueryRequest;
/**
* Wraps the old BeanFinder to make it implement BeanFindController.
*/
public class BeanFinderAdapter implements BeanFindController {
final BeanFinder beanFinder;
public BeanFinderAdapter(BeanFinder beanFinder) {
this.beanFinder = beanFinder;
}
@Override
public boolean isRegisterFor(Class<?> cls) {
return false;
}
@Override
public boolean isInterceptFind(BeanQueryRequest<?> request) {
// always intercept to support old behavior
return true;
}
@Override
public <T> T find(BeanQueryRequest<T> request) {
return (T)beanFinder.find(request);
}
@Override
public <T> BeanCollection<T> findMany(BeanQueryRequest<T> request) {
return beanFinder.findMany(request);
}
@Override
public boolean isInterceptFindMany(BeanQueryRequest<?> request) {
// always intercept to support old behavior
return true;
}
}
@@ -1,26 +1,85 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.List;
import com.avaje.ebean.event.BeanFindController;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebeaninternal.server.core.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Factory for controlling the construction of BeanFinders.
* Default implementation for BeanFinderFactory.
*/
public interface BeanFinderManager {
/**
* Return the number of beans with a registered finder.
*/
public int getRegisterCount();
public class BeanFinderManager {
/**
* Create the appropriate BeanController.
*/
public int createBeanFinders(List<Class<?>> finderClassList);
/**
* Return the BeanController for a given entity type.
*/
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType);
final Logger logger = LoggerFactory.getLogger(BeanFinderManager.class);
/**
* Register of BeanFinder instances.
*/
final Map<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
private final List<BeanFindController> list;
public BeanFinderManager(BootupClasses bootupClasses) {
list = bootupClasses.getBeanFindControllers();
List<Class<?>> beanFinders = bootupClasses.getBeanFinders();
for (Class<?> cls : beanFinders) {
Class<?> entityType = getEntityClass(cls);
try {
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
registerFor.put(entityType, beanFinder);
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
}
public int getRegisterCount() {
return registerFor.size() + list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addFindControllers(DeployBeanDescriptor<?> deployDesc) {
for (int i = 0; i < list.size(); i++) {
BeanFindController c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())) {
logger.debug("BeanFindController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.setBeanFinder(c);
}
}
// support the deprecated BeanFinder
BeanFinder beanFinder = registerFor.get(deployDesc.getBeanType());
if (beanFinder != null) {
deployDesc.setBeanFinder(new BeanFinderAdapter(beanFinder));
logger.debug("BeanFinder on[" + deployDesc.getFullName() + "] " + beanFinder.getClass().getName());
}
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private Class<?> getEntityClass(Class<?> controller) {
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
if (cls == null) {
String msg = "Could not determine the entity class (generics parameter type) from " + controller + " using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
@@ -109,8 +109,12 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
@Override
public void add(BeanCollection<?> collection, EntityBean bean) {
Object keyValue = beanProperty.getValueIntercept(bean);
((BeanMap<?, ?>) collection).internalPut(keyValue, bean);
if (bean == null) {
((BeanMap<?, ?>) collection).internalPutNull();
} else {
Object keyValue = beanProperty.getValueIntercept(bean);
((BeanMap<?, ?>) collection).internalPut(keyValue, bean);
}
}
@Override
File diff suppressed because it is too large Load Diff
@@ -74,7 +74,7 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty {
* Construct the property.
*/
public BeanPropertyAssoc(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyAssoc<T> deploy) {
super(owner, descriptor, deploy);
super(descriptor, deploy);
this.extraWhere = InternString.intern(deploy.getExtraWhere());
this.isOuterJoin = deploy.isOuterJoin();
this.beanTable = deploy.getBeanTable();
@@ -13,8 +13,8 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.fasterxml.jackson.core.JsonParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -878,7 +878,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
}
}
public void jsonRead(JsonParser parser, EntityBean parentBean) throws IOException {
jsonHelp.jsonRead(parser, parentBean);
public void jsonRead(ReadJson readJson, EntityBean parentBean) throws IOException {
jsonHelp.jsonRead(readJson, parentBean);
}
}
@@ -5,6 +5,7 @@ import java.io.IOException;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
@@ -17,12 +18,13 @@ public class BeanPropertyAssocManyJsonHelp {
this.many = many;
}
public void jsonRead(JsonParser parser, EntityBean parentBean) throws IOException {
public void jsonRead(ReadJson readJson, EntityBean parentBean) throws IOException {
if (!this.many.jsonDeserialize) {
return;
}
JsonParser parser = readJson.getParser();
JsonToken event = parser.nextToken();
if (JsonToken.VALUE_NULL == event) {
return;
@@ -34,7 +36,7 @@ public class BeanPropertyAssocManyJsonHelp {
BeanCollection<?> collection = many.createEmpty(parentBean);
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
do {
EntityBean detailBean = (EntityBean) many.targetDescriptor.jsonRead(parser, many.name);
EntityBean detailBean = (EntityBean) many.targetDescriptor.jsonRead(readJson, many.name);
if (detailBean == null) {
// read the entire array
break;
@@ -25,8 +25,8 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SplitName;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.fasterxml.jackson.core.JsonParser;
/**
* Property mapped to a joined bean.
@@ -843,9 +843,9 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
@Override
public void jsonRead(JsonParser parser, EntityBean bean) throws IOException {
public void jsonRead(ReadJson readJson, EntityBean bean) throws IOException {
if (jsonDeserialize && targetDescriptor != null) {
T assocBean = targetDescriptor.jsonRead(parser, name);
T assocBean = targetDescriptor.jsonRead(readJson, name);
setValue(bean, assocBean);
}
}
@@ -13,11 +13,11 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.fasterxml.jackson.core.JsonParser;
/**
* Property mapped to an Immutable Compound Value Object.
@@ -28,171 +28,168 @@ import com.fasterxml.jackson.core.JsonParser;
*/
public class BeanPropertyCompound extends BeanProperty {
private final CtCompoundType<?> compoundType;
private final CtCompoundType<?> compoundType;
/**
* Type Converter for scala.Option and similar type wrapping.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
private final BeanProperty[] scalarProperties;
/**
* Type Converter for scala.Option and similar type wrapping.
*/
@SuppressWarnings("rawtypes")
private final ScalarTypeConverter typeConverter;
private final LinkedHashMap<String, BeanProperty> propertyMap = new LinkedHashMap<String, BeanProperty>();
private final BeanProperty[] scalarProperties;
private final LinkedHashMap<String, CtCompoundPropertyElAdapter> nonScalarMap = new LinkedHashMap<String, CtCompoundPropertyElAdapter>();
private final LinkedHashMap<String, BeanProperty> propertyMap = new LinkedHashMap<String, BeanProperty>();
private final BeanPropertyCompoundRoot root;
/**
* Create the property.
*/
public BeanPropertyCompound(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyCompound deploy) {
private final LinkedHashMap<String, CtCompoundPropertyElAdapter> nonScalarMap = new LinkedHashMap<String, CtCompoundPropertyElAdapter>();
super(owner, descriptor, deploy);
/**
* Create the property.
*/
public BeanPropertyCompound(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertyCompound deploy) {
this.compoundType = deploy.getCompoundType();
this.typeConverter = deploy.getTypeConverter();
this.root = deploy.getFlatProperties(owner, descriptor);
super(descriptor, deploy);
this.scalarProperties = root.getScalarProperties();
this.compoundType = deploy.getCompoundType();
this.typeConverter = deploy.getTypeConverter();
for (int i = 0; i < scalarProperties.length; i++) {
propertyMap.put(scalarProperties[i].getName(), scalarProperties[i]);
}
BeanPropertyCompoundRoot root = deploy.getFlatProperties(owner, descriptor);
List<CtCompoundProperty> nonScalarPropsList = root.getNonScalarProperties();
for (int i = 0; i < nonScalarPropsList.size(); i++) {
CtCompoundProperty ctProp = nonScalarPropsList.get(i);
CtCompoundPropertyElAdapter adapter = new CtCompoundPropertyElAdapter(ctProp);
nonScalarMap.put(ctProp.getRelativeName(), adapter);
}
this.scalarProperties = root.getScalarProperties();
for (int i = 0; i < scalarProperties.length; i++) {
propertyMap.put(scalarProperties[i].getName(), scalarProperties[i]);
}
@Override
public void initialise() {
// do nothing for normal BeanProperty
if (!isTransient && compoundType == null) {
String msg = "No cvoInternalType assigned to " + descriptor.getFullName() + "." + getName();
throw new RuntimeException(msg);
}
List<CtCompoundProperty> nonScalarPropsList = root.getNonScalarProperties();
for (int i = 0; i < nonScalarPropsList.size(); i++) {
CtCompoundProperty ctProp = nonScalarPropsList.get(i);
CtCompoundPropertyElAdapter adapter = new CtCompoundPropertyElAdapter(ctProp);
nonScalarMap.put(ctProp.getRelativeName(), adapter);
}
@Override
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
for (CtCompoundPropertyElAdapter adapter : nonScalarMap.values()) {
adapter.setDeployOrder(deployOrder);
}
}
@Override
public void initialise() {
// do nothing for normal BeanProperty
if (!isTransient && compoundType == null) {
String msg = "No cvoInternalType assigned to " + descriptor.getFullName() + "." + getName();
throw new RuntimeException(msg);
}
}
@Override
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
for (CtCompoundPropertyElAdapter adapter : nonScalarMap.values()) {
adapter.setDeployOrder(deployOrder);
}
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (chain == null) {
chain = new ElPropertyChainBuilder(true, propName);
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
// first add this property
chain.add(this);
if (chain == null) {
chain = new ElPropertyChainBuilder(true, propName);
}
// first add this property
chain.add(this);
// handle all the rest of the chain handled by the
// BeanProperty (all depth for nested compound type)
BeanProperty p = propertyMap.get(remainder);
if (p != null) {
return chain.add(p).build();
}
CtCompoundPropertyElAdapter elAdapter = nonScalarMap.get(remainder);
if (elAdapter == null) {
throw new RuntimeException("property [" + remainder + "] not found in " + getFullBeanName());
}
return chain.add(elAdapter).build();
// handle all the rest of the chain handled by the
// BeanProperty (all depth for nested compound type)
BeanProperty p = propertyMap.get(remainder);
if (p != null) {
return chain.add(p).build();
}
@Override
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!isTransient) {
for (int i = 0; i < scalarProperties.length; i++) {
scalarProperties[i].appendSelect(ctx, subQuery);
}
}
CtCompoundPropertyElAdapter elAdapter = nonScalarMap.get(remainder);
if (elAdapter == null) {
throw new RuntimeException("property [" + remainder + "] not found in " + getFullBeanName());
}
return chain.add(elAdapter).build();
}
public BeanProperty[] getScalarProperties() {
return scalarProperties;
}
@Override
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
boolean assignable = (type == null || owningType.isAssignableFrom(type));
Object v = compoundType.read(ctx.getDataReader());
if (assignable) {
setValue(bean, v);
}
return v;
}
/**
* Read the data from the resultSet effectively ignoring it and returning
* null.
*/
@SuppressWarnings("unchecked")
@Override
public Object read(DbReadContext ctx) throws SQLException {
Object v = compoundType.read(ctx.getDataReader());
if (typeConverter != null){
v = typeConverter.wrapValue(v);
}
return v;
}
@Override
public void loadIgnore(DbReadContext ctx) {
compoundType.loadIgnore(ctx.getDataReader());
}
@Override
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
sqlBeanLoad.load(this);
}
@Override
public Object elGetReference(EntityBean bean) {
return bean;
}
public void jsonWrite(WriteJson ctx, EntityBean bean) throws IOException {
if (!jsonSerialize) {
return;
}
Object value = getValueIntercept(bean);
if (value == null) {
ctx.writeNull(name);
} else {
compoundType.jsonWrite(ctx, value, name);
}
}
public void jsonRead(JsonParser ctx, EntityBean bean) throws IOException {
if (!jsonDeserialize) {
return;
}
Object value = EJson.parse(ctx);
if (value == null) {
setValue(bean, null);
} else {
@SuppressWarnings("unchecked")
Map<String,Object> map = (Map<String,Object>)value;
Object objValue = compoundType.jsonConvert(map);
setValue(bean, objValue);
@Override
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!isTransient) {
for (int i = 0; i < scalarProperties.length; i++) {
scalarProperties[i].appendSelect(ctx, subQuery);
}
}
}
public BeanProperty[] getScalarProperties() {
return scalarProperties;
}
@Override
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
boolean assignable = (type == null || owningType.isAssignableFrom(type));
Object v = compoundType.read(ctx.getDataReader());
if (assignable) {
setValue(bean, v);
}
return v;
}
/**
* Read the data from the resultSet effectively ignoring it and returning
* null.
*/
@SuppressWarnings("unchecked")
@Override
public Object read(DbReadContext ctx) throws SQLException {
Object v = compoundType.read(ctx.getDataReader());
if (typeConverter != null) {
v = typeConverter.wrapValue(v);
}
return v;
}
@Override
public void loadIgnore(DbReadContext ctx) {
compoundType.loadIgnore(ctx.getDataReader());
}
@Override
public void load(SqlBeanLoad sqlBeanLoad) throws SQLException {
sqlBeanLoad.load(this);
}
@Override
public Object elGetReference(EntityBean bean) {
return bean;
}
public void jsonWrite(WriteJson ctx, EntityBean bean) throws IOException {
if (!jsonSerialize) {
return;
}
Object value = getValueIntercept(bean);
if (value == null) {
ctx.writeNull(name);
} else {
compoundType.jsonWrite(ctx, value, name);
}
}
@Override
public void jsonRead(ReadJson readJson, EntityBean bean) throws IOException {
if (!jsonDeserialize) {
return;
}
Map<String, Object> map = EJson.parseObject(readJson.getParser());
if (map == null) {
setValue(bean, null);
} else {
Object objValue = compoundType.jsonConvert(map);
setValue(bean, objValue);
}
}
}
@@ -17,18 +17,11 @@ import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
* scalar properties match to DB columns and the non-scalar ones are here solely
* to support EL expression language for nested compound types.
* </p>
*
* @author rbygrave
*/
public class BeanPropertyCompoundRoot {
private final BeanPropertySetter setter;
/**
* The method used to write the property.
*/
private final Method writeMethod;
private final String name;
private final String fullBeanName;
@@ -42,7 +35,6 @@ public class BeanPropertyCompoundRoot {
this.fullBeanName = deploy.getFullBeanName();
this.name = deploy.getName();
this.setter = deploy.getSetter();
this.writeMethod = deploy.getWriteMethod();
this.propList = new ArrayList<BeanPropertyCompoundScalar>();
this.propMap = new LinkedHashMap<String, BeanPropertyCompoundScalar>();
}
@@ -75,13 +67,7 @@ public class BeanPropertyCompoundRoot {
*/
public void setRootValue(EntityBean bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.set(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
setter.set(bean, value);
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "set " + name + " with arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
@@ -94,13 +80,7 @@ public class BeanPropertyCompoundRoot {
*/
public void setRootValueIntercept(EntityBean bean, Object value) {
try {
if (bean instanceof EntityBean) {
setter.setIntercept(bean, value);
} else {
Object[] args = new Object[1];
args[0] = value;
writeMethod.invoke(bean, args);
}
setter.setIntercept(bean, value);
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "setIntercept " + name + " arg[" + value + "] on ["+fullBeanName+"] with type[" + beanType + "] threw error";
@@ -9,6 +9,11 @@ import java.util.Set;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistRequest;
/**
* Chains multiple BeanPersistController's together.
*
* Used when multiple BeanPersistController register for the same bean type.
*/
public class ChainedBeanPersistController implements BeanPersistController {
private static final Sorter SORTER = new Sorter();
@@ -35,7 +40,6 @@ public class ChainedBeanPersistController implements BeanPersistController {
/**
* Construct given the list of BeanPersistController's.
* @param list
*/
public ChainedBeanPersistController(List<BeanPersistController> list) {
this.list = list;
@@ -43,7 +47,14 @@ public class ChainedBeanPersistController implements BeanPersistController {
Arrays.sort(c, SORTER);
this.chain = c;
}
/**
* Return the size of the chain.
*/
protected int size() {
return chain.length;
}
/**
* Register a new BeanPersistController and return the resulting chain.
*/
@@ -22,6 +22,13 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
this(addList(c1, c2));
}
/**
* Return the size of the chain.
*/
protected int size() {
return chain.length;
}
@Override
public boolean isRegisterFor(Class<?> cls) {
// never called
@@ -40,7 +47,6 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
/**
* Construct given the list of BeanPersistController's.
* @param list
*/
public ChainedBeanPersistListener(List<BeanPersistListener> list) {
this.list = list;
@@ -13,75 +13,70 @@ import com.avaje.ebeaninternal.server.type.DataReader;
* Context provided when a BeanProperty reads from a ResultSet.
*/
public interface DbReadContext {
/**
* Return the state of the object graph.
*/
public Boolean isReadOnly();
Boolean isReadOnly();
/**
* Propagate the state to the bean.
*/
public void propagateState(Object e);
void propagateState(Object e);
/**
* Return the DataReader.
*/
public DataReader getDataReader();
/**
* Return true if the query is using supplied SQL rather than generated SQL.
*/
public boolean isRawSql();
/**
* Set the JoinNode - used by proxy/reference beans for profiling.
*/
public void setCurrentPrefix(String currentPrefix, Map<String,String> pathMap);
DataReader getDataReader();
/**
* Return true if we are profiling this query.
*/
public boolean isAutoFetchProfiling();
/**
* Add autoFetch profiling for a loaded entity bean.
*/
public void profileBean(EntityBeanIntercept ebi, String prefix);
/**
* Return the persistence context.
*/
public PersistenceContext getPersistenceContext();
/**
* Return true if the query is using supplied SQL rather than generated SQL.
*/
boolean isRawSql();
/**
* Register a reference for lazy loading.
*/
public void register(String path, EntityBeanIntercept ebi);
/**
* Set the JoinNode - used by proxy/reference beans for profiling.
*/
void setCurrentPrefix(String currentPrefix, Map<String, String> pathMap);
/**
* Register a collection for lazy loading.
*/
public void register(String path, BeanCollection<?> bc);
/**
* Return true if we are profiling this query.
*/
boolean isAutoFetchProfiling();
/**
* Return the property that is associated with the many. There can only be
* one. This can be null.
*/
public BeanPropertyAssocMany<?> getManyProperty();
/**
* Add autoFetch profiling for a loaded entity bean.
*/
void profileBean(EntityBeanIntercept ebi, String prefix);
/**
* Set back the bean that has just been loaded with its id.
*/
public void setLoadedBean(EntityBean loadedBean, Object id, Object lazyLoadParentId);
/**
* Return the persistence context.
*/
PersistenceContext getPersistenceContext();
/**
* Set back the 'detail' bean that has just been loaded.
*/
public void setLoadedManyBean(EntityBean loadedBean);
/**
* Return the query mode.
*/
public SpiQuery.Mode getQueryMode();
/**
* Register a reference for lazy loading.
*/
void register(String path, EntityBeanIntercept ebi);
/**
* Register a collection for lazy loading.
*/
void register(String path, BeanCollection<?> bc);
/**
* Return the property that is associated with the many. There can only be
* one. This can be null.
*/
BeanPropertyAssocMany<?> getManyProperty();
/**
* Set back the bean that has just been loaded with its id.
*/
void setLazyLoadedChildBean(EntityBean loadedBean, Object parentId);
/**
* Return the query mode.
*/
SpiQuery.Mode getQueryMode();
}
@@ -1,61 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.HashMap;
import java.util.List;
import javax.persistence.PersistenceException;
import com.avaje.ebean.event.BeanFinder;
/**
* Default implementation for BeanFinderFactory.
*/
public class DefaultBeanFinderManager implements BeanFinderManager {
HashMap<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
public int createBeanFinders(List<Class<?>> finderClassList) {
for (Class<?> cls : finderClassList) {
Class<?> entityType = getEntityClass(cls);
try {
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
registerFor.put(entityType, beanFinder);
} catch (Exception ex) {
throw new PersistenceException(ex);
}
}
return registerFor.size();
}
public int getRegisterCount() {
return registerFor.size();
}
/**
* Return the BeanFinder for a given entity type.
*/
@SuppressWarnings("unchecked")
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType) {
return (BeanFinder<T>)registerFor.get(entityType);
}
/**
* Find the entity class given the controller class.
* <p>
* This uses reflection to find the generics parameter type.
* </p>
*/
private Class<?> getEntityClass(Class<?> controller){
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
if (cls == null){
String msg = "Could not determine the entity class (generics parameter type) from "+controller+" using reflection.";
throw new PersistenceException(msg);
}
return cls;
}
}
@@ -13,31 +13,31 @@ import org.slf4j.LoggerFactory;
*/
public class PersistControllerManager {
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
private final List<BeanPersistController> list;
public PersistControllerManager(BootupClasses bootupClasses){
list = bootupClasses.getBeanPersistControllers();
private final List<BeanPersistController> list;
public PersistControllerManager(BootupClasses bootupClasses) {
list = bootupClasses.getBeanPersistControllers();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc) {
for (int i = 0; i < list.size(); i++) {
BeanPersistController c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())) {
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistController(c);
}
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc){
for (int i = 0; i < list.size(); i++) {
BeanPersistController c = list.get(i);
if (c.isRegisterFor(deployDesc.getBeanType())){
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
deployDesc.addPersistController(c);
}
}
}
}
}
@@ -1,42 +1,18 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.annotation.ConcurrencyMode;
import com.avaje.ebean.config.TableName;
import com.avaje.ebean.config.dbplatform.IdGenerator;
import com.avaje.ebean.config.dbplatform.IdType;
import com.avaje.ebean.event.BeanFinder;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebean.event.*;
import com.avaje.ebeaninternal.server.core.CacheOptions;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueContraint;
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
import com.avaje.ebeaninternal.server.deploy.*;
import javax.persistence.Entity;
import javax.persistence.MappedSuperclass;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* Describes Beans including their deployment information.
@@ -57,8 +33,6 @@ public class DeployBeanDescriptor<T> {
private static final String I_SCALAOBJECT = "scala.ScalaObject";
private static final Logger logger = LoggerFactory.getLogger(DeployBeanDescriptor.class);
/**
* Map of BeanProperty Linked so as to preserve order.
*/
@@ -100,8 +74,6 @@ public class DeployBeanDescriptor<T> {
*/
private String selectLastInsertedId;
private String lazyFetchIncludes;
/**
* The concurrency mode for beans of this type.
*/
@@ -109,11 +81,6 @@ public class DeployBeanDescriptor<T> {
private boolean updateChangesOnly;
/**
* The tables this bean is dependent on.
*/
private String[] dependantTables;
private List<CompoundUniqueContraint> compoundUniqueConstraints;
/**
@@ -122,11 +89,6 @@ public class DeployBeanDescriptor<T> {
private String baseTable;
private TableName baseTableFull;
/**
* Used to provide mechanism to new EntityBean instances. Generated code
* faster than reflection at this stage.
*/
private BeanPropertyInfo beanReflect;
private String[] properties;
/**
@@ -143,7 +105,7 @@ public class DeployBeanDescriptor<T> {
/**
* If set overrides the find implementation. Server side only.
*/
private BeanFinder<T> beanFinder;
private BeanFindController beanFinder;
/**
* The table joins for this bean. Server side only.
@@ -219,34 +181,6 @@ public class DeployBeanDescriptor<T> {
return beanTable;
}
/**
* Check all the properties to see if they all have read and write methods
* (required if using "subclassing" but not for "enhancement").
*/
public boolean checkReadAndWriteMethods() {
boolean missingMethods = false;
for (DeployBeanProperty prop : propMap.values()) {
if (!prop.isTransient()) {
String m = "";
if (prop.getReadMethod() == null) {
m += " missing readMethod ";
}
if (prop.getWriteMethod() == null) {
m += " missing writeMethod ";
}
if (!"".equals(m)) {
m += ". Should it be transient?";
String msg = "Bean property " + getFullName() + "." + prop.getName() + " has " + m;
logger.error(msg);
missingMethods = true;
}
}
}
return !missingMethods;
}
public void setEntityType(EntityType entityType) {
this.entityType = entityType;
}
@@ -317,10 +251,6 @@ public class DeployBeanDescriptor<T> {
this.properties = props;
}
public BeanPropertyInfo getBeanReflect() {
return beanReflect;
}
/**
* Return the class type this BeanDescriptor describes.
*/
@@ -328,14 +258,6 @@ public class DeployBeanDescriptor<T> {
return beanType;
}
/**
* Set the BeanReflect used to create new instances of an EntityBean. This
* could use reflection or code generation to do this.
*/
public void setBeanReflect(BeanPropertyInfo beanReflect) {
this.beanReflect = beanReflect;
}
/**
* Returns the Inheritance mapping information. This will be null if this type
* of bean is not involved in any ORM inheritance mapping.
@@ -358,10 +280,6 @@ public class DeployBeanDescriptor<T> {
return cacheOptions;
}
public boolean isNaturalKeyProperty(String name) {
return name.equals(cacheOptions.getNaturalKey());
}
public DeployBeanPropertyAssocOne<?> getUnidirectional() {
return unidirectional;
}
@@ -392,14 +310,6 @@ public class DeployBeanDescriptor<T> {
this.updateChangesOnly = updateChangesOnly;
}
/**
* Return the tables this bean is dependant on. This implies that if any of
* these tables are modified then cached beans may be invalidated.
*/
public String[] getDependantTables() {
return dependantTables;
}
/**
* Add a compound unique constraint.
*/
@@ -421,18 +331,10 @@ public class DeployBeanDescriptor<T> {
}
}
/**
* Set the tables this bean is dependant on. This implies that if any of these
* tables are modified then cached beans may be invalidated.
*/
public void setDependantTables(String[] dependantTables) {
this.dependantTables = dependantTables;
}
/**
* Return the beanFinder. Usually null unless overriding the finder.
*/
public BeanFinder<T> getBeanFinder() {
public BeanFindController getBeanFinder() {
return beanFinder;
}
@@ -440,7 +342,7 @@ public class DeployBeanDescriptor<T> {
* Set the BeanFinder to use for beans of this type. This is set to override
* the finding from the default.
*/
public void setBeanFinder(BeanFinder<T> beanFinder) {
public void setBeanFinder(BeanFindController beanFinder) {
this.beanFinder = beanFinder;
}
@@ -495,17 +397,6 @@ public class DeployBeanDescriptor<T> {
queryAdapters.add(queryAdapter);
}
/**
* Return true if this bean type should use IdGeneration.
* <p>
* If this is false and the Id is null it is assumed that a database auto
* increment feature is being used to populate the id.
* </p>
*/
public boolean isUseIdGenerator() {
return idType == IdType.GENERATOR;
}
/**
* Return the base table. Only properties mapped to the base table are by
* default persisted.
@@ -659,24 +550,6 @@ public class DeployBeanDescriptor<T> {
}
}
/**
* Return the includes for getReference().
*/
public String getLazyFetchIncludes() {
return lazyFetchIncludes;
}
/**
* Set includes to use for lazy loading by getReference(). Note queries also
* build references and includes on the actual association are used for those
* references.
*/
public void setLazyFetchIncludes(String lazyFetchIncludes) {
if (lazyFetchIncludes != null && lazyFetchIncludes.length() > 0) {
this.lazyFetchIncludes = lazyFetchIncludes;
}
}
/**
* Summary description.
*/
@@ -712,11 +585,7 @@ public class DeployBeanDescriptor<T> {
boolean hasLazyFetch = false;
for (DeployBeanProperty prop : propMap.values()) {
if (prop.isTransient()) {
// ignore transient props etc
} else if (prop instanceof DeployBeanPropertyAssocMany<?>) {
// ignore the associated many properties
} else {
if (!prop.isTransient() && !(prop instanceof DeployBeanPropertyAssocMany<?>)) {
if (prop.isFetchEager()) {
sb.append(prop.getName()).append(",");
} else {
@@ -748,7 +617,7 @@ public class DeployBeanDescriptor<T> {
LinkedHashSet<String> set = new LinkedHashSet<String>(res.length + 3);
String temp = null;
String temp;
for (int i = 0; i < res.length; i++) {
temp = res[i].trim();
if (temp.length() > 0) {
@@ -844,26 +713,6 @@ public class DeployBeanDescriptor<T> {
return list;
}
/**
* Returns 'Version' properties on this bean. These are 'Counter' or 'Update
* Timestamp' type properties. Note version properties can also be on embedded
* beans rather than on the bean itself.
*/
public List<DeployBeanProperty> propertiesVersion() {
ArrayList<DeployBeanProperty> list = new ArrayList<DeployBeanProperty>();
for (DeployBeanProperty prop : propMap.values()) {
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
if (!prop.isId() && prop.isVersionColumn()) {
list.add(prop);
}
}
}
return list;
}
/**
* base properties without the unique id properties.
*/
@@ -872,10 +721,8 @@ public class DeployBeanDescriptor<T> {
ArrayList<DeployBeanProperty> list = new ArrayList<DeployBeanProperty>();
for (DeployBeanProperty prop : propMap.values()) {
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
if (!prop.isId()) {
list.add(prop);
}
if (!(prop instanceof DeployBeanPropertyAssoc<?>) && !prop.isId()) {
list.add(prop);
}
}
@@ -195,11 +195,6 @@ public class DeployBeanProperty {
*/
private Method readMethod;
/**
* The method used to write the property.
*/
private Method writeMethod;
private int propertyIndex;
private BeanPropertyGetter getter;
@@ -454,13 +449,6 @@ public class DeployBeanProperty {
return readMethod;
}
/**
* Return the setter method.
*/
public Method getWriteMethod() {
return writeMethod;
}
/**
* Set to the owning type form a Inheritance heirarchy.
*/
@@ -850,17 +838,6 @@ public class DeployBeanProperty {
this.readMethod = readMethod;
}
/**
* Set the bean write method.
* <p>
* NB: That a BeanReflectSetter is used to actually perform the setting of
* property values to a bean. This is due to performance considerations.
* </p>
*/
public void setWriteMethod(Method writeMethod) {
this.writeMethod = writeMethod;
}
/**
* Return the property type.
*/
@@ -97,7 +97,7 @@ public class DeployBeanPropertyLists {
discDeployProp.setDbColumn(discriminatorColumn);
// create the discriminator BeanProperty and only register it in the propertyMap
BeanProperty dprop = new BeanProperty(owner, desc, discDeployProp);
BeanProperty dprop = new BeanProperty(desc, discDeployProp);
propertyMap.put(dprop.getName(), dprop);
}
@@ -188,11 +188,11 @@ public class DeployBeanPropertyLists {
* properties).
*/
public BeanProperty[] getBaseScalar() {
return (BeanProperty[]) baseScalar.toArray(new BeanProperty[baseScalar.size()]);
return baseScalar.toArray(new BeanProperty[baseScalar.size()]);
}
public BeanPropertyCompound[] getBaseCompound() {
return (BeanPropertyCompound[]) baseCompound.toArray(new BeanPropertyCompound[baseCompound.size()]);
return baseCompound.toArray(new BeanPropertyCompound[baseCompound.size()]);
}
public BeanProperty getId() {
@@ -208,11 +208,11 @@ public class DeployBeanPropertyLists {
}
public BeanProperty[] getNonTransients() {
return (BeanProperty[]) nonTransients.toArray(new BeanProperty[nonTransients.size()]);
return nonTransients.toArray(new BeanProperty[nonTransients.size()]);
}
public BeanProperty[] getTransients() {
return (BeanProperty[]) transients.toArray(new BeanProperty[transients.size()]);
return transients.toArray(new BeanProperty[transients.size()]);
}
public BeanProperty getVersionProperty() {
@@ -220,27 +220,27 @@ public class DeployBeanPropertyLists {
}
public BeanProperty[] getLocal() {
return (BeanProperty[]) local.toArray(new BeanProperty[local.size()]);
return local.toArray(new BeanProperty[local.size()]);
}
public BeanProperty[] getMutable() {
return (BeanProperty[]) mutable.toArray(new BeanProperty[mutable.size()]);
return mutable.toArray(new BeanProperty[mutable.size()]);
}
public BeanPropertyAssocOne<?>[] getEmbedded() {
return (BeanPropertyAssocOne[]) embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
return embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExported() {
return (BeanPropertyAssocOne[]) onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
return onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
}
public BeanPropertyAssocOne<?>[] getOneImported() {
return (BeanPropertyAssocOne[]) onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
return onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
}
public BeanPropertyAssocOne<?>[] getOnes() {
return (BeanPropertyAssocOne[]) ones.toArray(new BeanPropertyAssocOne[ones.size()]);
return ones.toArray(new BeanPropertyAssocOne[ones.size()]);
}
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
@@ -260,11 +260,11 @@ public class DeployBeanPropertyLists {
}
public BeanProperty[] getNonMany() {
return (BeanProperty[]) nonManys.toArray(new BeanProperty[nonManys.size()]);
return nonManys.toArray(new BeanProperty[nonManys.size()]);
}
public BeanPropertyAssocMany<?>[] getMany() {
return (BeanPropertyAssocMany[]) manys.toArray(new BeanPropertyAssocMany[manys.size()]);
return manys.toArray(new BeanPropertyAssocMany[manys.size()]);
}
public BeanPropertyAssocMany<?>[] getManySave() {
@@ -283,7 +283,7 @@ public class DeployBeanPropertyLists {
* Mode used to determine which BeanPropertyAssoc to include.
*/
private enum Mode {
Save, Delete, Validate;
Save, Delete, Validate
}
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
@@ -382,6 +382,6 @@ public class DeployBeanPropertyLists {
return new BeanPropertyCompound(owner, desc, (DeployBeanPropertyCompound) deployProp);
}
return new BeanProperty(owner, desc, deployProp);
return new BeanProperty(desc, deployProp);
}
}
@@ -119,9 +119,9 @@ public class AnnotationFields extends AnnotationParser {
readGenValue(gen, prop);
}
Id id = (Id) get(prop, Id.class);
Id id = get(prop, Id.class);
if (id != null) {
readId(id, prop);
readId(prop);
}
// determine the JDBC type using Lob/Temporal
@@ -135,6 +135,21 @@ public class AnnotationFields extends AnnotationParser {
util.setLobType(prop);
}
DbJson dbJson = get(prop, DbJson.class);
if (dbJson != null) {
util.setDbJsonType(prop, dbJson);
} else {
if (get(prop, DbJsonB.class) != null) {
util.setDbJsonBType(prop);
}
}
if (get(prop, ColumnHstore.class) != null) {
util.setDbHstore(prop);
}
if (get(prop, DbHstore.class) != null) {
util.setDbHstore(prop);
}
Formula formula = get(prop, Formula.class);
if (formula != null) {
prop.setSqlFormula(formula.select(), formula.join());
@@ -202,8 +217,7 @@ public class AnnotationFields extends AnnotationParser {
}
} else {
throw new RuntimeException("Can't use EmbeddedColumns on ScalarType "
+ prop.getFullBeanName());
throw new RuntimeException("Can't use EmbeddedColumns on ScalarType " + prop.getFullBeanName());
}
}
@@ -219,8 +233,7 @@ public class AnnotationFields extends AnnotationParser {
if (!prop.isTransient()) {
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(),
prop.getDbColumn());
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) {
Encrypted encrypted = get(prop, Encrypted.class);
if (encrypted != null) {
@@ -233,7 +246,7 @@ public class AnnotationFields extends AnnotationParser {
Index index = get(prop, Index.class);
if (index != null) {
if(hasRelationshipItem(prop)) {
if (hasRelationshipItem(prop)) {
throw new RuntimeException("Can't use Index on foreign key relationships.");
}
prop.setIndexed(true);
@@ -243,8 +256,8 @@ public class AnnotationFields extends AnnotationParser {
private boolean hasRelationshipItem(DeployBeanProperty prop) {
return get(prop, OneToMany.class) != null ||
get(prop, ManyToOne.class) != null ||
get(prop, OneToOne.class) != null;
get(prop, ManyToOne.class) != null ||
get(prop, OneToOne.class) != null;
}
/**
@@ -252,13 +265,7 @@ public class AnnotationFields extends AnnotationParser {
* can be applied to DDL generation.
*/
private boolean isNotNullOnAllValidationGroups(Class<?>[] groups) {
if (groups.length == 0) {
return true;
}
if (groups.length == 1 && javax.validation.groups.Default.class.isAssignableFrom(groups[0])) {
return true;
}
return false;
return groups.length == 0 || groups.length == 1 && javax.validation.groups.Default.class.isAssignableFrom(groups[0]);
}
private void setEncryption(DeployBeanProperty prop, boolean dbEncString, int dbLen) {
@@ -324,7 +331,7 @@ public class AnnotationFields extends AnnotationParser {
return util.createDataEncryptSupport(table, column);
}
private void readId(Id id, DeployBeanProperty prop) {
private void readId(DeployBeanProperty prop) {
prop.setId(true);
prop.setNullable(false);
@@ -368,9 +375,6 @@ public class AnnotationFields extends AnnotationParser {
if (prop.getPropertyType().equals(UUID.class)) {
descriptor.setIdGeneratorName(UuidIdGenerator.AUTO_UUID);
descriptor.setIdType(IdType.GENERATOR);
} else {
// use DatabasePlatform defaults
}
}
}
@@ -414,13 +418,9 @@ public class AnnotationFields extends AnnotationParser {
String baseTable = descriptor.getBaseTable();
String tableName = columnAnn.table();
if (tableName.equals("") || tableName.equalsIgnoreCase(baseTable)) {
// its a base table property...
} else {
if (!"".equals(tableName) && !tableName.equalsIgnoreCase(baseTable)) {
// its on a secondary table...
prop.setSecondaryTable(tableName);
// DeployTableJoin tableJoin = info.getTableJoin(tableName);
// tableJoin.addProperty(prop);
}
}
@@ -1,33 +1,23 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import com.avaje.ebean.annotation.ColumnHstore;
import com.avaje.ebean.annotation.DbHstore;
import com.avaje.ebean.annotation.DbJson;
import com.avaje.ebean.annotation.DbJsonB;
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.meta.*;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.ManyToOne;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.annotation.ColumnHstore;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypePostgresHstore;
import com.avaje.ebeaninternal.server.type.TypeManager;
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
import java.lang.reflect.*;
/**
* Create the properties for a bean.
@@ -56,20 +46,6 @@ public class DeployCreateProperties {
createProperties(desc, desc.getBeanType(), 0);
desc.sortProperties();
// check the transient properties...
for (DeployBeanProperty prop : desc.propertiesAll()) {
if (prop.isTransient()) {
if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
// Typically a helper method ... this is expected
logger.trace("... transient: " + prop.getFullBeanName());
} else {
// dubious, possible error...
String msg = Message.msg("deploy.property.nofield", desc.getFullName(), prop.getName());
logger.warn(msg);
}
}
}
}
/**
@@ -109,41 +85,31 @@ public class DeployCreateProperties {
Field field = fields[i];
if (Modifier.isStatic(field.getModifiers())) {
// not interested in static fields
logger.trace("Skipping static field {} in {}", field.getName(), beanType.getName());
} else if (Modifier.isTransient(field.getModifiers())) {
// not interested in transient fields
logger.trace("Skipping transient field " + field.getName() + " in " + beanType.getName());
logger.trace("Skipping transient field {} in {}", field.getName(), beanType.getName());
} else if (ignoreFieldByName(field.getName())) {
// not interested this field (ebean or aspectJ field)
} else {
} else if (!ignoreFieldByName(field.getName())) {
String fieldName = getFieldName(field, beanType);
String initFieldName = initCap(fieldName);
Method getter = findGetter(field, initFieldName, declaredMethods, scalaObject);
Method setter = findSetter(field, initFieldName, declaredMethods, scalaObject);
DeployBeanProperty prop = createProp(desc, field, beanType, getter, setter);
if (prop == null) {
// transient annotation on unsupported type
} else {
DeployBeanProperty prop = createProp(desc, field, beanType, getter);
if (prop != null) {
// set a order that gives priority to inherited properties
// push Id/EmbeddedId up and CreatedTimestamp/UpdatedTimestamp down
int sortOverride = prop.getSortOverride();
prop.setSortOrder((level * 10000 + 100 - i + sortOverride));
DeployBeanProperty replaced = desc.addBeanProperty(prop);
if (replaced != null) {
if (replaced.isTransient()) {
// expected for inheritance...
} else {
String msg = "Huh??? property " + prop.getFullBeanName() + " being defined twice";
msg += " but replaced property was not transient? This is not expected?";
logger.warn(msg);
}
if (replaced != null && !replaced.isTransient()) {
String msg = "Huh??? property " + prop.getFullBeanName() + " being defined twice";
msg += " but replaced property was not transient? This is not expected?";
logger.warn(msg);
}
}
}
@@ -228,33 +194,6 @@ public class DeployCreateProperties {
return null;
}
/**
* Find a public non-static setter method that matches this field (according to bean-spec rules).
*/
private Method findSetter(Field field, String initFieldName, Method[] declaredMethods, boolean scalaObject) {
String methSetName = "set" + initFieldName;
String scalaSetName = field.getName() + "_$eq";
for (int i = 0; i < declaredMethods.length; i++) {
Method m = declaredMethods[i];
if ((scalaObject && m.getName().equals(scalaSetName)) || m.getName().equals(methSetName)) {
Class<?>[] params = m.getParameterTypes();
if (params.length == 1 && field.getType().equals(params[0])) {
if (void.class.equals(m.getReturnType())) {
int modifiers = m.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
return m;
}
}
}
}
}
return null;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
@@ -264,7 +203,7 @@ public class DeployCreateProperties {
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
}
} catch (NullPointerException e) {
logger.debug("expected non-scalar type" + e.getMessage());
logger.debug("expected non-scalar type {}", e.getMessage());
}
// TODO: Handle Collection of CompoundType and Embedded Type
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
@@ -282,19 +221,10 @@ public class DeployCreateProperties {
if (tt != null && !tt.equals(void.class)){
propertyType = tt;
logger.debug("target type" + tt);
}
}
Class<?> innerType = propertyType;
String specialTypeKey = getSpecialScalarType(field);
if (specialTypeKey != null) {
ScalarType<?> scalarType = typeManager.getScalarTypeFromKey(specialTypeKey);
if (scalarType == null) {
logger.error("Could not find ScalarType to match key ["+specialTypeKey+"]");
} else {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
if (isMappedType(field)) {
return new DeployBeanProperty(desc, propertyType, null, null);
}
// check for Collection type (list, set or map)
@@ -314,16 +244,16 @@ public class DeployCreateProperties {
return createManyType(desc, targetType, manyType);
}
if (innerType.isEnum() || innerType.isPrimitive()) {
if (propertyType.isEnum() || propertyType.isPrimitive()) {
return new DeployBeanProperty(desc, propertyType, null, null);
}
ScalarType<?> scalarType = typeManager.getScalarType(innerType);
ScalarType<?> scalarType = typeManager.getScalarType(propertyType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
CtCompoundType<?> compoundType = typeManager.getCompoundType(innerType);
CtCompoundType<?> compoundType = typeManager.getCompoundType(propertyType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
}
@@ -332,19 +262,19 @@ public class DeployCreateProperties {
return null;
}
try {
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(innerType);
CheckImmutableResponse checkImmutable = typeManager.checkImmutable(propertyType);
if (checkImmutable.isImmutable()) {
if (checkImmutable.isCompoundType()) {
// use reflection to support compound immutable value objects
typeManager.recursiveCreateScalarDataReader(innerType);
compoundType = typeManager.getCompoundType(innerType);
typeManager.recursiveCreateScalarDataReader(propertyType);
compoundType = typeManager.getCompoundType(propertyType);
if (compoundType != null) {
return new DeployBeanPropertyCompound(desc, propertyType, compoundType, null);
}
} else {
// use reflection to support simple immutable value objects
scalarType = typeManager.recursiveCreateScalarTypes(innerType);
scalarType = typeManager.recursiveCreateScalarTypes(propertyType);
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
}
@@ -357,13 +287,14 @@ public class DeployCreateProperties {
}
}
private String getSpecialScalarType(Field field) {
if (field.getAnnotation(ColumnHstore.class) != null) {
return ScalarTypePostgresHstore.KEY;
}
return null;
/**
* Return true if the field has one of the special mappings.
*/
private boolean isMappedType(Field field) {
return (field.getAnnotation(DbJson.class) != null)
|| (field.getAnnotation(DbJsonB.class) != null)
|| (field.getAnnotation(DbHstore.class) != null)
|| (field.getAnnotation(ColumnHstore.class) != null);
}
private boolean isTransientField(Field field) {
@@ -372,8 +303,7 @@ public class DeployCreateProperties {
return (t != null);
}
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field, Class<?> beanType,
Method getter, Method setter) {
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field, Class<?> beanType, Method getter) {
DeployBeanProperty prop = createProp(desc, field);
if (prop == null) {
@@ -383,11 +313,8 @@ public class DeployCreateProperties {
prop.setOwningType(beanType);
prop.setName(field.getName());
// the getter or setter could be null if we are using
// javaagent type enhancement. If we are using subclass
// generation then we do need to find the getter and setter
// interested in the getter for reading annotations
prop.setReadMethod(getter);
prop.setWriteMethod(setter);
prop.setField(field);
return prop;
}
@@ -5,6 +5,8 @@ import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.PersistenceException;
import com.avaje.ebean.annotation.DbJson;
import com.avaje.ebean.annotation.DbJsonType;
import com.avaje.ebean.config.EncryptDeploy;
import com.avaje.ebean.config.EncryptDeployManager;
import com.avaje.ebean.config.EncryptKeyManager;
@@ -13,6 +15,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.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.type.DataEncryptSupport;
@@ -28,201 +31,252 @@ import org.slf4j.LoggerFactory;
*/
public class DeployUtil {
private static final Logger logger = LoggerFactory.getLogger(DeployUtil.class);
private static final Logger logger = LoggerFactory.getLogger(DeployUtil.class);
/**
* Assumes CLOB rather than LONGVARCHAR.
*/
private static final int dbCLOBType = Types.CLOB;
/**
* Assumes BLOB rather than LONGVARBINARY. This should probably be
* configurable.
*/
private static final int dbBLOBType = Types.BLOB;
/**
* Assumes CLOB rather than LONGVARCHAR.
*/
private static final int dbCLOBType = Types.CLOB;
private static final int DEFAULT_JSON_VARCHAR_LENGTH = 3000;
/**
* Assumes BLOB rather than LONGVARBINARY. This should probably be
* configurable.
*/
private static final int dbBLOBType = Types.BLOB;
private final NamingConvention namingConvention;
private final NamingConvention namingConvention;
private final TypeManager typeManager;
private final TypeManager typeManager;
private final DatabasePlatform dbPlatform;
private final String manyToManyAlias;
private final EncryptDeployManager encryptDeployManager;
private final DatabasePlatform dbPlatform;
private final EncryptDeployManager encryptDeployManager;
private final EncryptKeyManager encryptKeyManager;
private final EncryptKeyManager encryptKeyManager;
private final Encryptor bytesEncryptor;
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
private final Encryptor bytesEncryptor;
this.typeManager = typeMgr;
this.namingConvention = serverConfig.getNamingConvention();
this.dbPlatform = serverConfig.getDatabasePlatform();
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
Encryptor be = serverConfig.getEncryptor();
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
// this alias is used for ManyToMany lazy loading queries
this.manyToManyAlias = "zzzzzz";
}
public TypeManager getTypeManager() {
return typeManager;
public DeployUtil(TypeManager typeMgr, ServerConfig serverConfig) {
this.typeManager = typeMgr;
this.namingConvention = serverConfig.getNamingConvention();
this.dbPlatform = serverConfig.getDatabasePlatform();
this.encryptDeployManager = serverConfig.getEncryptDeployManager();
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
Encryptor be = serverConfig.getEncryptor();
this.bytesEncryptor = be != null ? be : new SimpleAesEncryptor();
}
public TypeManager getTypeManager() {
return typeManager;
}
public DatabasePlatform getDbPlatform() {
return dbPlatform;
}
public NamingConvention getNamingConvention() {
return namingConvention;
}
/**
* Check that the EncryptKeyManager has been defined.
*/
public void checkEncryptKeyManagerDefined(String fullPropName) {
if (encryptKeyManager == null) {
String msg = "Using encryption on " + fullPropName + " but no EncryptKeyManager defined!";
throw new PersistenceException(msg);
}
}
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
if (encryptDeployManager == null) {
return EncryptDeploy.ANNOTATION;
}
return encryptDeployManager.getEncryptDeploy(table, column);
}
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
}
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
Class<?> enumType = prop.getPropertyType();
if (!enumType.isEnum()) {
throw new IllegalArgumentException("Class [" + enumType + "] is Not a Enum?");
}
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
if (scalarType == null) {
// see if it has a Mapping in avaje.properties
scalarType = typeManager.createEnumScalarType(enumType);
if (scalarType == null) {
// use JPA normal Enum type (without mapping)
EnumType type = enumerated != null ? enumerated.value() : null;
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
}
typeManager.add(scalarType);
}
prop.setScalarType(scalarType);
prop.setDbType(scalarType.getJdbcType());
return scalarType;
}
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
if (type == null) {
// default as per spec is ORDINAL
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else if (type == EnumType.ORDINAL) {
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
} else {
return new ScalarTypeEnumStandard.StringEnum(enumType);
}
}
/**
* Find the ScalarType for this property.
* <p>
* This determines if there is a conversion required from the logical (bean)
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
* </p>
*/
public void setScalarType(DeployBeanProperty property) {
if (property.getScalarType() != null) {
// already has a ScalarType assigned.
// this will be an Enum type...
return;
}
if (property instanceof DeployBeanPropertyCompound) {
// compound properties have a CvoInternalType instead
return;
}
public DatabasePlatform getDbPlatform() {
return dbPlatform;
}
ScalarType<?> scalarType = getScalarType(property);
if (scalarType != null) {
// set the jdbc type this maps to
public NamingConvention getNamingConvention() {
return namingConvention;
}
property.setDbType(scalarType.getJdbcType());
property.setScalarType(scalarType);
}
}
/**
* Check that the EncryptKeyManager has been defined.
*/
public void checkEncryptKeyManagerDefined(String fullPropName) {
if (encryptKeyManager == null){
String msg = "Using encryption on "+fullPropName+" but no EncryptKeyManager defined!";
throw new PersistenceException(msg);
}
}
public EncryptDeploy getEncryptDeploy(TableName table, String column) {
if (encryptDeployManager == null){
return EncryptDeploy.ANNOTATION;
}
return encryptDeployManager.getEncryptDeploy(table, column);
}
public DataEncryptSupport createDataEncryptSupport(String table, String column) {
return new DataEncryptSupport(encryptKeyManager, bytesEncryptor, table, column);
}
/**
* Return the table alias used for ManyToMany joins.
*/
public String getManyToManyAlias() {
return manyToManyAlias;
}
private ScalarType<?> getScalarType(DeployBeanProperty property) {
public ScalarType<?> setEnumScalarType(Enumerated enumerated, DeployBeanProperty prop) {
// Note that Temporal types already have dbType
// set via annotations
Class<?> propType = property.getPropertyType();
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
if (scalarType != null) {
return scalarType;
}
Class<?> enumType = prop.getPropertyType();
if (!enumType.isEnum()) {
throw new IllegalArgumentException("Class ["+enumType+"] is Not a Enum?");
}
ScalarType<?> scalarType = typeManager.getScalarType(enumType);
if (scalarType == null) {
// see if it has a Mapping in avaje.properties
scalarType = typeManager.createEnumScalarType(enumType);
if (scalarType == null){
// use JPA normal Enum type (without mapping)
EnumType type = enumerated != null? enumerated.value(): null;
scalarType = createEnumScalarTypePerSpec(enumType, type, prop.getDbType());
}
String msg = property.getFullBeanName() + " has no ScalarType - type[" + propType.getName() + "]";
if (!property.isTransient()) {
throw new PersistenceException(msg);
typeManager.add(scalarType);
}
prop.setScalarType(scalarType);
prop.setDbType(scalarType.getJdbcType());
return scalarType;
}
} else {
// this is ok...
logger.trace("... transient property " + msg);
return null;
}
}
private ScalarType<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type, int dbType) {
/**
* Map to Postgres HSTORE type.
*/
public void setDbHstore(DeployBeanProperty prop) {
if (type == null) {
// default as per spec is ORDINAL
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
ScalarType<?> scalarType = typeManager.getScalarType(DbType.HSTORE);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType found for HSTORE on [" + prop.getFullBeanName() + "]");
}
prop.setDbType(DbType.HSTORE);
prop.setScalarType(scalarType);
}
} else if (type == EnumType.ORDINAL) {
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
/**
* This property is marked as a Lob object.
*/
public void setDbJsonType(DeployBeanProperty prop, DbJson dbJsonType) {
} else {
return new ScalarTypeEnumStandard.StringEnum(enumType);
}
}
int dbType = getDbJsonStorage(dbJsonType.storage());
setDbJsonType(prop, dbType, dbJsonType.length());
}
/**
* Find the ScalarType for this property.
* <p>
* This determines if there is a conversion required from the logical (bean)
* type to a DB (jdbc) type. This is the case for java.util.Date etc.
* </p>
*/
public void setScalarType(DeployBeanProperty property) {
public void setDbJsonBType(DeployBeanProperty prop) {
setDbJsonType(prop, DbType.JSONB, 0);
}
if (property.getScalarType() != null){
// already has a ScalarType assigned.
// this will be an Enum type...
return;
}
if (property instanceof DeployBeanPropertyCompound){
// compound properties have a CvoInternalType instead
return;
}
private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength) {
ScalarType<?> scalarType = getScalarType(property);
if (scalarType != null){
// set the jdbc type this maps to
property.setDbType(scalarType.getJdbcType());
property.setScalarType(scalarType);
}
}
Class<?> type = prop.getPropertyType();
private ScalarType<?> getScalarType(DeployBeanProperty property) {
ScalarType<?> scalarType = typeManager.getJsonScalarType(type, dbType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for JSON type [" + type + "] [" + dbType + "]");
}
prop.setDbType(dbType);
prop.setScalarType(scalarType);
if (dbType == Types.VARCHAR) {
// determine the db column size
int columnLength = (dbLength > 0) ? dbLength : DEFAULT_JSON_VARCHAR_LENGTH;
prop.setDbLength(columnLength);
}
}
// Note that Temporal types already have dbType
// set via annotations
Class<?> propType = property.getPropertyType();
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
if (scalarType != null) {
return scalarType;
}
/**
* Return the JDBC type for the JSON storage type.
*/
private int getDbJsonStorage(DbJsonType dbJsonType) {
String msg = property.getFullBeanName()+" has no ScalarType - type[" + propType.getName() + "]";
if (!property.isTransient()){
throw new PersistenceException(msg);
switch (dbJsonType) {
case JSON:
return DbType.JSON;
case JSONB:
return DbType.JSONB;
case VARCHAR:
return Types.VARCHAR;
case CLOB:
return Types.CLOB;
case BLOB:
return Types.BLOB;
default:
return DbType.JSON;
}
}
} else {
// this is ok...
logger.trace("... transient property "+msg);
return null;
}
}
/**
* This property is marked as a Lob object.
*/
public void setLobType(DeployBeanProperty prop) {
/**
* This property is marked as a Lob object.
*/
public void setLobType(DeployBeanProperty prop) {
// is String or byte[] ? used to determine if its a CLOB or BLOB
Class<?> type = prop.getPropertyType();
// is String or byte[] ? used to determine if its a CLOB or BLOB
Class<?> type = prop.getPropertyType();
// this also sets the lob flag on DeployBeanProperty
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for LOB type ["+type+"] ["+lobType+"]");
}
prop.setDbType(lobType);
prop.setScalarType(scalarType);
}
// this also sets the lob flag on DeployBeanProperty
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
public boolean isClobType(Class<?> type){
if (type.equals(String.class)){
return true;
}
return false;
}
ScalarType<?> scalarType = typeManager.getScalarType(type, lobType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for LOB type [" + type + "] [" + lobType + "]");
}
prop.setDbType(lobType);
prop.setScalarType(scalarType);
}
public boolean isClobType(Class<?> type) {
return type.equals(String.class);
}
}
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More