mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
43
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21b04c244b | ||
|
|
957c2def43 | ||
|
|
35f9cd3821 | ||
|
|
e95d3304bf | ||
|
|
0f7c9da5d2 | ||
|
|
b4008da70c | ||
|
|
34a0f16c74 | ||
|
|
a880109201 | ||
|
|
0607151ac8 | ||
|
|
5c4ad4c01c | ||
|
|
3564504e00 | ||
|
|
49babef495 | ||
|
|
9e3362d004 | ||
|
|
3f0dcdb6d1 | ||
|
|
481116251d | ||
|
|
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 |
@@ -1,9 +1,10 @@
|
||||
[](https://waffle.io/ebean-orm/avaje-ebeanorm)
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm) - avaje-ebeanorm
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-agent) - avaje-ebeanorm-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-mavenenhancer) - avaje-ebeanorm-mavenenhancer
|
||||
|
||||
|
||||
Ebean ORM
|
||||
==============
|
||||
|
||||
Project Website
|
||||
----------------
|
||||
[http://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
|
||||
|
||||
|
||||
@@ -12,7 +13,7 @@ Maven Dependency
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.6.2</version>
|
||||
<version>4.7.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.6.3</version>
|
||||
<version>4.8.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -152,7 +152,7 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.27</version>
|
||||
<version>5.1.36</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
|
||||
@@ -480,6 +480,13 @@ public final class RawSql implements Serializable {
|
||||
this.queryHashCode = hc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is mapped.
|
||||
*/
|
||||
public boolean contains(String property) {
|
||||
return this.propertyColumnMap.containsKey(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an immutable copy of this ColumnMapping.
|
||||
*
|
||||
|
||||
@@ -55,4 +55,4 @@ public @interface CacheStrategy {
|
||||
*/
|
||||
String warmingQuery() default "";
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -44,4 +44,12 @@ public @interface CacheTuning {
|
||||
* </p>
|
||||
*/
|
||||
int maxSecsToLive() default 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The frequency (in seconds) that cache trimming should occur.
|
||||
* <p>
|
||||
* This is a hint for cache implementations that use background cache trimming.
|
||||
* </p>
|
||||
*/
|
||||
int trimFrequency() 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 {
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -48,12 +48,6 @@ public interface ServerCache {
|
||||
*/
|
||||
Object put(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Put the value in the cache but only if a matching value is not already in
|
||||
* the cache.
|
||||
*/
|
||||
Object putIfAbsent(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Remove a entry from the cache given its id.
|
||||
*/
|
||||
|
||||
+24
-5
@@ -10,6 +10,7 @@ public class ServerCacheOptions {
|
||||
private int maxSize;
|
||||
private int maxIdleSecs;
|
||||
private int maxSecsToLive;
|
||||
private int trimFrequency;
|
||||
|
||||
/**
|
||||
* Construct with no set options.
|
||||
@@ -25,15 +26,17 @@ public class ServerCacheOptions {
|
||||
this.maxSize = cacheTuning.maxSize();
|
||||
this.maxIdleSecs = cacheTuning.maxIdleSecs();
|
||||
this.maxSecsToLive = cacheTuning.maxSecsToLive();
|
||||
this.trimFrequency = cacheTuning.trimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create merging default options with the deployment specified ones.
|
||||
*/
|
||||
public ServerCacheOptions(ServerCacheOptions d) {
|
||||
this.maxSize = d.getMaxSize();
|
||||
this.maxIdleSecs = d.getMaxIdleSecs();
|
||||
this.maxSecsToLive = d.getMaxIdleSecs();
|
||||
public ServerCacheOptions(ServerCacheOptions defaults) {
|
||||
this.maxSize = defaults.getMaxSize();
|
||||
this.maxIdleSecs = defaults.getMaxIdleSecs();
|
||||
this.maxSecsToLive = defaults.getMaxIdleSecs();
|
||||
this.trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,6 +53,9 @@ public class ServerCacheOptions {
|
||||
if (maxSecsToLive == 0) {
|
||||
maxSecsToLive = defaults.getMaxSecsToLive();
|
||||
}
|
||||
if (trimFrequency == 0) {
|
||||
trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +67,7 @@ public class ServerCacheOptions {
|
||||
copy.maxSize = maxSize;
|
||||
copy.maxIdleSecs = maxIdleSecs;
|
||||
copy.maxSecsToLive = maxSecsToLive;
|
||||
|
||||
copy.trimFrequency = trimFrequency;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -107,4 +113,17 @@ public class ServerCacheOptions {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the trim frequency in seconds.
|
||||
*/
|
||||
public int getTrimFrequency() {
|
||||
return trimFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trim frequency in seconds.
|
||||
*/
|
||||
public void setTrimFrequency(int trimFrequency) {
|
||||
this.trimFrequency = trimFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
+175
-23
@@ -5,9 +5,9 @@ package com.avaje.ebean.cache;
|
||||
* <p>
|
||||
* These can be monitored to review the effectiveness of a particular cache.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* <p>
|
||||
* Depending on the cache implementation not all the statistics may be collected.
|
||||
* </p>
|
||||
*/
|
||||
public class ServerCacheStatistics {
|
||||
|
||||
@@ -17,21 +17,63 @@ public class ServerCacheStatistics {
|
||||
|
||||
protected int size;
|
||||
|
||||
protected int hitCount;
|
||||
protected long hitCount;
|
||||
|
||||
protected int missCount;
|
||||
protected long missCount;
|
||||
|
||||
protected long insertCount;
|
||||
|
||||
protected long updateCount;
|
||||
|
||||
protected long removeCount;
|
||||
|
||||
protected long clearCount;
|
||||
|
||||
protected long evictionRunCount;
|
||||
|
||||
protected long evictionRunMicros;
|
||||
|
||||
protected long evictByIdle;
|
||||
|
||||
protected long evictByTTL;
|
||||
|
||||
protected long evictByLRU;
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(cacheName);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" size:").append(size);
|
||||
sb.append(" hitRatio:").append(getHitRatio());
|
||||
sb.append(" hitCount:").append(hitCount);
|
||||
sb.append(" missCount:").append(missCount);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" hit:").append(hitCount);
|
||||
sb.append(" miss:").append(missCount);
|
||||
sb.append(" insert:").append(insertCount);
|
||||
sb.append(" update:").append(updateCount);
|
||||
sb.append(" remove:").append(removeCount);
|
||||
sb.append(" clear:").append(clearCount);
|
||||
sb.append(" evictByIdle:").append(evictByIdle);
|
||||
sb.append(" evictByTTL:").append(evictByTTL);
|
||||
sb.append(" evictByLRU:").append(evictByLRU);
|
||||
sb.append(" evictionRunCount:").append(evictionRunCount);
|
||||
sb.append(" evictionRunMicros:").append(evictionRunMicros);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
long totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int)(hitCount * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
@@ -49,28 +91,28 @@ public class ServerCacheStatistics {
|
||||
/**
|
||||
* Return the hit count. The number of successful gets.
|
||||
*/
|
||||
public int getHitCount() {
|
||||
public long getHitCount() {
|
||||
return hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hit count.
|
||||
*/
|
||||
public void setHitCount(int hitCount) {
|
||||
public void setHitCount(long hitCount) {
|
||||
this.hitCount = hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the miss count. The number of gets that returned null.
|
||||
*/
|
||||
public int getMissCount() {
|
||||
public long getMissCount() {
|
||||
return missCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the miss count.
|
||||
*/
|
||||
public void setMissCount(int missCount) {
|
||||
public void setMissCount(long missCount) {
|
||||
this.missCount = missCount;
|
||||
}
|
||||
|
||||
@@ -107,18 +149,128 @@ public class ServerCacheStatistics {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
* Set the put insert count.
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
int totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return hitCount * 100 / totalCount;
|
||||
}
|
||||
public void setInsertCount(long insertCount) {
|
||||
this.insertCount = insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put insert count.
|
||||
*/
|
||||
public long getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the put update count.
|
||||
*/
|
||||
public void setUpdateCount(long updateCount) {
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put update count.
|
||||
*/
|
||||
public long getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remove count.
|
||||
*/
|
||||
public void setRemoveCount(long removeCount) {
|
||||
this.removeCount = removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remove count.
|
||||
*/
|
||||
public long getRemoveCount() {
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clear count.
|
||||
*/
|
||||
public void setClearCount(long clearCount) {
|
||||
this.clearCount = clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the clear count.
|
||||
*/
|
||||
public long getClearCount() {
|
||||
return clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run count.
|
||||
*/
|
||||
public void setEvictionRunCount(long evictCount) {
|
||||
this.evictionRunCount = evictCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run count.
|
||||
*/
|
||||
public long getEvictionRunCount() {
|
||||
return evictionRunCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run time in micros.
|
||||
*/
|
||||
public void setEvictionRunMicros(long evictionRunMicros) {
|
||||
this.evictionRunMicros = evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run time in micros.
|
||||
*/
|
||||
public long getEvictionRunMicros() {
|
||||
return evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to idle time.
|
||||
*/
|
||||
public void setEvictByIdle(long evictByIdle) {
|
||||
this.evictByIdle = evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to idle time.
|
||||
*/
|
||||
public long getEvictByIdle() {
|
||||
return evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time to live.
|
||||
*/
|
||||
public void setEvictByTTL(long evictByTTL) {
|
||||
this.evictByTTL = evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time to live.
|
||||
*/
|
||||
public long getEvictByTTL() {
|
||||
return evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public void setEvictByLRU(long evictByLRU) {
|
||||
this.evictByLRU = evictByLRU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public long getEvictByLRU() {
|
||||
return evictByLRU;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>();
|
||||
@@ -1540,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.
|
||||
*/
|
||||
@@ -1819,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<?>>();
|
||||
|
||||
@@ -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> {
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
+354
-341
@@ -1,22 +1,18 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.cache.ServerCache;
|
||||
import com.avaje.ebean.cache.ServerCacheOptions;
|
||||
import com.avaje.ebean.cache.ServerCacheStatistics;
|
||||
import com.avaje.ebeaninternal.server.util.LongAdder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The default cache implementation.
|
||||
@@ -27,375 +23,392 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class DefaultServerCache implements ServerCache {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultServerCache.class);
|
||||
protected static final Logger logger = LoggerFactory.getLogger(DefaultServerCache.class);
|
||||
|
||||
private static final CacheEntryComparator comparator = new CacheEntryComparator();
|
||||
|
||||
private final ConcurrentHashMap<Object, CacheEntry> map = new ConcurrentHashMap<Object, CacheEntry>();
|
||||
|
||||
private final AtomicInteger missCount = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger removedHitCount = new AtomicInteger();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final String name;
|
||||
|
||||
private int maxSize;
|
||||
|
||||
private long trimFrequency;
|
||||
|
||||
private int maxIdleSecs;
|
||||
|
||||
private int maxSecsToLive;
|
||||
|
||||
public DefaultServerCache(String name, ServerCacheOptions options) {
|
||||
this(name, options.getMaxSize(), options.getMaxIdleSecs(), options.getMaxSecsToLive());
|
||||
}
|
||||
|
||||
public DefaultServerCache(String name, int maxSize, int maxIdleSecs, int maxSecsToLive) {
|
||||
this.name = name;
|
||||
this.maxSize = maxSize;
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
this.trimFrequency = 60;
|
||||
|
||||
}
|
||||
|
||||
public void init(EbeanServer server) {
|
||||
|
||||
TrimTask trim = new TrimTask();
|
||||
|
||||
BackgroundExecutor executor = server.getBackgroundExecutor();
|
||||
executor.executePeriodically(trim, trimFrequency, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ServerCacheStatistics getStatistics(boolean reset) {
|
||||
|
||||
ServerCacheStatistics s = new ServerCacheStatistics();
|
||||
s.setCacheName(name);
|
||||
s.setMaxSize(maxSize);
|
||||
|
||||
// these counters won't necessarily be consistent with
|
||||
// respect to each other as activity can occur while
|
||||
// they are being calculated
|
||||
int mc = reset ? missCount.getAndSet(0) : missCount.get();
|
||||
int hc = getHitCount(reset);
|
||||
int size = size();
|
||||
|
||||
s.setSize(size);
|
||||
s.setHitCount(hc);
|
||||
s.setMissCount(mc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public int getHitRatio() {
|
||||
|
||||
int mc = missCount.get();
|
||||
int hc = getHitCount(false);
|
||||
|
||||
int totalCount = hc + mc;
|
||||
if (totalCount == 0){
|
||||
return 0;
|
||||
} else {
|
||||
return hc * 100 / totalCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getHitCount(boolean reset) {
|
||||
|
||||
int hc = reset ? removedHitCount.getAndSet(0) : removedHitCount.get();
|
||||
|
||||
for (CacheEntry cacheEntry : map.values()) {
|
||||
hc += cacheEntry.getHitCount(reset);
|
||||
}
|
||||
|
||||
return hc;
|
||||
}
|
||||
/**
|
||||
* Compare by last access time (for LRU eviction).
|
||||
*/
|
||||
public static final CompareByLastAccess BY_LAST_ACCESS = new CompareByLastAccess();
|
||||
|
||||
|
||||
public ServerCacheOptions getOptions() {
|
||||
synchronized (monitor) {
|
||||
ServerCacheOptions o = new ServerCacheOptions();
|
||||
o.setMaxIdleSecs(maxIdleSecs);
|
||||
o.setMaxSize(maxSize);
|
||||
o.setMaxSecsToLive(maxSecsToLive);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptions(ServerCacheOptions o) {
|
||||
synchronized (monitor) {
|
||||
maxIdleSecs = o.getMaxIdleSecs();
|
||||
maxSize = o.getMaxSize();
|
||||
maxSecsToLive = o.getMaxSecsToLive();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the max cache size.
|
||||
*/
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
/**
|
||||
* The underlying map (ConcurrentHashMap or similar)
|
||||
*/
|
||||
protected final Map<Object, CacheEntry> map;
|
||||
|
||||
/**
|
||||
* Set the max cache size.
|
||||
*/
|
||||
public void setMaxSize(int maxSize) {
|
||||
synchronized (monitor) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
}
|
||||
// LongAdder is a highly concurrent low latency counter (back ported from Java8)
|
||||
protected final LongAdder missCount = new LongAdder();
|
||||
protected final LongAdder hitCount = new LongAdder();
|
||||
protected final LongAdder insertCount = new LongAdder();
|
||||
protected final LongAdder updateCount = new LongAdder();
|
||||
protected final LongAdder removeCount = new LongAdder();
|
||||
protected final LongAdder clearCount = new LongAdder();
|
||||
|
||||
/**
|
||||
* Return the max idle time.
|
||||
*/
|
||||
public long getMaxIdleSecs() {
|
||||
return maxIdleSecs;
|
||||
}
|
||||
protected final LongAdder evictByIdle = new LongAdder();
|
||||
protected final LongAdder evictByTTL = new LongAdder();
|
||||
protected final LongAdder evictByLRU = new LongAdder();
|
||||
protected final LongAdder evictCount = new LongAdder();
|
||||
protected final LongAdder evictMicros = new LongAdder();
|
||||
|
||||
/**
|
||||
* Set the max idle time.
|
||||
*/
|
||||
public void setMaxIdleSecs(int maxIdleSecs) {
|
||||
synchronized (monitor) {
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
}
|
||||
}
|
||||
protected final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* Return the maximum time to live.
|
||||
*/
|
||||
public long getMaxSecsToLive() {
|
||||
return maxSecsToLive;
|
||||
}
|
||||
protected final String name;
|
||||
|
||||
/**
|
||||
* Set the maximum time to live.
|
||||
*/
|
||||
public void setMaxSecsToLive(int maxSecsToLive) {
|
||||
synchronized (monitor) {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
protected int maxSize;
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
*/
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
protected int trimFrequency;
|
||||
|
||||
/**
|
||||
* Return a value from the cache.
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
|
||||
CacheEntry entry = map.get(key);
|
||||
|
||||
if (entry == null){
|
||||
missCount.incrementAndGet();
|
||||
return null;
|
||||
|
||||
} else {
|
||||
// get value incrementing last
|
||||
// access time and hitCount
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
protected int maxIdleSecs;
|
||||
|
||||
/**
|
||||
* Put a value into the cache.
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
// put new entry with create time
|
||||
CacheEntry entry = map.put(key, new CacheEntry(key, value));
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
int removedHits = entry.getHitCount(true);
|
||||
removedHitCount.addAndGet(removedHits);
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
protected int maxSecsToLive;
|
||||
|
||||
/**
|
||||
* Put a value into the cache but only if absent.
|
||||
*/
|
||||
public Object putIfAbsent(Object key, Object value) {
|
||||
CacheEntry entry = map.putIfAbsent(key, new CacheEntry(key, value));
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Construct using a ConcurrentHashMap and cache options.
|
||||
*/
|
||||
public DefaultServerCache(String name, ServerCacheOptions options) {
|
||||
this(name, new ConcurrentHashMap<Object, CacheEntry>(), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry from the cache.
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
CacheEntry entry = map.remove(key);
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
int removedHits = entry.getHitCount(true);
|
||||
removedHitCount.addAndGet(removedHits);
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Construct passing in name, map and base eviction controls as ServerCacheOptions.
|
||||
*/
|
||||
public DefaultServerCache(String name, Map<Object, CacheEntry> map, ServerCacheOptions options) {
|
||||
this(name, map, options.getMaxSize(), options.getMaxIdleSecs(), options.getMaxSecsToLive(), options.getTrimFrequency());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the cache.
|
||||
*/
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
/**
|
||||
* Construct passing in name, map and base eviction controls.
|
||||
*/
|
||||
public DefaultServerCache(String name, Map<Object, CacheEntry> map, int maxSize, int maxIdleSecs, int maxSecsToLive, int trimFrequency) {
|
||||
this.name = name;
|
||||
this.map = map;
|
||||
this.maxSize = maxSize;
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
this.trimFrequency = trimFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* The task used to periodically trim the cache.
|
||||
*/
|
||||
private class TrimTask implements Runnable {
|
||||
@Override
|
||||
public void init(EbeanServer server) {
|
||||
|
||||
public void run() {
|
||||
EvictionRunnable trim = new EvictionRunnable();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
if (logger.isTraceEnabled()){
|
||||
logger.trace("trimming cache " + name);
|
||||
}
|
||||
|
||||
int trimmedByIdle = 0;
|
||||
int trimmedByTTL = 0;
|
||||
int trimmedByLRU = 0;
|
||||
// default to trimming the cache every 60 seconds
|
||||
long trimFreqSecs = (trimFrequency == 0) ? 60 : trimFrequency;
|
||||
|
||||
boolean trimMaxSize = maxSize > 0 && maxSize < size();
|
||||
BackgroundExecutor executor = server.getBackgroundExecutor();
|
||||
executor.executePeriodically(trim, trimFreqSecs, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
ArrayList<CacheEntry> activeList = new ArrayList<CacheEntry>();
|
||||
@Override
|
||||
public ServerCacheStatistics getStatistics(boolean reset) {
|
||||
|
||||
long idleExpire = System.currentTimeMillis() - (maxIdleSecs*1000);
|
||||
long ttlExpire = System.currentTimeMillis() - (maxSecsToLive*1000);
|
||||
ServerCacheStatistics cacheStats = new ServerCacheStatistics();
|
||||
cacheStats.setCacheName(name);
|
||||
cacheStats.setMaxSize(maxSize);
|
||||
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
if (maxIdleSecs > 0 && idleExpire > cacheEntry.getLastAccessTime()) {
|
||||
it.remove();
|
||||
trimmedByIdle++;
|
||||
// these counters won't necessarily be consistent with
|
||||
// respect to each other as activity can occur while
|
||||
// they are being calculated here but they should be good enough
|
||||
// and we don't want to reduce concurrent use to make them consistent
|
||||
long clear = reset ? clearCount.sumThenReset() : clearCount.sum();
|
||||
long remove = reset ? removeCount.sumThenReset() : removeCount.sum();
|
||||
long update = reset ? updateCount.sumThenReset() : updateCount.sum();
|
||||
long insert = reset ? insertCount.sumThenReset() : insertCount.sum();
|
||||
long miss = reset ? missCount.sumThenReset() : missCount.sum();
|
||||
long hit = reset ? hitCount.sumThenReset() : hitCount.sum();
|
||||
|
||||
} else if (maxSecsToLive > 0 && ttlExpire > cacheEntry.getCreateTime()) {
|
||||
it.remove();
|
||||
trimmedByTTL++;
|
||||
long evict = reset ? evictCount.sumThenReset() : evictCount.sum();
|
||||
long evictTime = reset ? evictMicros.sumThenReset() : evictMicros.sum();
|
||||
long evictIdle = reset ? evictByIdle.sumThenReset() : evictByIdle.sum();
|
||||
long evictTTL = reset ? evictByTTL.sumThenReset() : evictByTTL.sum();
|
||||
long evictLRU = reset ? evictByLRU.sumThenReset() : evictByLRU.sum();
|
||||
|
||||
} else if (trimMaxSize) {
|
||||
activeList.add(cacheEntry);
|
||||
}
|
||||
}
|
||||
int size = size();
|
||||
|
||||
if (trimMaxSize) {
|
||||
trimmedByLRU = activeList.size() - maxSize;
|
||||
cacheStats.setSize(size);
|
||||
cacheStats.setHitCount(hit);
|
||||
cacheStats.setMissCount(miss);
|
||||
cacheStats.setInsertCount(insert);
|
||||
cacheStats.setUpdateCount(update);
|
||||
cacheStats.setRemoveCount(remove);
|
||||
cacheStats.setClearCount(clear);
|
||||
|
||||
if (trimmedByLRU > 0) {
|
||||
// sort into last access time ascending
|
||||
Collections.sort(activeList, comparator);
|
||||
for (int i = maxSize; i < activeList.size(); i++) {
|
||||
// remove if still in the cache
|
||||
map.remove(activeList.get(i).getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long exeTime = System.currentTimeMillis() - startTime;
|
||||
|
||||
if (logger.isDebugEnabled()){
|
||||
logger.debug("Executed trim of cache " + name + " in ["+exeTime
|
||||
+"]millis idle[" + trimmedByIdle + "] timeToLive["
|
||||
+ trimmedByTTL + "] accessTime["
|
||||
+ trimmedByLRU + "]");
|
||||
}
|
||||
cacheStats.setEvictionRunCount(evict);
|
||||
cacheStats.setEvictionRunMicros(evictTime);
|
||||
cacheStats.setEvictByIdle(evictIdle);
|
||||
cacheStats.setEvictByTTL(evictTTL);
|
||||
cacheStats.setEvictByLRU(evictLRU);
|
||||
|
||||
}
|
||||
return cacheStats;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public int getHitRatio() {
|
||||
|
||||
/**
|
||||
* Comparator for sorting by last access time.
|
||||
*/
|
||||
private static class CacheEntryComparator implements Comparator<CacheEntry>, Serializable {
|
||||
long mc = missCount.sum();
|
||||
long hc = hitCount.sum();
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
long totalCount = hc + mc;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (hc * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
public int compare(CacheEntry o1, CacheEntry o2) {
|
||||
|
||||
return o1.getLastAccessLong().compareTo(o2.getLastAccessLong());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the values to additionally hold createTime and lastAccessTime.
|
||||
*/
|
||||
public static class CacheEntry {
|
||||
/**
|
||||
* Return the options controlling the cache.
|
||||
*/
|
||||
@Override
|
||||
public ServerCacheOptions getOptions() {
|
||||
synchronized (monitor) {
|
||||
ServerCacheOptions options = new ServerCacheOptions();
|
||||
options.setMaxIdleSecs(maxIdleSecs);
|
||||
options.setMaxSize(maxSize);
|
||||
options.setMaxSecsToLive(maxSecsToLive);
|
||||
options.setTrimFrequency(trimFrequency);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
private final long createTime;
|
||||
private final AtomicInteger hitCount = new AtomicInteger();
|
||||
private Long lastAccessTime;
|
||||
/**
|
||||
* Set the options controlling the cache
|
||||
*/
|
||||
@Override
|
||||
public void setOptions(ServerCacheOptions options) {
|
||||
synchronized (monitor) {
|
||||
maxIdleSecs = options.getMaxIdleSecs();
|
||||
maxSize = options.getMaxSize();
|
||||
maxSecsToLive = options.getMaxSecsToLive();
|
||||
}
|
||||
}
|
||||
|
||||
public CacheEntry(Object key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.createTime = System.currentTimeMillis();
|
||||
this.lastAccessTime = Long.valueOf(createTime);
|
||||
}
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
/**
|
||||
* Clear the cache.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
clearCount.increment();
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
// object assignment is atomic
|
||||
hitCount.incrementAndGet();
|
||||
this.lastAccessTime = Long.valueOf(System.currentTimeMillis());
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Return a value from the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
CacheEntry entry = map.get(key);
|
||||
if (entry == null) {
|
||||
missCount.increment();
|
||||
return null;
|
||||
|
||||
public long getLastAccessTime() {
|
||||
return lastAccessTime.longValue();
|
||||
}
|
||||
} else {
|
||||
// Important that hitCount.increment() MUST be low latency under concurrent
|
||||
// use hence must use LongAdder or better here
|
||||
hitCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Long getLastAccessLong() {
|
||||
return lastAccessTime;
|
||||
}
|
||||
/**
|
||||
* Put a value into the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object put(Object key, Object value) {
|
||||
CacheEntry entry = map.put(key, new CacheEntry(key, value));
|
||||
if (entry == null) {
|
||||
insertCount.increment();
|
||||
return null;
|
||||
} else {
|
||||
updateCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public int getHitCount(boolean reset) {
|
||||
if (reset){
|
||||
return hitCount.getAndSet(0);
|
||||
/**
|
||||
* Remove an entry from the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object remove(Object key) {
|
||||
CacheEntry entry = map.remove(key);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
removeCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the cache.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size to trim to based on the max size.
|
||||
* <p>
|
||||
* This returns 90% of the max size.
|
||||
* </p>
|
||||
*/
|
||||
protected int getTrimSize() {
|
||||
return (maxSize * 90 / 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the eviction based on Idle time, Time to live and LRU last access.
|
||||
*/
|
||||
public void runEviction() {
|
||||
|
||||
long trimForMaxSize;
|
||||
if (maxSize == 0) {
|
||||
trimForMaxSize = 0;
|
||||
} else {
|
||||
trimForMaxSize = size() - maxSize;
|
||||
}
|
||||
|
||||
if (maxIdleSecs == 0 && maxSecsToLive == 0 && trimForMaxSize < 0) {
|
||||
// nothing to trim on this cache
|
||||
return;
|
||||
}
|
||||
|
||||
long startNanos = System.nanoTime();
|
||||
|
||||
long trimmedByIdle = 0;
|
||||
long trimmedByTTL = 0;
|
||||
long trimmedByLRU = 0;
|
||||
|
||||
ArrayList<CacheEntry> activeList = new ArrayList<CacheEntry>();
|
||||
|
||||
long idleExpire = System.currentTimeMillis() - (maxIdleSecs * 1000);
|
||||
long ttlExpire = System.currentTimeMillis() - (maxSecsToLive * 1000);
|
||||
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
if (maxIdleSecs > 0 && idleExpire > cacheEntry.getLastAccessTime()) {
|
||||
it.remove();
|
||||
trimmedByIdle++;
|
||||
|
||||
} else if (maxSecsToLive > 0 && ttlExpire > cacheEntry.getCreateTime()) {
|
||||
it.remove();
|
||||
trimmedByTTL++;
|
||||
|
||||
} else if (trimForMaxSize > 0) {
|
||||
activeList.add(cacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
if (trimForMaxSize > 0) {
|
||||
trimmedByLRU = activeList.size() - maxSize;
|
||||
if (trimmedByLRU > 0) {
|
||||
// sort into last access time ascending
|
||||
Collections.sort(activeList, BY_LAST_ACCESS);
|
||||
int trimSize = getTrimSize();
|
||||
for (int i = trimSize; i < activeList.size(); i++) {
|
||||
// remove if still in the cache
|
||||
map.remove(activeList.get(i).getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long exeNanos = System.nanoTime() - startNanos;
|
||||
long exeMicros = TimeUnit.MICROSECONDS.convert(exeNanos, TimeUnit.NANOSECONDS);
|
||||
|
||||
// increment the eviction statistics
|
||||
evictMicros.add(exeMicros);
|
||||
evictCount.increment();
|
||||
evictByIdle.add(trimmedByIdle);
|
||||
evictByTTL.add(trimmedByTTL);
|
||||
evictByLRU.add(trimmedByLRU);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}]"
|
||||
, name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable that calls the eviction routine.
|
||||
*/
|
||||
public class EvictionRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runEviction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator for sorting by last access time.
|
||||
*/
|
||||
public static class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public int compare(CacheEntry entry1, CacheEntry entry2) {
|
||||
return Long.compare(entry1.getLastAccessTime(), entry2.getLastAccessTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the value to additionally hold createTime and lastAccessTime and hit counter.
|
||||
*/
|
||||
public static class CacheEntry {
|
||||
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
private final long createTime;
|
||||
private long lastAccessTime;
|
||||
|
||||
public CacheEntry(Object key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.createTime = System.currentTimeMillis();
|
||||
this.lastAccessTime = createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entry key.
|
||||
*/
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entry value.
|
||||
*/
|
||||
public Object getValue() {
|
||||
// long assignment should be atomic these days (Ref Cliff Click)
|
||||
lastAccessTime = System.currentTimeMillis();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time the entry was created.
|
||||
*/
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time the entry was last accessed.
|
||||
*/
|
||||
public long getLastAccessTime() {
|
||||
return lastAccessTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return hitCount.get();
|
||||
}
|
||||
}
|
||||
public int getHitCount() {
|
||||
return hitCount.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,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;
|
||||
|
||||
@@ -47,15 +42,15 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
private ArrayList<Class<?>> transactionEventListenerList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanFinderList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanListenerList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanFindControllerList = 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 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>();
|
||||
@@ -112,6 +107,19 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
@@ -161,6 +169,22 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return findControllerInstances;
|
||||
}
|
||||
|
||||
public List<BeanPersistListener> getBeanPersistListeners() {
|
||||
// add class registered BeanPersistController to the
|
||||
// already created instances
|
||||
@@ -212,63 +236,63 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
/**
|
||||
* Return the list of Embeddable classes.
|
||||
*/
|
||||
public ArrayList<Class<?>> getEmbeddables() {
|
||||
public List<Class<?>> getEmbeddables() {
|
||||
return embeddableList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of entity classes.
|
||||
*/
|
||||
public ArrayList<Class<?>> getEntities() {
|
||||
public List<Class<?>> getEntities() {
|
||||
return entityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarTypes found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getScalarTypes() {
|
||||
public List<Class<?>> getScalarTypes() {
|
||||
return scalarTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getScalarConverters() {
|
||||
public List<Class<?>> getScalarConverters() {
|
||||
return scalarConverterList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getCompoundTypes() {
|
||||
public List<Class<?>> getCompoundTypes() {
|
||||
return compoundTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanControllers found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanControllers() {
|
||||
public List<Class<?>> getBeanControllers() {
|
||||
return beanControllerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of TransactionEventListeners found
|
||||
*/
|
||||
public ArrayList<Class<?>> getTransactionEventListenerList() {
|
||||
public List<Class<?>> getTransactionEventListenerList() {
|
||||
return transactionEventListenerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanFinders found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanFinders() {
|
||||
public List<Class<?>> getBeanFinders() {
|
||||
return beanFinderList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanListeners found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanListeners() {
|
||||
public List<Class<?>> getBeanListeners() {
|
||||
return beanListenerList;
|
||||
}
|
||||
|
||||
@@ -332,6 +356,11 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanFindController.class.isAssignableFrom(cls)) {
|
||||
beanFindControllerList.add(cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanPersistListener.class.isAssignableFrom(cls)) {
|
||||
beanListenerList.add(cls);
|
||||
interesting = true;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -219,7 +219,16 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
ServerCacheFactory cacheFactory = serverConfig.getServerCacheFactory();
|
||||
if (cacheFactory == null) {
|
||||
cacheFactory = new DefaultServerCacheFactory();
|
||||
ServiceLoader<ServerCacheFactory> cacheFactories = ServiceLoader.load(ServerCacheFactory.class);
|
||||
Iterator<ServerCacheFactory> iterator = cacheFactories.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
// use the cacheFactory (via classpath service loader)
|
||||
cacheFactory = iterator.next();
|
||||
logger.debug("using ServerCacheFactory {}", cacheFactory.getClass());
|
||||
} else {
|
||||
// use the built in default
|
||||
cacheFactory = new DefaultServerCacheFactory();
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultServerCacheManager(cacheFactory, beanOptions, queryOptions);
|
||||
@@ -233,6 +242,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 +310,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 +318,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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -153,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.
|
||||
@@ -634,7 +631,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
|
||||
public boolean calculateUseCache(Boolean queryUseCache) {
|
||||
return (queryUseCache != null) ? queryUseCache.booleanValue() : isBeanCaching();
|
||||
return (queryUseCache != null) ? queryUseCache : isBeanCaching();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1514,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;
|
||||
}
|
||||
|
||||
@@ -1525,17 +1522,35 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return queryAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register the BeanPersistListener.
|
||||
*/
|
||||
public void deregister(BeanPersistListener listener) {
|
||||
|
||||
// volatile read...
|
||||
BeanPersistListener currentListener = persistListener;
|
||||
if (currentListener != null) {
|
||||
if (currentListener instanceof ChainedBeanPersistListener) {
|
||||
// remove it from the existing chain
|
||||
persistListener = ((ChainedBeanPersistListener) currentListener).deregister(listener);
|
||||
} else if (currentListener.equals(listener)) {
|
||||
persistListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
@@ -1549,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1571,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1714,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;
|
||||
}
|
||||
@@ -1729,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) {
|
||||
@@ -1893,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,7 +303,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
// try looking up into the bean cache using the id
|
||||
T cacheBean = beanCacheGetInternal(id, query.isReadOnly());
|
||||
if (cacheBean != null) {
|
||||
setupContext(cacheBean, query, getPersistenceContext(t));
|
||||
setupContext(cacheBean, getPersistenceContext(t));
|
||||
}
|
||||
return cacheBean;
|
||||
}
|
||||
@@ -320,7 +320,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
}
|
||||
|
||||
private boolean isNaturalKeyCaching(Boolean queryUseCache) {
|
||||
return naturalKeyCache != null && (queryUseCache == null || queryUseCache.booleanValue());
|
||||
return naturalKeyCache != null && (queryUseCache == null || queryUseCache);
|
||||
}
|
||||
|
||||
private boolean isNaturalKey(String propName) {
|
||||
@@ -332,7 +332,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* For a bean built from the cache this sets up its persistence context for future lazy loading etc.
|
||||
*/
|
||||
private void setupContext(Object bean, SpiQuery<T> query, PersistenceContext context) {
|
||||
private void setupContext(Object bean, PersistenceContext context) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
}
|
||||
@@ -408,7 +408,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
public T beanCacheGet(SpiQuery<T> query, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(query.getId(), query.isReadOnly());
|
||||
if (bean != null) {
|
||||
setupContext(bean, query, context);
|
||||
setupContext(bean, context);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -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.*;
|
||||
@@ -161,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();
|
||||
@@ -407,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 + "]");
|
||||
}
|
||||
@@ -435,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()) {
|
||||
@@ -456,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);
|
||||
@@ -935,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
|
||||
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.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
@@ -533,7 +533,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
sqlBeanLoad.load(this);
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
if (prefix == null) {
|
||||
selectChain.add(name);
|
||||
} else {
|
||||
@@ -1076,7 +1076,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(JsonParser ctx, EntityBean bean) throws IOException {
|
||||
public void jsonRead(ReadJson ctx, EntityBean bean) throws IOException {
|
||||
if (!jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
@@ -1086,7 +1086,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
setValue(bean, null);
|
||||
} else {
|
||||
// expect to read non-null json value
|
||||
Object objValue = scalarType.jsonRead(ctx, event);
|
||||
Object objValue = scalarType.jsonRead(ctx.getParser(), event);
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -225,7 +225,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return createElPropertyValue(propName, remainder, chain, propertyDeploy);
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
// do not add to the selectChain at the top level of the Many bean
|
||||
}
|
||||
|
||||
@@ -878,7 +879,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;
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
@@ -25,8 +17,15 @@ 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;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Property mapped to a joined bean.
|
||||
@@ -273,17 +272,27 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return embeddedProps;
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
|
||||
prefix = SplitName.add(prefix, name);
|
||||
|
||||
if (!embedded){
|
||||
targetIdBinder.buildSelectExpressionChain(prefix, selectChain);
|
||||
|
||||
InheritInfo inheritInfo = targetDescriptor.getInheritInfo();
|
||||
if (inheritInfo != null) {
|
||||
// expect the discriminator column to be included in order
|
||||
// to determine the inheritance type so we add it to the
|
||||
// selectChain (so that it takes a position in the resultSet)
|
||||
String discriminatorColumn = inheritInfo.getDiscriminatorColumn();
|
||||
String discProperty = prefix + "." + discriminatorColumn;
|
||||
selectChain.add(discProperty);
|
||||
}
|
||||
targetIdBinder.buildRawSqlSelectChain(prefix, selectChain);
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < embeddedProps.length; i++) {
|
||||
embeddedProps[i].buildSelectExpressionChain(prefix, selectChain);
|
||||
}
|
||||
embeddedProps[i].buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -843,9 +852,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.
|
||||
@@ -177,18 +177,17 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(JsonParser ctx, EntityBean bean) throws IOException {
|
||||
@Override
|
||||
public void jsonRead(ReadJson readJson, EntityBean bean) throws IOException {
|
||||
|
||||
if (!jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object value = EJson.parse(ctx);
|
||||
if (value == null) {
|
||||
Map<String, Object> map = EJson.parseObject(readJson.getParser());
|
||||
if (map == null) {
|
||||
setValue(bean, null);
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
Object objValue = compoundType.jsonConvert(map);
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
|
||||
+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;
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
|
||||
/**
|
||||
* Default implementation for BeanFinderFactory.
|
||||
*/
|
||||
public class DefaultBeanFinderManager implements BeanFinderManager {
|
||||
|
||||
HashMap<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
|
||||
|
||||
public int createBeanFinders(List<Class<?>> finderClassList) {
|
||||
|
||||
for (Class<?> cls : finderClassList) {
|
||||
Class<?> entityType = getEntityClass(cls);
|
||||
try {
|
||||
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
|
||||
registerFor.put(entityType, beanFinder);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return registerFor.size();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return registerFor.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanFinder for a given entity type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType) {
|
||||
return (BeanFinder<T>)registerFor.get(entityType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity class given the controller class.
|
||||
* <p>
|
||||
* This uses reflection to find the generics parameter type.
|
||||
* </p>
|
||||
*/
|
||||
private Class<?> getEntityClass(Class<?> controller){
|
||||
|
||||
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
|
||||
|
||||
if (cls == null){
|
||||
String msg = "Could not determine the entity class (generics parameter type) from "+controller+" using reflection.";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
@@ -13,31 +13,31 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class PersistControllerManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
|
||||
|
||||
private final List<BeanPersistController> list;
|
||||
|
||||
public PersistControllerManager(BootupClasses bootupClasses){
|
||||
|
||||
list = bootupClasses.getBeanPersistControllers();
|
||||
private final List<BeanPersistController> list;
|
||||
|
||||
public PersistControllerManager(BootupClasses bootupClasses) {
|
||||
|
||||
list = bootupClasses.getBeanPersistControllers();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController for a given entity type.
|
||||
*/
|
||||
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanPersistController c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())) {
|
||||
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.addPersistController(c);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController for a given entity type.
|
||||
*/
|
||||
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc){
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanPersistController c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())){
|
||||
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.addPersistController(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -15,6 +8,12 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Binds id values to prepared statements.
|
||||
*/
|
||||
@@ -135,7 +134,7 @@ public interface IdBinder {
|
||||
*/
|
||||
public String getIdInValueExprDelete(int size);
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain);
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain);
|
||||
|
||||
/**
|
||||
* Read the id value from the result set and set it to the bean also returning
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
@@ -17,6 +11,12 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Bind an Id that is an Embedded bean.
|
||||
*/
|
||||
@@ -115,12 +115,12 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
return embIdProperty.getName();
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
|
||||
prefix = SplitName.add(prefix, embIdProperty.getName());
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
props[i].buildSelectExpressionChain(prefix, selectChain);
|
||||
props[i].buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -15,6 +8,12 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* For beans with no id properties AKA report type beans.
|
||||
*/
|
||||
@@ -38,7 +37,7 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
}
|
||||
|
||||
public int getPropertyCount() {
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
@@ -17,6 +10,12 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Bind an Id where the Id is made of a single property (not embedded).
|
||||
*/
|
||||
@@ -59,9 +58,9 @@ public final class IdBinderSimple implements IdBinder {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
|
||||
idProperty.buildSelectExpressionChain(prefix, selectChain);
|
||||
idProperty.buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,14 +4,10 @@ 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.*;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
@@ -109,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.
|
||||
@@ -338,7 +334,7 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* Return the beanFinder. Usually null unless overriding the finder.
|
||||
*/
|
||||
public BeanFinder<T> getBeanFinder() {
|
||||
public BeanFindController getBeanFinder() {
|
||||
return beanFinder;
|
||||
}
|
||||
|
||||
@@ -346,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -146,6 +146,9 @@ public class AnnotationFields extends AnnotationParser {
|
||||
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) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
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;
|
||||
@@ -292,6 +293,7 @@ public class DeployCreateProperties {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -265,7 +265,7 @@ public class CQueryBuilder implements Constants {
|
||||
propertyName = SplitName.parent(propertyName);
|
||||
} else if (beanProperty instanceof BeanPropertyAssocOne<?>) {
|
||||
String msg = "Column [" + column.getDbColumn() + "] mapped to complex Property[" + propertyName + "]";
|
||||
msg += ". It should be mapped to a simple property (proably the Id property). ";
|
||||
msg += ". It should be mapped to a simple property (probably the Id property). ";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
if (propertyName != null) {
|
||||
@@ -284,8 +284,16 @@ public class CQueryBuilder implements Constants {
|
||||
detail.getChunk(path, true).setDefaultProperties(null, props);
|
||||
}
|
||||
|
||||
// check if @Id property included in RawSql
|
||||
boolean rawNoId = true;
|
||||
BeanProperty idProperty = descriptor.getIdProperty();
|
||||
if (idProperty != null && columnMapping.contains(idProperty.getName())) {
|
||||
// contains the @Id property for the root level bean
|
||||
rawNoId = false;
|
||||
}
|
||||
|
||||
// build SqlTree based on OrmQueryDetail of the RawSql
|
||||
return new SqlTreeBuilder(request, predicates, detail).build();
|
||||
return new SqlTreeBuilder(request, predicates, detail, rawNoId).build();
|
||||
}
|
||||
|
||||
private SqlLimitResponse buildSql(String selectClause, OrmQueryRequest<?> request, CQueryPredicates predicates, SqlTree select) {
|
||||
|
||||
@@ -31,9 +31,11 @@ public class CQueryPlanRawSql extends CQueryPlan {
|
||||
|
||||
private int[] createIndexPositions(OrmQueryRequest<?> request, SqlTree sqlTree) {
|
||||
|
||||
List<String> chain = sqlTree.buildSelectExpressionChain();
|
||||
List<String> chain = sqlTree.buildRawSqlSelectChain();
|
||||
ColumnMapping columnMapping = request.getQuery().getRawSql().getColumnMapping();
|
||||
|
||||
// if the top level bean has inheritance expect first column
|
||||
// to be the discriminator type column (and use offset 1)
|
||||
InheritInfo inheritInfo = request.getBeanDescriptor().getInheritInfo();
|
||||
boolean addDiscriminator = inheritInfo != null;
|
||||
int offset = addDiscriminator ? 1 : 0;
|
||||
@@ -43,12 +45,25 @@ public class CQueryPlanRawSql extends CQueryPlan {
|
||||
// discriminator column must always be first in the query
|
||||
indexPositions[0] = 1;
|
||||
}
|
||||
|
||||
// set the resultSet index positions for the property expressions
|
||||
for (int i = 0; i < chain.size(); i++) {
|
||||
String expr = chain.get(i);
|
||||
int indexPos = 1 + columnMapping.getIndexPosition(expr);
|
||||
indexPositions[i + offset] = indexPos;
|
||||
}
|
||||
|
||||
// check and handle the case where a discriminator column for
|
||||
// an associated bean is in the raw SQL but is mapped columnIgnore
|
||||
for (int i = 0; i <indexPositions.length ; i++) {
|
||||
if (indexPositions[i] == 0) {
|
||||
if (i < indexPositions.length) {
|
||||
// expect discriminator column to immediately proceed id column
|
||||
indexPositions[i] = indexPositions[i+1] - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return indexPositions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebeaninternal.api.BeanIdList;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Main Finder implementation.
|
||||
@@ -27,7 +26,7 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
/**
|
||||
* Create the Finder.
|
||||
*/
|
||||
public DefaultOrmQueryEngine(BeanDescriptorManager descMgr, CQueryEngine queryEngine) {
|
||||
public DefaultOrmQueryEngine(CQueryEngine queryEngine) {
|
||||
|
||||
this.queryEngine = queryEngine;
|
||||
}
|
||||
@@ -70,11 +69,11 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
|
||||
flushJdbcBatchOnQuery(request);
|
||||
|
||||
BeanFinder<T> finder = request.getBeanFinder();
|
||||
BeanFindController finder = request.getBeanFinder();
|
||||
|
||||
BeanCollection<T> result;
|
||||
if (finder != null) {
|
||||
// this bean type has its own specific finder
|
||||
if (finder != null && finder.isInterceptFindMany(request)) {
|
||||
// intercept this request
|
||||
result = finder.findMany(request);
|
||||
} else {
|
||||
result = queryEngine.findMany(request);
|
||||
@@ -106,10 +105,10 @@ public class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
|
||||
flushJdbcBatchOnQuery(request);
|
||||
|
||||
BeanFinder<T> finder = request.getBeanFinder();
|
||||
BeanFindController finder = request.getBeanFinder();
|
||||
|
||||
T result;
|
||||
if (finder != null) {
|
||||
if (finder != null && finder.isInterceptFind(request)) {
|
||||
result = finder.find(request);
|
||||
} else {
|
||||
result = queryEngine.find(request);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents the SELECT clause part of the SQL query.
|
||||
*/
|
||||
@@ -83,9 +83,9 @@ public class SqlTree {
|
||||
/**
|
||||
* Build a select expression chain for RawSql.
|
||||
*/
|
||||
public List<String> buildSelectExpressionChain() {
|
||||
public List<String> buildRawSqlSelectChain() {
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
rootNode.buildSelectExpressionChain(list);
|
||||
rootNode.buildRawSqlSelectChain(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,15 +66,21 @@ public class SqlTreeBuilder {
|
||||
|
||||
private final boolean rawSql;
|
||||
|
||||
/**
|
||||
* rawNoId true if the RawSql does not include the @Id property
|
||||
*/
|
||||
private final boolean rawNoId;
|
||||
|
||||
private SqlTreeNode rootNode;
|
||||
|
||||
/**
|
||||
* Construct for RawSql query.
|
||||
*/
|
||||
public SqlTreeBuilder(OrmQueryRequest<?> request, CQueryPredicates predicates, OrmQueryDetail queryDetail) {
|
||||
public SqlTreeBuilder(OrmQueryRequest<?> request, CQueryPredicates predicates, OrmQueryDetail queryDetail, boolean rawNoId) {
|
||||
|
||||
this.rawSql = true;
|
||||
this.desc = request.getBeanDescriptor();
|
||||
this.rawNoId = rawNoId;
|
||||
this.query = null;
|
||||
this.subQuery = false;
|
||||
this.queryDetail = queryDetail;
|
||||
@@ -95,6 +101,7 @@ public class SqlTreeBuilder {
|
||||
OrmQueryRequest<?> request, CQueryPredicates predicates) {
|
||||
|
||||
this.rawSql = false;
|
||||
this.rawNoId = false;
|
||||
this.desc = request.getBeanDescriptor();
|
||||
this.query = request.getQuery();
|
||||
|
||||
@@ -257,7 +264,7 @@ public class SqlTreeBuilder {
|
||||
|
||||
// Optional many property for lazy loading query
|
||||
BeanPropertyAssocMany<?> lazyLoadMany = (query == null) ? null : query.getLazyLoadForParentsProperty();
|
||||
boolean withId = !subQuery && (query == null || !query.isDistinct());
|
||||
boolean withId = !rawNoId && !subQuery && (query == null || !query.isDistinct());
|
||||
return new SqlTreeNodeRoot(desc, props, myList, withId, includeJoin, lazyLoadMany);
|
||||
|
||||
} else if (prop instanceof BeanPropertyAssocMany<?>) {
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
public interface SqlTreeNode {
|
||||
|
||||
String COMMA = ", ";
|
||||
|
||||
void buildSelectExpressionChain(List<String> selectChain);
|
||||
/**
|
||||
* Build the select chain for a RawSql query.
|
||||
*/
|
||||
void buildRawSqlSelectChain(List<String> selectChain);
|
||||
|
||||
/**
|
||||
* Append the required column information to the SELECT part of the sql
|
||||
|
||||
@@ -137,18 +137,18 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(List<String> selectChain) {
|
||||
if (readId) {
|
||||
idBinder.buildSelectExpressionChain(prefix, selectChain);
|
||||
idBinder.buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
for (int i = 0, x = properties.length; i < x; i++) {
|
||||
properties[i].buildSelectExpressionChain(prefix, selectChain);
|
||||
properties[i].buildRawSqlSelectChain(prefix, selectChain);
|
||||
}
|
||||
// recursively continue reading...
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
// read each child... and let them set their
|
||||
// values back to this localBean
|
||||
children[i].buildSelectExpressionChain(selectChain);
|
||||
children[i].buildRawSqlSelectChain(selectChain);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (Mode.LAZYLOAD_BEAN.equals(queryMode)) {
|
||||
// Lazy Load does not reset the dirty state
|
||||
ebi.setLoadedLazy();
|
||||
} else {
|
||||
} else if (readId) {
|
||||
// normal bean loading
|
||||
ebi.setLoaded();
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -11,6 +7,10 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The purpose is to add an extra join to the query.
|
||||
* <p>
|
||||
@@ -35,7 +35,8 @@ public class SqlTreeNodeExtraJoin implements SqlTreeNode {
|
||||
this.manyJoin = assocBeanProperty instanceof BeanPropertyAssocMany<?>;
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(List<String> selectChain) {
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(List<String> selectChain) {
|
||||
// nothing to add
|
||||
}
|
||||
|
||||
@@ -49,7 +50,6 @@ public class SqlTreeNodeExtraJoin implements SqlTreeNode {
|
||||
return manyJoin;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -12,6 +8,9 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Join to Many (or child of a many) to support where clause predicates on many properties.
|
||||
*/
|
||||
@@ -76,7 +75,7 @@ public class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
|
||||
}
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(List<String> selectChain) {
|
||||
// nothing to add
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.text.json;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebean.text.json.*;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import com.avaje.ebean.text.json.JsonIOException;
|
||||
import com.avaje.ebean.text.json.JsonWriteOptions;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.util.ParamTypeHelper;
|
||||
@@ -56,15 +53,29 @@ public class DJsonContext implements JsonContext {
|
||||
return toBean(cls, new StringReader(json));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T toBean(Class<T> cls, String json, JsonReadOptions options) throws JsonIOException {
|
||||
return toBean(cls, new StringReader(json), options);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, Reader jsonReader) throws JsonIOException {
|
||||
return toBean(cls, createParser(jsonReader));
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, JsonParser parser) throws JsonIOException {
|
||||
public <T> T toBean(Class<T> cls, Reader jsonReader, JsonReadOptions options) throws JsonIOException {
|
||||
return toBean(cls, createParser(jsonReader), options);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, JsonParser parser) throws JsonIOException {
|
||||
return toBean(cls, parser, null);
|
||||
}
|
||||
|
||||
public <T> T toBean(Class<T> cls, JsonParser parser, JsonReadOptions options) throws JsonIOException {
|
||||
|
||||
ReadJson readJson = new ReadJson(parser, options);
|
||||
try {
|
||||
BeanDescriptor<T> d = getDescriptor(cls);
|
||||
return d.jsonRead(parser, null);
|
||||
return d.jsonRead(readJson, null);
|
||||
} catch (IOException e) {
|
||||
throw new JsonIOException(e);
|
||||
}
|
||||
@@ -74,13 +85,26 @@ public class DJsonContext implements JsonContext {
|
||||
return toList(cls, new StringReader(json));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> toList(Class<T> cls, String json, JsonReadOptions options) throws JsonIOException {
|
||||
return toList(cls, new StringReader(json), options);
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, Reader jsonReader) throws JsonIOException {
|
||||
return toList(cls, createParser(jsonReader));
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, JsonParser src) throws JsonIOException {
|
||||
public <T> List<T> toList(Class<T> cls, Reader jsonReader, JsonReadOptions options) throws JsonIOException {
|
||||
return toList(cls, createParser(jsonReader), options);
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, JsonParser src) throws JsonIOException {
|
||||
return toList(cls, src, null);
|
||||
}
|
||||
|
||||
public <T> List<T> toList(Class<T> cls, JsonParser src, JsonReadOptions options) throws JsonIOException {
|
||||
|
||||
ReadJson readJson = new ReadJson(src, options);
|
||||
try {
|
||||
BeanDescriptor<T> d = getDescriptor(cls);
|
||||
|
||||
@@ -92,7 +116,7 @@ public class DJsonContext implements JsonContext {
|
||||
}
|
||||
|
||||
do {
|
||||
T bean = d.jsonRead(src, null);
|
||||
T bean = d.jsonRead(readJson, null);
|
||||
if (bean == null) {
|
||||
break;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.avaje.ebeaninternal.server.text.json;
|
||||
|
||||
import com.avaje.ebean.text.json.JsonReadBeanVisitor;
|
||||
import com.avaje.ebean.text.json.JsonReadOptions;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Context for JSON read processing.
|
||||
*/
|
||||
public class ReadJson {
|
||||
|
||||
/**
|
||||
* Jackson parser.
|
||||
*/
|
||||
final JsonParser parser;
|
||||
|
||||
/**
|
||||
* Stack of the path - used to find the appropriate JsonReadBeanVisitor.
|
||||
*/
|
||||
final PathStack pathStack;
|
||||
|
||||
/**
|
||||
* Map of the JsonReadBeanVisitor keyed by path.
|
||||
*/
|
||||
final Map<String, JsonReadBeanVisitor<?>> visitorMap;
|
||||
|
||||
/**
|
||||
* Construct with parser and readOptions.
|
||||
*/
|
||||
public ReadJson(JsonParser parser, JsonReadOptions readOptions) {
|
||||
this.parser = parser;
|
||||
|
||||
// only create visitorMap, pathStack if needed ...
|
||||
this.visitorMap = (readOptions == null) ? null : readOptions.getVisitorMap();
|
||||
this.pathStack = (visitorMap == null) ? null : new PathStack();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonParser.
|
||||
*/
|
||||
public JsonParser getParser() {
|
||||
return parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next JsonToken from the underlying parser.
|
||||
*/
|
||||
public JsonToken nextToken() throws IOException {
|
||||
return parser.nextToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the path onto the stack (traversing a 1-M or M-1 etc)
|
||||
*/
|
||||
public void pushPath(String path) {
|
||||
if (pathStack != null) {
|
||||
pathStack.pushPathKey(path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop the path stack.
|
||||
*/
|
||||
public void popPath() {
|
||||
if (pathStack != null) {
|
||||
pathStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a JsonReadBeanVisitor registered to the current path then
|
||||
* call it's visit method with the bean and unmappedProperties.
|
||||
*/
|
||||
@SuppressWarnings(value = "unchecked")
|
||||
public void beanVisitor(Object bean, Map<String, Object> unmappedProperties) {
|
||||
if (visitorMap != null) {
|
||||
JsonReadBeanVisitor visitor = visitorMap.get(pathStack.peekWithNull());
|
||||
if (visitor != null) {
|
||||
visitor.visit(bean, unmappedProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-28
@@ -7,39 +7,39 @@ import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
*/
|
||||
public class DefaultTransactionScopeManager extends TransactionScopeManager {
|
||||
|
||||
|
||||
public DefaultTransactionScopeManager(TransactionManager transactionManager){
|
||||
super(transactionManager);
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
DefaultTransactionThreadLocal.commit(serverName);
|
||||
}
|
||||
public DefaultTransactionScopeManager(TransactionManager transactionManager) {
|
||||
super(transactionManager);
|
||||
}
|
||||
|
||||
public void end() {
|
||||
DefaultTransactionThreadLocal.end(serverName);
|
||||
}
|
||||
public void commit() {
|
||||
DefaultTransactionThreadLocal.commit(serverName);
|
||||
}
|
||||
|
||||
public SpiTransaction get() {
|
||||
SpiTransaction t = DefaultTransactionThreadLocal.get(serverName);
|
||||
if (t == null || !t.isActive()){
|
||||
return null;
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
public void end() {
|
||||
DefaultTransactionThreadLocal.end(serverName);
|
||||
}
|
||||
|
||||
public void replace(SpiTransaction trans) {
|
||||
DefaultTransactionThreadLocal.replace(serverName, trans);
|
||||
}
|
||||
public SpiTransaction get() {
|
||||
SpiTransaction t = DefaultTransactionThreadLocal.get(serverName);
|
||||
if (t == null || !t.isActive()) {
|
||||
return null;
|
||||
} else {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
public void rollback() {
|
||||
DefaultTransactionThreadLocal.rollback(serverName);
|
||||
}
|
||||
public void replace(SpiTransaction trans) {
|
||||
DefaultTransactionThreadLocal.replace(serverName, trans);
|
||||
}
|
||||
|
||||
public void rollback() {
|
||||
DefaultTransactionThreadLocal.rollback(serverName);
|
||||
}
|
||||
|
||||
public void set(SpiTransaction trans) {
|
||||
DefaultTransactionThreadLocal.set(serverName, trans);
|
||||
}
|
||||
|
||||
public void set(SpiTransaction trans) {
|
||||
DefaultTransactionThreadLocal.set(serverName, trans);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,63 +14,63 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
*/
|
||||
public final class DeleteByIdMap {
|
||||
|
||||
private final Map<String,BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
|
||||
|
||||
public String toString() {
|
||||
return beanMap.toString();
|
||||
}
|
||||
private final Map<String, BeanPersistIds> beanMap = new LinkedHashMap<String, BeanPersistIds>();
|
||||
|
||||
public void notifyCache() {
|
||||
for (BeanPersistIds deleteIds : beanMap.values()) {
|
||||
BeanDescriptor<?> d = deleteIds.getBeanDescriptor();
|
||||
List<Serializable> idValues = deleteIds.getDeleteIds();
|
||||
if (idValues != null){
|
||||
d.queryCacheClear();
|
||||
for (int i = 0; i < idValues.size(); i++) {
|
||||
d.cacheBeanRemove(idValues.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return beanMap.isEmpty();
|
||||
}
|
||||
public String toString() {
|
||||
return beanMap.toString();
|
||||
}
|
||||
|
||||
public Collection<BeanPersistIds> values() {
|
||||
return beanMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Insert Update or Delete payload.
|
||||
*/
|
||||
public void add(BeanDescriptor<?> desc, Object id) {
|
||||
|
||||
BeanPersistIds r = getPersistIds(desc);
|
||||
r.addId(PersistRequest.Type.DELETE, (Serializable)id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a List of Insert Update or Delete Id's.
|
||||
*/
|
||||
public void addList(BeanDescriptor<?> desc, List<Object> idList) {
|
||||
|
||||
BeanPersistIds r = getPersistIds(desc);
|
||||
for (int i = 0; i < idList.size(); i++) {
|
||||
r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i));
|
||||
public void notifyCache() {
|
||||
for (BeanPersistIds deleteIds : beanMap.values()) {
|
||||
BeanDescriptor<?> d = deleteIds.getBeanDescriptor();
|
||||
List<Serializable> idValues = deleteIds.getDeleteIds();
|
||||
if (idValues != null) {
|
||||
d.queryCacheClear();
|
||||
for (int i = 0; i < idValues.size(); i++) {
|
||||
d.cacheBeanRemove(idValues.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
|
||||
String beanType = desc.getFullName();
|
||||
BeanPersistIds r = beanMap.get(beanType);
|
||||
if (r == null){
|
||||
r = new BeanPersistIds(desc);
|
||||
beanMap.put(beanType, r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return beanMap.isEmpty();
|
||||
}
|
||||
|
||||
public Collection<BeanPersistIds> values() {
|
||||
return beanMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Insert Update or Delete payload.
|
||||
*/
|
||||
public void add(BeanDescriptor<?> desc, Object id) {
|
||||
|
||||
BeanPersistIds r = getPersistIds(desc);
|
||||
r.addId(PersistRequest.Type.DELETE, (Serializable) id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a List of Insert Update or Delete Id's.
|
||||
*/
|
||||
public void addList(BeanDescriptor<?> desc, List<Object> idList) {
|
||||
|
||||
BeanPersistIds r = getPersistIds(desc);
|
||||
for (int i = 0; i < idList.size(); i++) {
|
||||
r.addId(PersistRequest.Type.DELETE, (Serializable) idList.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
private BeanPersistIds getPersistIds(BeanDescriptor<?> desc) {
|
||||
String beanType = desc.getFullName();
|
||||
BeanPersistIds r = beanMap.get(beanType);
|
||||
if (r == null) {
|
||||
r = new BeanPersistIds(desc);
|
||||
beanMap.put(beanType, r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
/**
|
||||
* Set to true if the connection has autoCommit=true initially.
|
||||
*/
|
||||
protected final boolean autoCommit;
|
||||
protected boolean autoCommit;
|
||||
|
||||
protected IdentityHashMap<Object, Object> persistingBeans;
|
||||
|
||||
@@ -146,11 +146,13 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
this.batchOnCascadeMode = manager == null ? PersistBatch.NONE : manager.getPersistBatchOnCascade();
|
||||
this.onQueryOnly = manager == null ? OnQueryOnly.ROLLBACK : manager.getOnQueryOnly();
|
||||
this.persistenceContext = new DefaultPersistenceContext();
|
||||
this.autoCommit = connection.getAutoCommit();
|
||||
if (this.autoCommit) {
|
||||
connection.setAutoCommit(false);
|
||||
|
||||
if (connection != null) {
|
||||
this.autoCommit = connection.getAutoCommit();
|
||||
if (this.autoCommit) {
|
||||
connection.setAutoCommit(false);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user