mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
66
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d490966025 | ||
|
|
5bc0b01a6c | ||
|
|
2bd14db8f7 | ||
|
|
17a0933860 | ||
|
|
5bb8384567 | ||
|
|
29a6bbb6e6 | ||
|
|
46a1324f58 | ||
|
|
8f7199b586 | ||
|
|
d2c3142de4 | ||
|
|
721a50219d | ||
|
|
f0b8270e5e | ||
|
|
92232c2afb | ||
|
|
5e68b1a25e | ||
|
|
041324d177 | ||
|
|
7d02a42276 | ||
|
|
2a900165f0 | ||
|
|
e7c40e9552 | ||
|
|
0d92807308 | ||
|
|
16f7de30c6 | ||
|
|
3d250b0eca | ||
|
|
8403adac90 | ||
|
|
c006aa3f48 | ||
|
|
dcb7054248 | ||
|
|
12833bc918 | ||
|
|
71d805bc17 | ||
|
|
ab8704e2c9 | ||
|
|
327e2baae7 | ||
|
|
6e89c551d5 | ||
|
|
0a3941227f | ||
|
|
0013cb1a76 | ||
|
|
8fe91f66c0 | ||
|
|
053fdf4abb | ||
|
|
24be907dc5 | ||
|
|
6aa915b420 | ||
|
|
40d87af5b1 | ||
|
|
75082fe0c0 | ||
|
|
7d43f5a3d7 | ||
|
|
99203a35a2 | ||
|
|
67f427b83e | ||
|
|
f5a2cf8ff9 | ||
|
|
4e1cda691f | ||
|
|
64b01324d1 | ||
|
|
3cba238073 | ||
|
|
b5b4a4639f | ||
|
|
2d0a179c3b | ||
|
|
40f7a0088d | ||
|
|
6a02a8d69f | ||
|
|
ed18cbcabf | ||
|
|
3ce4f2fb35 | ||
|
|
962a27f838 | ||
|
|
2b583cf707 | ||
|
|
ef9ade4f5c | ||
|
|
b1b7774a23 | ||
|
|
c6632bbc25 | ||
|
|
8c12fc762c | ||
|
|
8cb0b13ccb | ||
|
|
c2faffb6f4 | ||
|
|
e17d823c17 | ||
|
|
9bf9338ba9 | ||
|
|
0da764ed0c | ||
|
|
43003f4a3a | ||
|
|
7081d3f54a | ||
|
|
cce2c2e28f | ||
|
|
61ecf16978 | ||
|
|
9ff4e63c32 | ||
|
|
a13fd55f64 |
@@ -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")
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
* @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 {
|
||||
* @EnumValue("N")
|
||||
*
|
||||
* @EnumValue("N")
|
||||
* NEW,
|
||||
*
|
||||
* @EnumValue("A")
|
||||
* @EnumValue("A")
|
||||
* ACTIVE,
|
||||
*
|
||||
* @EnumValue("I")
|
||||
* @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("id, totalAmount")
|
||||
* .select("id, totalAmount")
|
||||
* .setId(1).findUnique();
|
||||
*
|
||||
* // find list ... using totalAmount in the where clause
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .select("id, totalAmount")
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .select("id, totalAmount")
|
||||
* .where()
|
||||
* .eq("status", Order.Status.NEW)
|
||||
* .gt("totalAmount", 10)
|
||||
* .eq("status", Order.Status.NEW)
|
||||
* .gt("totalAmount", 10)
|
||||
* .findList();
|
||||
*
|
||||
* // as a join from customer
|
||||
* List<Customer> l0 = Ebean.find(Customer.class)
|
||||
* .select("id, name")
|
||||
* .join("orders", "status, totalAmount")
|
||||
* List<Customer> l0 = Ebean.find(Customer.class)
|
||||
* .select("id, name")
|
||||
* .fetch("orders", "status, totalAmount")
|
||||
* .where()
|
||||
* .gt("id", 0)
|
||||
* .gt("orders.totalAmount", 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...
|
||||
*
|
||||
* @OneToMany
|
||||
* @Where(clause = "deleted='y'")
|
||||
* List<Topic> 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...
|
||||
*
|
||||
* @OneToMany
|
||||
* @Where(clause = "${ta}.deleted='y'")
|
||||
* List<Topic> 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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -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";
|
||||
|
||||
+13
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+14
-167
@@ -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.
|
||||
*/
|
||||
|
||||
+15
-15
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-116
@@ -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
Reference in New Issue
Block a user