mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c447511c1 | ||
|
|
f91789886c | ||
|
|
7d14ede1b9 | ||
|
|
1ba8bc4557 | ||
|
|
a234bd1201 | ||
|
|
1c0c0893b6 | ||
|
|
ebbc560ae8 | ||
|
|
fcb9df05ad | ||
|
|
3de79b211a | ||
|
|
d93952a920 | ||
|
|
3b4836cad9 | ||
|
|
6048d97aab | ||
|
|
16d32b408e | ||
|
|
0435ab0991 | ||
|
|
95617d1bea | ||
|
|
38d0e7642e | ||
|
|
e4306ce1ab | ||
|
|
444b656780 | ||
|
|
fcbba23441 | ||
|
|
18961047a1 | ||
|
|
34347fc3e1 | ||
|
|
189e0a2ea9 | ||
|
|
182e027521 | ||
|
|
f85fa2c21d | ||
|
|
5a5f479568 | ||
|
|
9ca2486c9c | ||
|
|
656b239925 | ||
|
|
5d46904341 | ||
|
|
f0dd069ed2 | ||
|
|
5bd454bdc0 | ||
|
|
eeebaf9a08 | ||
|
|
636a148509 | ||
|
|
170cd6051e | ||
|
|
522fc2384c | ||
|
|
6f214590aa | ||
|
|
0014ea3501 | ||
|
|
db3140512f | ||
|
|
8bfa331c61 | ||
|
|
456a1d8608 | ||
|
|
695d3374a8 | ||
|
|
5488d054bf |
@@ -1,14 +1,14 @@
|
||||
avaje-ebeanorm-server
|
||||
=====================
|
||||
avaje-ebeanorm
|
||||
==============
|
||||
|
||||
The internal server implementation of EbeanORM API
|
||||
Main EbeanORM artifact
|
||||
|
||||
Maven Dependency
|
||||
----------------
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>3.2.5</version>
|
||||
<version>3.3.2</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>3.3.1-RC1</version>
|
||||
<version>3.4.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -167,10 +167,19 @@
|
||||
<!-- Enhance the meta beans -->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<version>3.3.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>main</id>
|
||||
|
||||
@@ -36,11 +36,6 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ExpressionFactory {
|
||||
|
||||
/**
|
||||
* Return the language for this expression factory.
|
||||
*/
|
||||
public String getLang();
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
|
||||
@@ -244,14 +244,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the number of rows after which the fetching should continue in a
|
||||
* background thread.
|
||||
*
|
||||
* @see Query#setBackgroundFetchAfter(int)
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the name of the property which values become the key of a map.
|
||||
*
|
||||
@@ -259,15 +251,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}.
|
||||
* Set a QueryListener for bean by bean processing.
|
||||
*
|
||||
* @see Query#setListener(QueryListener)
|
||||
* @deprecated Migrate to {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set to true to use the query for executing this query.
|
||||
*
|
||||
|
||||
@@ -269,26 +269,6 @@ import java.util.Set;
|
||||
*/
|
||||
public interface Query<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* How this query should use (or not) the Lucene Index if one is defined for
|
||||
* the bean type.
|
||||
*/
|
||||
public enum UseIndex {
|
||||
NO, DEFAULT, YES_IDS, YES_OBJECTS
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly specify how this query should use a Lucene Index if one is
|
||||
* defined for this bean type.
|
||||
*/
|
||||
public Query<T> setUseIndex(UseIndex useIndex);
|
||||
|
||||
/**
|
||||
* Return the setting for how this query should use a Lucene Index if one is
|
||||
* defined for this bean type.
|
||||
*/
|
||||
public UseIndex getUseIndex();
|
||||
|
||||
/**
|
||||
* Return the RawSql that was set to use for this query.
|
||||
*/
|
||||
@@ -683,36 +663,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
* <p>
|
||||
* Set a listener to process the query on a row by row basis.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use this when you want to process a large query and do not want to hold the
|
||||
* entire query result in memory.
|
||||
* </p>
|
||||
* <p>
|
||||
* It this case the rows are not loaded into the persistence context and
|
||||
* instead are processed by the query listener.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* QueryListener<Order> listener = ...;
|
||||
*
|
||||
* Query<Order> query = Ebean.createQuery(Order.class);
|
||||
*
|
||||
* // set the listener that will process each order one at a time
|
||||
* query.setListener(listener);
|
||||
*
|
||||
* // execute the query. Note that the returned
|
||||
* // list (emptyList) will be empty ...
|
||||
* List<Order> emtyList = query.findList();
|
||||
* </pre>
|
||||
* @deprecated Deprecated in favor of {@link #findIterate()} and {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set the Id value to query. This is used with findUnique().
|
||||
* <p>
|
||||
@@ -986,13 +936,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the rows after which fetching should continue in a background thread.
|
||||
*
|
||||
* @param backgroundFetchAfter
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the property to use as keys for a map.
|
||||
* <p>
|
||||
@@ -1072,16 +1015,14 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public String getGeneratedSql();
|
||||
|
||||
/**
|
||||
* Return the total hits matched for a lucene text search query.
|
||||
*/
|
||||
public int getTotalHits();
|
||||
|
||||
/**
|
||||
* executed the select with "for update" which should lock the record
|
||||
* "on read"
|
||||
*/
|
||||
public Query<T> setForUpdate(boolean forUpdate);
|
||||
|
||||
/**
|
||||
* Return true if this query has forUpdate set.
|
||||
*/
|
||||
public boolean isForUpdate();
|
||||
}
|
||||
|
||||
@@ -35,13 +35,6 @@ public interface Transaction extends Closeable {
|
||||
*/
|
||||
public static final int SERIALIZABLE = java.sql.Connection.TRANSACTION_SERIALIZABLE;
|
||||
|
||||
// /**
|
||||
// * You can call this after the transaction commit to wait for any changes to
|
||||
// * Lucene indexes to be made and committed. Note that generally this could
|
||||
// * be some time so it is not expected that you call this method generally.
|
||||
// */
|
||||
// public void waitForIndexUpdates();
|
||||
|
||||
/**
|
||||
* Return true if this transaction is read only.
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
|
||||
/**
|
||||
* Specify the default cache use specific entity type.
|
||||
@@ -56,9 +55,4 @@ public @interface CacheStrategy {
|
||||
*/
|
||||
String warmingQuery() default "";
|
||||
|
||||
/**
|
||||
* Default setting for using a text index if it has been defined on this bean
|
||||
* type.
|
||||
*/
|
||||
UseIndex useIndex() default UseIndex.DEFAULT;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Identifies a unique node of an object graph.
|
||||
@@ -70,7 +69,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
|
||||
public int hashCode() {
|
||||
int hc = 31 * originQueryPoint.hashCode();
|
||||
hc = 31 * hc + Objects.hashCode(path);
|
||||
hc = 31 * hc + (path == null ? 0 : path.hashCode());
|
||||
return hc;
|
||||
}
|
||||
|
||||
@@ -83,7 +82,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
}
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
return Objects.equals(e.path, path)
|
||||
return ((e.path == path) || (e.path != null && e.path.equals(path)))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,228 +0,0 @@
|
||||
package com.avaje.ebean.meta;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
||||
|
||||
/**
|
||||
* Statistics collected by AutoFetch profiling.
|
||||
*/
|
||||
@Entity
|
||||
public class MetaAutoFetchStatistic implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6640406753257176803L;
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
private ObjectGraphOrigin origin;
|
||||
|
||||
private String beanType;
|
||||
|
||||
private int counter;
|
||||
|
||||
@Transient
|
||||
private List<QueryStats> queryStats;
|
||||
|
||||
@Transient
|
||||
private List<NodeUsageStats> nodeUsageStats;
|
||||
|
||||
public MetaAutoFetchStatistic() {
|
||||
}
|
||||
|
||||
public MetaAutoFetchStatistic(ObjectGraphOrigin origin, int counter, List<QueryStats> queryStats,
|
||||
List<NodeUsageStats> nodeUsageStats) {
|
||||
|
||||
this.origin = origin;
|
||||
this.beanType = origin == null ? null : origin.getBeanType();
|
||||
this.id = origin == null ? null : origin.getKey();
|
||||
this.counter = counter;
|
||||
this.queryStats = queryStats;
|
||||
this.nodeUsageStats = nodeUsageStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the query point key.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean type.
|
||||
*/
|
||||
public String getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query point.
|
||||
*/
|
||||
public ObjectGraphOrigin getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of profiled queries the statistics is based on.
|
||||
*/
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query execution statistics.
|
||||
*/
|
||||
public List<QueryStats> getQueryStats() {
|
||||
return queryStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node usage statistics.
|
||||
*/
|
||||
public List<NodeUsageStats> getNodeUsageStats() {
|
||||
return nodeUsageStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: This will likely be deprecated in favour of a separate object graph
|
||||
* cost.
|
||||
*/
|
||||
public static class QueryStats implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5517935732867671387L;
|
||||
|
||||
private final String path;
|
||||
|
||||
private final long exeCount;
|
||||
|
||||
private final long totalBeanLoaded;
|
||||
|
||||
private final long totalMicros;
|
||||
|
||||
public QueryStats(String path, long exeCount, long totalBeanLoaded, long totalMicros) {
|
||||
this.path = path;
|
||||
this.exeCount = exeCount;
|
||||
this.totalBeanLoaded = totalBeanLoaded;
|
||||
this.totalMicros = totalMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path. This is empty string for the origin query and otherwise
|
||||
* the path for the associated lazy loading queries.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of queries executed.
|
||||
*/
|
||||
public long getExeCount() {
|
||||
return exeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total number of beans loaded by the query.
|
||||
*/
|
||||
public long getTotalBeanLoaded() {
|
||||
return totalBeanLoaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total time in microseconds of the queries.
|
||||
*/
|
||||
public long getTotalMicros() {
|
||||
return totalMicros;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
long avgMicros = exeCount == 0 ? 0 : totalMicros / exeCount;
|
||||
|
||||
return "queryExe path[" + path + "] count[" + exeCount + "] totalBeansLoaded["
|
||||
+ totalBeanLoaded + "] avgMicros[" + avgMicros + "] totalMicros[" + totalMicros
|
||||
+ "]";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects usages statistics for a given node in the object graph.
|
||||
*/
|
||||
public static class NodeUsageStats implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1786787832374844739L;
|
||||
|
||||
private final String path;
|
||||
|
||||
private final int profileCount;
|
||||
|
||||
private final int profileUsedCount;
|
||||
|
||||
private final String[] usedProperties;
|
||||
|
||||
public NodeUsageStats(String path, int profileCount, int profileUsedCount,
|
||||
String[] usedProperties) {
|
||||
this.path = path == null ? "" : path;
|
||||
this.profileCount = profileCount;
|
||||
this.profileUsedCount = profileUsedCount;
|
||||
this.usedProperties = usedProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path. This is empty string for the origin and otherwise the
|
||||
* path for the associated nodes.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of profiled beans for this node.
|
||||
*/
|
||||
public int getProfileCount() {
|
||||
return profileCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of profiled beans that where actually used for this node.
|
||||
* <p>
|
||||
* The difference between profiled and used could show uneven traversal of
|
||||
* the object graph. UI paging through results means the traversal for the
|
||||
* first x beans can be much higher than the last x beans.
|
||||
* </p>
|
||||
*/
|
||||
public int getProfileUsedCount() {
|
||||
return profileUsedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The properties used at this node.
|
||||
*/
|
||||
public String[] getUsedProperties() {
|
||||
return usedProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the properties as a Set rather than an Array.
|
||||
*/
|
||||
public Set<String> getUsedPropertiesSet() {
|
||||
LinkedHashSet<String> s = new LinkedHashSet<String>();
|
||||
for (int i = 0; i < usedProperties.length; i++) {
|
||||
s.add(usedProperties[i]);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "path[" + path + "] profileCount[" + profileCount + "] used[" + profileUsedCount
|
||||
+ "] props" + Arrays.toString(usedProperties);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package com.avaje.ebean.meta;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
||||
|
||||
/**
|
||||
* "Tuned fetch" information used by AutoFetch.
|
||||
* <p>
|
||||
* Note that the queryPoint is effectively the Id field for this bean.
|
||||
* </p>
|
||||
* <p>
|
||||
* The queryPoint identifies both the query and call stack.
|
||||
* </p>
|
||||
*/
|
||||
@Entity
|
||||
public class MetaAutoFetchTunedQueryInfo implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3119991928889170215L;
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
|
||||
private String beanType;
|
||||
|
||||
/**
|
||||
* The profile query point (call stack and query).
|
||||
*/
|
||||
private ObjectGraphOrigin origin;
|
||||
|
||||
/**
|
||||
* The tuned query details with joins and properties.
|
||||
*/
|
||||
private String tunedDetail;
|
||||
|
||||
/**
|
||||
* The number of times profiling has been collected for this query point.
|
||||
*/
|
||||
private int profileCount;
|
||||
|
||||
/**
|
||||
* The number of queries tuned by this info.
|
||||
*/
|
||||
private int tunedCount;
|
||||
|
||||
private long lastTuneTime;
|
||||
|
||||
public MetaAutoFetchTunedQueryInfo() {
|
||||
|
||||
}
|
||||
|
||||
public MetaAutoFetchTunedQueryInfo(final ObjectGraphOrigin origin, String tunedDetail,
|
||||
int profileCount, int tunedCount, long lastTuneTime) {
|
||||
|
||||
this.origin = origin;
|
||||
this.beanType = origin == null ? null : origin.getBeanType();
|
||||
this.id = origin == null ? null : origin.getKey();
|
||||
this.tunedDetail = tunedDetail;
|
||||
this.profileCount = profileCount;
|
||||
this.tunedCount = tunedCount;
|
||||
this.lastTuneTime = lastTuneTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query point key.
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of bean this is tuned for.
|
||||
*/
|
||||
public String getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query point.
|
||||
*/
|
||||
public ObjectGraphOrigin getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* The tuned query detail in string form.
|
||||
*/
|
||||
public String getTunedDetail() {
|
||||
return tunedDetail;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of profiled queries the tuned query is based on.
|
||||
*/
|
||||
public int getProfileCount() {
|
||||
return profileCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of queries tuned.
|
||||
*/
|
||||
public int getTunedCount() {
|
||||
return tunedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time of the last tune (that changed the query).
|
||||
*/
|
||||
public long getLastTuneTime() {
|
||||
return lastTuneTime;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "origin[" + origin + "] query[" + tunedDetail + "] profileCount[" + profileCount + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A hash for a query plan.
|
||||
*/
|
||||
@@ -26,7 +24,7 @@ public class HashQueryPlan {
|
||||
public int hashCode() {
|
||||
int hc = planHash;
|
||||
hc = hc * 31 + bindCount;
|
||||
hc = hc * 31 + Objects.hashCode(rawSql);
|
||||
hc = hc * 31 + (rawSql == null ? 0 : rawSql.hashCode());
|
||||
return hc;
|
||||
}
|
||||
|
||||
@@ -41,6 +39,6 @@ public class HashQueryPlan {
|
||||
HashQueryPlan e = (HashQueryPlan) obj;
|
||||
return e.planHash == planHash
|
||||
&& e.bindCount == bindCount
|
||||
&& Objects.equals(e.rawSql, rawSql);
|
||||
&& ((e.rawSql == rawSql) || (e.rawSql != null && e.rawSql.equals(rawSql)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Used to build HashQueryPlan instances.
|
||||
*/
|
||||
@@ -33,7 +31,7 @@ public class HashQueryPlanBuilder {
|
||||
* Add an object to the hash calculation.
|
||||
*/
|
||||
public HashQueryPlanBuilder add(Object object) {
|
||||
planHash = planHash * 31 + Objects.hashCode(object);
|
||||
planHash = planHash * 31 + (object == null ? 0 : object.hashCode());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -80,11 +79,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
SUBQUERY
|
||||
}
|
||||
|
||||
/**
|
||||
* Set total hits when querying against lucene.
|
||||
*/
|
||||
public void setTotalHits(int totalHits);
|
||||
|
||||
/**
|
||||
* Return true if select all properties was used to ensure the property
|
||||
@@ -514,12 +508,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public String getMapKey();
|
||||
|
||||
/**
|
||||
* Return the number of rows after which fetching should occur in a
|
||||
* background thread.
|
||||
*/
|
||||
public int getBackgroundFetchAfter();
|
||||
|
||||
/**
|
||||
* Return the maximum number of rows to return in the query.
|
||||
*/
|
||||
@@ -550,19 +538,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public Object getId();
|
||||
|
||||
/**
|
||||
* Return the queryListener.
|
||||
*/
|
||||
public QueryListener<T> getListener();
|
||||
|
||||
/**
|
||||
* Return true if this query should use its own transaction.
|
||||
* <p>
|
||||
* This is true for background fetching and when using QueryListener.
|
||||
* </p>
|
||||
*/
|
||||
public boolean createOwnTransaction();
|
||||
|
||||
/**
|
||||
* Set the generated sql for debug purposes.
|
||||
*
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.autofetch;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.avaje.ebean.bean.NodeUsageCollector;
|
||||
import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic.NodeUsageStats;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic.QueryStats;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebean.text.PathProperties.Props;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -53,30 +48,6 @@ public class Statistics implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
public MetaAutoFetchStatistic createPublicMeta() {
|
||||
|
||||
synchronized (monitor) {
|
||||
|
||||
StatisticsQuery[] sourceQueryStats = queryStatsMap.values().toArray(new StatisticsQuery[queryStatsMap.size()]);
|
||||
List<QueryStats> destQueryStats = new ArrayList<QueryStats>(sourceQueryStats.length);
|
||||
|
||||
// copy the query statistics
|
||||
for (int i = 0; i < sourceQueryStats.length; i++) {
|
||||
destQueryStats.add(sourceQueryStats[i].createPublicMeta());
|
||||
}
|
||||
|
||||
StatisticsNodeUsage[] sourceNodeUsage = nodeUsageMap.values().toArray(new StatisticsNodeUsage[nodeUsageMap.size()]);
|
||||
List<NodeUsageStats> destNodeUsage = new ArrayList<NodeUsageStats>(sourceNodeUsage.length);
|
||||
|
||||
// copy the node usage statistics
|
||||
for (int i = 0; i < sourceNodeUsage.length; i++) {
|
||||
destNodeUsage.add(sourceNodeUsage[i].createPublicMeta());
|
||||
}
|
||||
|
||||
return new MetaAutoFetchStatistic(origin, counter, destQueryStats, destNodeUsage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of times the root query has executed.
|
||||
* <p>
|
||||
|
||||
@@ -5,16 +5,16 @@ import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.bean.NodeUsageCollector;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic.NodeUsageStats;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Collects usages statistics for a given node in the object graph.
|
||||
@@ -44,13 +44,6 @@ public class StatisticsNodeUsage implements Serializable {
|
||||
this.queryTuningAddVersion = queryTuningAddVersion;
|
||||
}
|
||||
|
||||
public NodeUsageStats createPublicMeta() {
|
||||
synchronized(monitor){
|
||||
String[] usedProps = aggregateUsed.toArray(new String[aggregateUsed.size()]);
|
||||
return new NodeUsageStats(path, profileCount, profileUsedCount, usedProps);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildTunedFetch(PathProperties pathProps, BeanDescriptor<?> rootDesc) {
|
||||
|
||||
synchronized(monitor){
|
||||
|
||||
@@ -2,8 +2,6 @@ package com.avaje.ebeaninternal.server.autofetch;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic.QueryStats;
|
||||
|
||||
/**
|
||||
* Used to accumulate query execution statistics.
|
||||
*/
|
||||
@@ -22,10 +20,6 @@ public class StatisticsQuery implements Serializable {
|
||||
public StatisticsQuery(String path){
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public QueryStats createPublicMeta() {
|
||||
return new QueryStats(path, exeCount, totalBeanLoaded, totalMicros);
|
||||
}
|
||||
|
||||
public void add(long beansLoaded, long micros) {
|
||||
exeCount++;
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.avaje.ebeaninternal.server.autofetch;
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchTunedQueryInfo;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
|
||||
@@ -73,13 +72,6 @@ public class TunedQueryInfo implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this tuned fetch data for public consumption.
|
||||
*/
|
||||
public MetaAutoFetchTunedQueryInfo createPublicMeta() {
|
||||
return new MetaAutoFetchTunedQueryInfo(origin, tunedDetail.toString(), profileCount, tunedCount, lastTuneTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the number of times profiling has been collected for this query
|
||||
* point.
|
||||
|
||||
@@ -2,6 +2,11 @@ package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
@@ -11,6 +16,8 @@ import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
*/
|
||||
public abstract class BeanRequest {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BeanRequest.class);
|
||||
|
||||
/**
|
||||
* The server processing the request.
|
||||
*/
|
||||
@@ -84,7 +91,14 @@ public abstract class BeanRequest {
|
||||
*/
|
||||
public void rollbackTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
transaction.rollback();
|
||||
try {
|
||||
transaction.rollback();
|
||||
} catch (PersistenceException e) {
|
||||
// Just log this and carry on. A previous exception has been
|
||||
// thrown and if this rollback throws exception it likely means
|
||||
// that the connection is broken (and the datasource and db will cleanup)
|
||||
log.error("Error trying to rollack a transaction (after a prior exception thrown)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,16 +82,22 @@ public class BootupClassPathSearch {
|
||||
ClassPathSearchFilter filter = new ClassPathSearchFilter();
|
||||
filter.addDefaultExcludePackages();
|
||||
|
||||
if (packages != null) {
|
||||
if (packages != null && packages.size() > 0) {
|
||||
for (String packageName : packages) {
|
||||
filter.includePackage(packageName);
|
||||
}
|
||||
|
||||
// if they specified include packages, they don't want by default to include everything
|
||||
filter.setDefaultPackageMatch(false);
|
||||
}
|
||||
|
||||
if (jars != null) {
|
||||
if (jars != null && jars.size() > 0) {
|
||||
for (String jarName : jars) {
|
||||
filter.includeJar(jarName);
|
||||
}
|
||||
|
||||
// if they specified jars to specifically include, they don't want everything included
|
||||
filter.setDefaultJarMatch(false);
|
||||
}
|
||||
|
||||
return filter;
|
||||
|
||||
@@ -8,8 +8,9 @@ import java.util.List;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.CompoundType;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
@@ -22,8 +23,6 @@ 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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Interesting classes for a EbeanServer such as Embeddable, Entity,
|
||||
@@ -33,8 +32,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BootupClasses.class);
|
||||
|
||||
private ArrayList<Class<?>> xmlBeanList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> embeddableList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> entityList = new ArrayList<Class<?>>();
|
||||
@@ -55,8 +52,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
private ArrayList<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> luceneIndexList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
|
||||
private ArrayList<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
|
||||
|
||||
@@ -75,7 +70,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
}
|
||||
|
||||
private BootupClasses(BootupClasses parent) {
|
||||
this.xmlBeanList.addAll(parent.xmlBeanList);
|
||||
this.embeddableList.addAll(parent.embeddableList);
|
||||
this.entityList.addAll(parent.entityList);
|
||||
this.scalarTypeList.addAll(parent.scalarTypeList);
|
||||
@@ -86,7 +80,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
this.beanFinderList.addAll(parent.beanFinderList);
|
||||
this.beanListenerList.addAll(parent.beanListenerList);
|
||||
this.beanQueryAdapterList.addAll(parent.beanQueryAdapterList);
|
||||
this.luceneIndexList.addAll(parent.luceneIndexList);
|
||||
this.serverConfigStartupList.addAll(parent.serverConfigStartupList);
|
||||
}
|
||||
|
||||
@@ -304,13 +297,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
return beanListenerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of XML Beans.
|
||||
*/
|
||||
public ArrayList<Class<?>> getXmlBeanList() {
|
||||
return xmlBeanList;
|
||||
}
|
||||
|
||||
public void add(Iterator<Class<?>> it) {
|
||||
while (it.hasNext()) {
|
||||
Class<?> clazz = it.next();
|
||||
@@ -325,11 +311,7 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
} else if (isEntity(cls)) {
|
||||
entityList.add(cls);
|
||||
|
||||
} else if (isXmlBean(cls)){
|
||||
entityList.add(cls);
|
||||
//xmlBeanList.add(cls);
|
||||
|
||||
|
||||
} else if (isInterestingInterface(cls)) {
|
||||
return true;
|
||||
|
||||
@@ -419,18 +401,4 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isXmlBean(Class<?> cls) {
|
||||
|
||||
Annotation ann = cls.getAnnotation(XmlRootElement.class);
|
||||
if (ann != null) {
|
||||
return true;
|
||||
}
|
||||
ann = cls.getAnnotation(XmlType.class);
|
||||
if (ann != null) {
|
||||
// Only looking for Beans and not Enums
|
||||
return !cls.isEnum();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +90,6 @@ import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.el.ElFilter;
|
||||
import com.avaje.ebeaninternal.server.jmx.MAdminAutofetch;
|
||||
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
|
||||
import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.query.CQuery;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.query.CallableQueryIds;
|
||||
@@ -490,7 +489,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile a query. Only valid for ORM queries (not LDAP)
|
||||
* Compile a query. Only valid for ORM queries.
|
||||
*/
|
||||
public <T> CQuery<T> compileQuery(Query<T> query, Transaction t) {
|
||||
SpiOrmQueryRequest<T> qr = createQueryRequest(Type.SUBQUERY, query, t);
|
||||
@@ -1133,7 +1132,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (Mode.LAZYLOAD_MANY.equals(query.getMode())) {
|
||||
allowOneManyFetch = false;
|
||||
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect() && query.getBackgroundFetchAfter() == 0) {
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect()) {
|
||||
// convert ALL fetch joins to Many's to be query joins
|
||||
// so that limit offset type SQL clauses work
|
||||
allowOneManyFetch = false;
|
||||
@@ -1194,16 +1193,15 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (cachedBean != null) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
|
||||
}
|
||||
context.put(query.getId(), cachedBean);
|
||||
|
||||
DLoadContext loadContext = new DLoadContext(this, beanDescriptor, query.isReadOnly(), query);
|
||||
loadContext.setPersistenceContext(context);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) cachedBean)._ebean_getIntercept();
|
||||
|
||||
// Not using a loadContext for beans coming out of L2 cache
|
||||
// so that means no batch lazy loading for these beans
|
||||
EntityBean entityBean = (EntityBean) cachedBean;
|
||||
EntityBeanIntercept ebi = entityBean._ebean_getIntercept();
|
||||
ebi.setPersistenceContext(context);
|
||||
loadContext.register(null, ebi);
|
||||
Object id = beanDescriptor.getId(entityBean);
|
||||
context.put(id, entityBean);
|
||||
}
|
||||
|
||||
return (T) cachedBean;
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.avaje.ebeaninternal.server.deploy.DeployPropertyParserMap;
|
||||
import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a Query.
|
||||
@@ -43,7 +44,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private final BeanFinder<T> finder;
|
||||
|
||||
private final LoadContext graphContext;
|
||||
private LoadContext graphContext;
|
||||
|
||||
private final Boolean readOnly;
|
||||
|
||||
@@ -75,13 +76,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
this.queryEngine = queryEngine;
|
||||
this.query = query;
|
||||
this.readOnly = query.isReadOnly();
|
||||
|
||||
this.graphContext = new DLoadContext(ebeanServer, beanDescriptor, readOnly, query);
|
||||
graphContext.registerSecondaryQueries(query);
|
||||
}
|
||||
|
||||
public void setTotalHits(int totalHits) {
|
||||
query.setTotalHits(totalHits);
|
||||
}
|
||||
|
||||
public void executeSecondaryQueries(int defaultQueryBatch) {
|
||||
@@ -167,12 +161,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
@Override
|
||||
public void initTransIfRequired() {
|
||||
// first check if the query requires its own transaction
|
||||
if (query.createOwnTransaction()) {
|
||||
// using background fetch or query listener etc
|
||||
transaction = ebeanServer.createQueryTransaction();
|
||||
createdTransaction = true;
|
||||
|
||||
} else if (transaction == null) {
|
||||
if (transaction == null) {
|
||||
// maybe a current one
|
||||
transaction = ebeanServer.getCurrentServerTransaction();
|
||||
if (transaction == null) {
|
||||
@@ -181,8 +170,11 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.persistenceContext = getPersistenceContext(query, transaction);
|
||||
this.graphContext.setPersistenceContext(persistenceContext);
|
||||
|
||||
this.graphContext = new DLoadContext(this);
|
||||
this.graphContext.registerSecondaryQueries(query);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,7 +377,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
|
||||
public void flushPersistenceContextOnIterate() {
|
||||
beanDescriptor.flushPersistenceContextOnIterate(persistenceContext);
|
||||
persistenceContext = new DefaultPersistenceContext();
|
||||
graphContext.setPersistenceContext(persistenceContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.annotation.ConcurrencyMode;
|
||||
@@ -97,7 +96,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
private final ConcurrentHashMap<String, BeanFkeyProperty> fkeyMap = new ConcurrentHashMap<String, BeanFkeyProperty>();
|
||||
|
||||
public enum EntityType {
|
||||
ORM, EMBEDDED, SQL, META, XMLELEMENT
|
||||
ORM, EMBEDDED, SQL
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +105,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
private final String serverName;
|
||||
|
||||
/**
|
||||
* Set to true if this is a LDAP domain object.
|
||||
* The nature/type of this bean.
|
||||
*/
|
||||
private final EntityType entityType;
|
||||
|
||||
@@ -346,12 +345,9 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
private final String defaultSelectClause;
|
||||
private final Set<String> defaultSelectClauseSet;
|
||||
private final String[] defaultSelectDbArray;
|
||||
|
||||
private final String descriptorId;
|
||||
|
||||
private final UseIndex useIndex;
|
||||
|
||||
private SpiEbeanServer ebeanServer;
|
||||
|
||||
private ServerCache beanCache;
|
||||
@@ -372,7 +368,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
this.fullName = InternString.intern(deploy.getFullName());
|
||||
this.descriptorId = descriptorId;
|
||||
|
||||
this.useIndex = deploy.getUseIndex();
|
||||
this.typeManager = typeManager;
|
||||
this.beanType = deploy.getBeanType();
|
||||
this.factoryType = deploy.getFactoryType();
|
||||
@@ -390,7 +385,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
this.defaultSelectClause = deploy.getDefaultSelectClause();
|
||||
this.defaultSelectClauseSet = deploy.parseDefaultSelectClause(defaultSelectClause);
|
||||
this.defaultSelectDbArray = deploy.getDefaultSelectDbArray(defaultSelectClauseSet);
|
||||
|
||||
this.idType = deploy.getIdType();
|
||||
this.idGenerator = deploy.getIdGenerator();
|
||||
@@ -569,14 +563,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default strategy for using a lucene index (if an index is
|
||||
* defined on this bean type).
|
||||
*/
|
||||
public UseIndex getUseIndex() {
|
||||
return useIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the Id properties first.
|
||||
* <p>
|
||||
@@ -808,13 +794,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return defaultSelectClauseSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* For LDAP return array of (DB) attributes to include in query by default.
|
||||
*/
|
||||
public String[] getDefaultSelectDbArray() {
|
||||
return defaultSelectDbArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this object is the root level object in its entity
|
||||
* inheritance.
|
||||
@@ -858,8 +837,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is L2 caching (Lucene or Bean cache) for this bean
|
||||
* type.
|
||||
* Return true if there is L2 bean caching for this bean type.
|
||||
*/
|
||||
public boolean isUsingL2Cache() {
|
||||
return isBeanCaching();
|
||||
@@ -2403,13 +2381,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T createJsonBean() {
|
||||
if (EntityType.XMLELEMENT.equals(entityType)) {
|
||||
try {
|
||||
return beanType.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return (T)createEntityBean();
|
||||
}
|
||||
|
||||
@@ -2473,13 +2444,5 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void flushPersistenceContextOnIterate(PersistenceContext persistenceContext) {
|
||||
persistenceContext.clear(beanType);
|
||||
for (int i = 0; i < propertiesMany.length; i++) {
|
||||
persistenceContext.clear(propertiesMany[i].getBeanDescriptor().getBeanType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -106,9 +106,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
private final BeanManagerFactory beanManagerFactory;
|
||||
|
||||
private int enhancedClassCount;
|
||||
private int subclassClassCount;
|
||||
private final HashSet<String> subclassedEntities = new HashSet<String>();
|
||||
|
||||
|
||||
private final boolean updateChangesOnly;
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
@@ -447,26 +445,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
logger.debug("BeanPersistControllers[" + cc + "] BeanFinders[" + fc + "] BeanPersistListeners[" + lc + "] BeanQueryAdapters[" + qa + "]");
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Warning if mixing subclass and enhancement.
|
||||
* <p>
|
||||
* If enhancement is used for some classes it is expected to be used for all
|
||||
* and vice versa.
|
||||
* </p>
|
||||
*/
|
||||
private void logStatus() {
|
||||
|
||||
String msg = "Entities enhanced[" + enhancedClassCount + "] subclassed[" + subclassClassCount + "]";
|
||||
logger.info(msg);
|
||||
|
||||
if (enhancedClassCount > 0) {
|
||||
if (subclassClassCount > 0) {
|
||||
String subclassEntityNames = subclassedEntities.toString();
|
||||
|
||||
String m = "Mixing enhanced and subclassed entities. Subclassed classes:" + subclassEntityNames;
|
||||
logger.warn(m);
|
||||
}
|
||||
}
|
||||
logger.info("Entities enhanced[" + enhancedClassCount + "]");
|
||||
}
|
||||
|
||||
private <T> BeanDescriptor<T> createEmbedded(Class<T> beanClass) {
|
||||
@@ -1462,25 +1442,13 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
private void checkEnhanced(DeployBeanDescriptor<?> desc, Class<?> beanClass) {
|
||||
// the bean already implements EntityBean
|
||||
checkInheritedClasses(true, beanClass);
|
||||
|
||||
desc.setFactoryType(beanClass);
|
||||
if (!beanClass.getName().startsWith("com.avaje.ebean.meta")) {
|
||||
enhancedClassCount++;
|
||||
}
|
||||
enhancedClassCount++;
|
||||
}
|
||||
|
||||
private void checkSubclass(DeployBeanDescriptor<?> desc, Class<?> beanClass) {
|
||||
|
||||
checkInheritedClasses(false, beanClass);
|
||||
desc.checkReadAndWriteMethods();
|
||||
|
||||
EntityType entityType = desc.getEntityType();
|
||||
if (EntityType.XMLELEMENT.equals(entityType)) {
|
||||
desc.setFactoryType(beanClass);
|
||||
|
||||
} else {
|
||||
throw new PersistenceException("Entity type "+beanClass+" is not an enhanced entity bean. Subclassing is not longer supported in Ebean");
|
||||
}
|
||||
throw new PersistenceException("Entity type "+beanClass+" is not an enhanced entity bean. Subclassing is not longer supported in Ebean");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1049,19 +1049,6 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return value;
|
||||
}
|
||||
|
||||
// private ArrayList<LuceneIndex> luceneIndexes;
|
||||
//
|
||||
// public void registerLuceneIndex(LuceneIndex luceneIndex) {
|
||||
// if (luceneIndexes == null) {
|
||||
// luceneIndexes = new ArrayList<LuceneIndex>();
|
||||
// }
|
||||
// luceneIndexes.add(luceneIndex);
|
||||
// }
|
||||
//
|
||||
// public boolean isDeltaRequired() {
|
||||
// return true;//luceneIndexes != null;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return true if by default this property is set to fetch eager.
|
||||
* Lob's usually default to fetch lazy.
|
||||
|
||||
@@ -6,9 +6,6 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -21,172 +18,156 @@ import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
*/
|
||||
public interface IdBinder {
|
||||
|
||||
/**
|
||||
* Initialise the binder.
|
||||
*/
|
||||
public void initialise();
|
||||
|
||||
/**
|
||||
* Convert the Id value as a Lucene string term.
|
||||
*/
|
||||
public String writeTerm(Object idValue);
|
||||
/**
|
||||
* Initialise the binder.
|
||||
*/
|
||||
public void initialise();
|
||||
|
||||
/**
|
||||
* Convert the Lucene string term into an Id value.
|
||||
*/
|
||||
public Object readTerm(String idTermValue);
|
||||
/**
|
||||
* Write the Id value to binary DataOuput.
|
||||
*/
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException;
|
||||
|
||||
/**
|
||||
* Write the Id value to binary DataOuput.
|
||||
*/
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException;
|
||||
/**
|
||||
* Read the Id value from the binary DataInput.
|
||||
*/
|
||||
public Object readData(DataInput dataInput) throws IOException;
|
||||
|
||||
/**
|
||||
* Read the Id value from the binary DataInput.
|
||||
*/
|
||||
public Object readData(DataInput dataInput) throws IOException;
|
||||
/**
|
||||
* Return the name(s) of the Id property(s). Comma delimited if there is more
|
||||
* than one.
|
||||
* <p>
|
||||
* This can be used to include in a query.
|
||||
* </p>
|
||||
*/
|
||||
public String getIdProperty();
|
||||
|
||||
/**
|
||||
* Adds RDN's to the LdapName using the id value.
|
||||
*/
|
||||
public void createLdapNameById(LdapName name, Object id) throws InvalidNameException;
|
||||
/**
|
||||
* Find a BeanProperty that is mapped to the database column.
|
||||
*/
|
||||
public BeanProperty findBeanProperty(String dbColumnName);
|
||||
|
||||
/**
|
||||
* Adds RDN's to the LdapName using the id value from the bean.
|
||||
*/
|
||||
public void createLdapNameByBean(LdapName name, Object bean) throws InvalidNameException;
|
||||
/**
|
||||
* Return the number of scalar properties for this id.
|
||||
*/
|
||||
public int getPropertyCount();
|
||||
|
||||
/**
|
||||
* Return the name(s) of the Id property(s).
|
||||
* Comma delimited if there is more than one.
|
||||
* <p>
|
||||
* This can be used to include in a query.
|
||||
* </p>
|
||||
*/
|
||||
public String getIdProperty();
|
||||
/**
|
||||
* Return false if the id is a simple scalar and false if it is embedded or
|
||||
* concatenated.
|
||||
*/
|
||||
public boolean isComplexId();
|
||||
|
||||
/**
|
||||
* Find a BeanProperty that is mapped to the database column.
|
||||
*/
|
||||
public BeanProperty findBeanProperty(String dbColumnName);
|
||||
|
||||
/**
|
||||
* Return the number of scalar properties for this id.
|
||||
*/
|
||||
public int getPropertyCount();
|
||||
|
||||
/**
|
||||
* Return false if the id is a simple scalar and false if it is embedded or concatenated.
|
||||
*/
|
||||
public boolean isComplexId();
|
||||
|
||||
/**
|
||||
* Return the default order by that may need to be used if the query includes a many property.
|
||||
*/
|
||||
public String getDefaultOrderBy();
|
||||
|
||||
public String getOrderBy(String pathPrefix, boolean ascending);
|
||||
|
||||
/**
|
||||
* Return the values as an array of scalar bindable values.
|
||||
* <p>
|
||||
* For concatenated keys that use an Embedded bean or multiple id properties
|
||||
* this determines the field values are returns them as an Object array.
|
||||
* </p>
|
||||
* <p>
|
||||
* Added primarily for Query.addWhere().add(Expr.idEq()) support.
|
||||
* </p>
|
||||
*/
|
||||
public Object[] getBindValues(Object idValue);
|
||||
|
||||
/**
|
||||
* Return the id values for a given bean.
|
||||
*/
|
||||
public Object[] getIdValues(Object bean);
|
||||
|
||||
/**
|
||||
* Build a string of the logical expressions.
|
||||
* <p>
|
||||
* Typically used to build a id = ? string.
|
||||
* </p>
|
||||
*/
|
||||
public String getAssocOneIdExpr(String prefix, String operator);
|
||||
|
||||
/**
|
||||
* Return the logical id in expression taking into account embedded id's.
|
||||
*/
|
||||
public String getAssocIdInExpr(String prefix);
|
||||
/**
|
||||
* Return the default order by that may need to be used if the query includes
|
||||
* a many property.
|
||||
*/
|
||||
public String getDefaultOrderBy();
|
||||
|
||||
/**
|
||||
* Binds an id value to a prepared statement.
|
||||
*/
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException;
|
||||
public String getOrderBy(String pathPrefix, boolean ascending);
|
||||
|
||||
/**
|
||||
* Bind the id value to a SqlUpdate statement.
|
||||
*/
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value);
|
||||
|
||||
public void addIdInBindValue(SpiExpressionRequest request, Object value);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id using an IN clause.
|
||||
*/
|
||||
public String getBindIdInSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Return the binding expression (like "?" or "(?,?)")for the Id.
|
||||
*/
|
||||
public String getIdInValueExpr(int size);
|
||||
|
||||
/**
|
||||
* Same as getIdInValueExpr but for delete by id.
|
||||
*/
|
||||
public String getIdInValueExprDelete(int size);
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain);
|
||||
|
||||
/**
|
||||
* Read the id value from the result set and set it to the bean also returning it.
|
||||
*/
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException;
|
||||
/**
|
||||
* Return the values as an array of scalar bindable values.
|
||||
* <p>
|
||||
* For concatenated keys that use an Embedded bean or multiple id properties
|
||||
* this determines the field values are returns them as an Object array.
|
||||
* </p>
|
||||
* <p>
|
||||
* Added primarily for Query.addWhere().add(Expr.idEq()) support.
|
||||
* </p>
|
||||
*/
|
||||
public Object[] getBindValues(Object idValue);
|
||||
|
||||
/**
|
||||
* Ignore the appropriate number of scalar properties for this id.
|
||||
*/
|
||||
public void loadIgnore(DbReadContext ctx);
|
||||
|
||||
/**
|
||||
* Read the id value from the result set and return it.
|
||||
*/
|
||||
public Object read(DbReadContext ctx) throws SQLException;
|
||||
/**
|
||||
* Return the id values for a given bean.
|
||||
*/
|
||||
public Object[] getIdValues(Object bean);
|
||||
|
||||
/**
|
||||
* Append to the select clause.
|
||||
*/
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id to. This includes table alias and columns that make up the id.
|
||||
*/
|
||||
public String getBindIdSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Return the id properties in flat form.
|
||||
*/
|
||||
public BeanProperty[] getProperties();
|
||||
|
||||
/**
|
||||
* Cast or convert the Id value if necessary and optionally set it.
|
||||
* <p>
|
||||
* The Id value is not assumed to be the correct type so it is converted to
|
||||
* the correct type. Typically this is because we could get a Integer, Long
|
||||
* or BigDecimal depending on the JDBC driver and situation.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the bean is not null, then the value is set to the bean.
|
||||
* </p>
|
||||
*/
|
||||
public Object convertSetId(Object idValue, Object bean);
|
||||
/**
|
||||
* Build a string of the logical expressions.
|
||||
* <p>
|
||||
* Typically used to build a id = ? string.
|
||||
* </p>
|
||||
*/
|
||||
public String getAssocOneIdExpr(String prefix, String operator);
|
||||
|
||||
/**
|
||||
* Return the logical id in expression taking into account embedded id's.
|
||||
*/
|
||||
public String getAssocIdInExpr(String prefix);
|
||||
|
||||
/**
|
||||
* Binds an id value to a prepared statement.
|
||||
*/
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException;
|
||||
|
||||
/**
|
||||
* Bind the id value to a SqlUpdate statement.
|
||||
*/
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value);
|
||||
|
||||
public void addIdInBindValue(SpiExpressionRequest request, Object value);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id using an IN clause.
|
||||
*/
|
||||
public String getBindIdInSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Return the binding expression (like "?" or "(?,?)")for the Id.
|
||||
*/
|
||||
public String getIdInValueExpr(int size);
|
||||
|
||||
/**
|
||||
* Same as getIdInValueExpr but for delete by id.
|
||||
*/
|
||||
public String getIdInValueExprDelete(int size);
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain);
|
||||
|
||||
/**
|
||||
* Read the id value from the result set and set it to the bean also returning
|
||||
* it.
|
||||
*/
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* Ignore the appropriate number of scalar properties for this id.
|
||||
*/
|
||||
public void loadIgnore(DbReadContext ctx);
|
||||
|
||||
/**
|
||||
* Read the id value from the result set and return it.
|
||||
*/
|
||||
public Object read(DbReadContext ctx) throws SQLException;
|
||||
|
||||
/**
|
||||
* Append to the select clause.
|
||||
*/
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id to. This includes table alias and columns
|
||||
* that make up the id.
|
||||
*/
|
||||
public String getBindIdSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Return the id properties in flat form.
|
||||
*/
|
||||
public BeanProperty[] getProperties();
|
||||
|
||||
/**
|
||||
* Cast or convert the Id value if necessary and optionally set it.
|
||||
* <p>
|
||||
* The Id value is not assumed to be the correct type so it is converted to
|
||||
* the correct type. Typically this is because we could get a Integer, Long or
|
||||
* BigDecimal depending on the JDBC driver and situation.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the bean is not null, then the value is set to the bean.
|
||||
* </p>
|
||||
*/
|
||||
public Object convertSetId(Object idValue, Object bean);
|
||||
|
||||
}
|
||||
|
||||
@@ -6,11 +6,6 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -99,23 +94,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public void createLdapNameById(LdapName name, Object id) throws InvalidNameException {
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object v = props[i].getValue(id);
|
||||
Rdn rdn = new Rdn(props[i].getDbColumn(), v);
|
||||
name.add(rdn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void createLdapNameByBean(LdapName name, Object bean) throws InvalidNameException {
|
||||
Object id = embIdProperty.getValue(bean);
|
||||
createLdapNameById(name, id);
|
||||
}
|
||||
|
||||
public BeanDescriptor<?> getIdBeanDescriptor() {
|
||||
return idDesc;
|
||||
}
|
||||
@@ -228,42 +206,6 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
return idInValueSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the lucene string term value into embedded id.
|
||||
*/
|
||||
public Object readTerm(String idTermValue) {
|
||||
|
||||
String[] split = idTermValue.split("|");
|
||||
if (split.length != props.length){
|
||||
String msg = "Failed to split ["+idTermValue+"] using | for id.";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
Object embId = idDesc.createBean();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object v = props[i].getScalarType().parse(split[i]);
|
||||
props[i].setValue(embId, v);
|
||||
}
|
||||
return embId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the embedded id as a Lucene string term value.
|
||||
*/
|
||||
public String writeTerm(Object idValue) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object v = props[i].getValue(idValue);
|
||||
String formatValue = props[i].getScalarType().format(v);
|
||||
if (i > 0){
|
||||
sb.append("|");
|
||||
}
|
||||
sb.append(formatValue);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Object[] getIdValues(Object bean) {
|
||||
bean = embIdProperty.getValue(bean);
|
||||
Object[] bindvalues = new Object[props.length];
|
||||
|
||||
@@ -6,9 +6,6 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -21,132 +18,118 @@ import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
*/
|
||||
public final class IdBinderEmpty implements IdBinder {
|
||||
|
||||
private static final String bindIdSql = "";
|
||||
|
||||
private static final BeanProperty[] properties = new BeanProperty[0];
|
||||
|
||||
public IdBinderEmpty() {
|
||||
private static final String bindIdSql = "";
|
||||
|
||||
}
|
||||
public void initialise(){
|
||||
|
||||
}
|
||||
|
||||
public Object readTerm(String idTermValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String writeTerm(Object idValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getOrderBy(String pathPrefix, boolean ascending){
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
}
|
||||
|
||||
public void createLdapNameById(LdapName name, Object id) throws InvalidNameException {
|
||||
}
|
||||
|
||||
public void createLdapNameByBean(LdapName name, Object bean) throws InvalidNameException {
|
||||
}
|
||||
|
||||
public int getPropertyCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getIdProperty() {
|
||||
return null;
|
||||
}
|
||||
private static final BeanProperty[] properties = new BeanProperty[0];
|
||||
|
||||
public BeanProperty findBeanProperty(String dbColumnName) {
|
||||
return null;
|
||||
}
|
||||
public boolean isComplexId(){
|
||||
return true;
|
||||
}
|
||||
public IdBinderEmpty() {
|
||||
|
||||
}
|
||||
|
||||
public String getDefaultOrderBy() {
|
||||
// this should never happen?
|
||||
return "";
|
||||
}
|
||||
|
||||
public BeanProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
public void initialise() {
|
||||
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
return bindIdSql;
|
||||
}
|
||||
|
||||
public String getAssocOneIdExpr(String prefix, String operator){
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addIdInBindValue(SpiExpressionRequest request, Object value) {
|
||||
|
||||
}
|
||||
|
||||
public String getIdInValueExprDelete(int size) {
|
||||
return getIdInValueExpr(size);
|
||||
}
|
||||
|
||||
public String getIdInValueExpr(int size) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object[] getIdValues(Object bean){
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object[] getBindValues(Object idValue){
|
||||
return new Object[]{idValue};
|
||||
}
|
||||
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
|
||||
|
||||
}
|
||||
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
public void loadIgnore(DbReadContext ctx) {
|
||||
}
|
||||
public String getOrderBy(String pathPrefix, boolean ascending) {
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
}
|
||||
|
||||
public int getPropertyCount() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getIdProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public BeanProperty findBeanProperty(String dbColumnName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isComplexId() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getDefaultOrderBy() {
|
||||
// this should never happen?
|
||||
return "";
|
||||
}
|
||||
|
||||
public BeanProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
return bindIdSql;
|
||||
}
|
||||
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addIdInBindValue(SpiExpressionRequest request, Object value) {
|
||||
|
||||
}
|
||||
|
||||
public String getIdInValueExprDelete(int size) {
|
||||
return getIdInValueExpr(size);
|
||||
}
|
||||
|
||||
public String getIdInValueExpr(int size) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object[] getIdValues(Object bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object[] getBindValues(Object idValue) {
|
||||
return new Object[] { idValue };
|
||||
}
|
||||
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
|
||||
|
||||
}
|
||||
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
public void loadIgnore(DbReadContext ctx) {
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
}
|
||||
|
||||
public Object convertSetId(Object idValue, Object bean) {
|
||||
return idValue;
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataOutput) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
}
|
||||
|
||||
public Object convertSetId(Object idValue, Object bean){
|
||||
return idValue;
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataOutput) throws IOException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
@@ -83,24 +80,6 @@ public final class IdBinderMultiple implements IdBinder {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void createLdapNameById(LdapName name, Object id) throws InvalidNameException {
|
||||
|
||||
if (id instanceof Map<?,?> == false){
|
||||
throw new RuntimeException("Expecting a Map for concatinated key");
|
||||
}
|
||||
|
||||
Map<?,?> mapId = (Map<?,?>)id;
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
|
||||
Object v = mapId.get(props[i].getName());
|
||||
if (v == null){
|
||||
throw new RuntimeException("No value in Map for key "+props[i].getName());
|
||||
}
|
||||
|
||||
Rdn rdn = new Rdn(props[i].getDbColumn(), v);
|
||||
name.add(rdn);
|
||||
}
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
|
||||
@@ -109,19 +88,11 @@ public final class IdBinderMultiple implements IdBinder {
|
||||
}
|
||||
}
|
||||
|
||||
public void createLdapNameByBean(LdapName name, Object bean) throws InvalidNameException {
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
|
||||
Object v = props[i].getValue(bean);
|
||||
Rdn rdn = new Rdn(props[i].getDbColumn(), v);
|
||||
name.add(rdn);
|
||||
}
|
||||
}
|
||||
|
||||
public int getPropertyCount() {
|
||||
return props.length;
|
||||
}
|
||||
public int getPropertyCount() {
|
||||
return props.length;
|
||||
}
|
||||
|
||||
public String getIdProperty() {
|
||||
return idProperties;
|
||||
@@ -229,40 +200,6 @@ public final class IdBinderMultiple implements IdBinder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Object readTerm(String idTermValue) {
|
||||
|
||||
String[] split = idTermValue.split("|");
|
||||
if (split.length != props.length){
|
||||
String msg = "Failed to split ["+idTermValue+"] using | for id.";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
Map<String, Object> uidMap = new LinkedHashMap<String, Object>();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object v = props[i].getScalarType().parse(split[i]);
|
||||
uidMap.put(props[i].getName(), v);
|
||||
}
|
||||
return uidMap;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public String writeTerm(Object idValue) {
|
||||
|
||||
Map<String, ?> uidMap = (Map<String, ?>) idValue;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object v = uidMap.get(props[i].getName());
|
||||
String formatValue = props[i].getScalarType().format(v);
|
||||
if (i > 0){
|
||||
sb.append("|");
|
||||
}
|
||||
sb.append(formatValue);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
|
||||
LinkedHashMap<String,Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
@@ -6,10 +6,6 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.naming.InvalidNameException;
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
@@ -48,14 +44,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public Object readTerm(String idTermValue) {
|
||||
return scalarType.parse(idTermValue);
|
||||
}
|
||||
|
||||
public String writeTerm(Object idValue) {
|
||||
return scalarType.format(idValue);
|
||||
}
|
||||
|
||||
public String getOrderBy(String pathPrefix, boolean ascending){
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
@@ -73,16 +61,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
idProperty.buildSelectExpressionChain(prefix, selectChain);
|
||||
}
|
||||
|
||||
public void createLdapNameById(LdapName name, Object id) throws InvalidNameException {
|
||||
Rdn rdn = new Rdn(idProperty.getDbColumn(), id);
|
||||
name.add(rdn);
|
||||
}
|
||||
|
||||
public void createLdapNameByBean(LdapName name, Object bean) throws InvalidNameException {
|
||||
Object id = idProperty.getValue(bean);
|
||||
createLdapNameById(name, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1.
|
||||
|
||||
@@ -13,7 +13,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.annotation.ConcurrencyMode;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.IdGenerator;
|
||||
@@ -22,7 +24,6 @@ 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.meta.MetaAutoFetchStatistic;
|
||||
import com.avaje.ebeaninternal.server.core.CacheOptions;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
|
||||
@@ -34,8 +35,6 @@ import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
@@ -58,8 +57,6 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DeployBeanDescriptor.class);
|
||||
|
||||
private static final String META_BEAN_PREFIX = MetaAutoFetchStatistic.class.getName().substring(0, 20);
|
||||
|
||||
/**
|
||||
* Map of BeanProperty Linked so as to preserve order.
|
||||
*/
|
||||
@@ -151,8 +148,6 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
private BeanFinder<T> beanFinder;
|
||||
|
||||
private UseIndex useIndex;
|
||||
|
||||
/**
|
||||
* The table joins for this bean. Server side only.
|
||||
*/
|
||||
@@ -181,20 +176,6 @@ public class DeployBeanDescriptor<T> {
|
||||
return Modifier.isAbstract(beanType.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default UseIndex strategy.
|
||||
*/
|
||||
public UseIndex getUseIndex() {
|
||||
return useIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default UseIndex strategy.
|
||||
*/
|
||||
public void setUseIndex(UseIndex useIndex) {
|
||||
this.useIndex = useIndex;
|
||||
}
|
||||
|
||||
public boolean isScalaObject() {
|
||||
Class<?>[] interfaces = beanType.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
@@ -247,9 +228,6 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
public boolean checkReadAndWriteMethods() {
|
||||
|
||||
if (isMeta()) {
|
||||
return true;
|
||||
}
|
||||
boolean missingMethods = false;
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
@@ -289,22 +267,11 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
public EntityType getEntityType() {
|
||||
if (entityType == null) {
|
||||
entityType = isMeta() ? EntityType.META : EntityType.ORM;
|
||||
entityType = EntityType.ORM;
|
||||
}
|
||||
return entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a Meta entity bean.
|
||||
* <p>
|
||||
* The Meta entity beans are not based on real tables but get meta information
|
||||
* from memory such as all the entity bean meta data.
|
||||
* </p>
|
||||
*/
|
||||
private boolean isMeta() {
|
||||
return beanType.getName().startsWith(META_BEAN_PREFIX);
|
||||
}
|
||||
|
||||
public void add(DRawSqlMeta rawSqlMeta) {
|
||||
rawSqlMetas.put(rawSqlMeta.getName(), rawSqlMeta);
|
||||
if ("default".equals(rawSqlMeta.getName())) {
|
||||
@@ -788,26 +755,6 @@ public class DeployBeanDescriptor<T> {
|
||||
return selectClause.substring(0, selectClause.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an Array of properties to include in default fetch (for LDAP).
|
||||
*/
|
||||
public String[] getDefaultSelectDbArray(Set<String> defaultSelect) {
|
||||
|
||||
ArrayList<String> list = new ArrayList<String>();
|
||||
for (DeployBeanProperty p : propMap.values()) {
|
||||
if (defaultSelect != null) {
|
||||
if (defaultSelect.contains(p.getName())) {
|
||||
// properties in defaultSelect
|
||||
list.add(p.getDbColumn());
|
||||
}
|
||||
} else if (!p.isTransient() && p.isDbRead()) {
|
||||
// non transient db properties
|
||||
list.add(p.getDbColumn());
|
||||
}
|
||||
}
|
||||
return list.toArray(new String[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the include separating by comma or semicolon.
|
||||
*/
|
||||
|
||||
@@ -6,10 +6,7 @@ import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.EntityConcurrencyMode;
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
@@ -54,18 +51,6 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isXmlElement(Class<?> cls) {
|
||||
XmlRootElement rootElement = cls.getAnnotation(XmlRootElement.class);
|
||||
if (rootElement != null) {
|
||||
return true;
|
||||
}
|
||||
XmlType xmlType = cls.getAnnotation(XmlType.class);
|
||||
if (xmlType != null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void read(Class<?> cls) {
|
||||
|
||||
Entity entity = cls.getAnnotation(Entity.class);
|
||||
@@ -77,9 +62,6 @@ public class AnnotationClass extends AnnotationParser {
|
||||
} else {
|
||||
descriptor.setName(entity.name());
|
||||
}
|
||||
} else if (isXmlElement(cls)) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
descriptor.setEntityType(EntityType.XMLELEMENT);
|
||||
}
|
||||
|
||||
Embeddable embeddable = cls.getAnnotation(Embeddable.class);
|
||||
@@ -152,11 +134,6 @@ public class AnnotationClass extends AnnotationParser {
|
||||
cacheOptions.setNaturalKey(propName);
|
||||
}
|
||||
}
|
||||
|
||||
if (!UseIndex.DEFAULT.equals(cacheStrategy.useIndex())) {
|
||||
// a specific text index strategy has been defined
|
||||
descriptor.setUseIndex(cacheStrategy.useIndex());
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQueries(NamedQueries namedQueries) {
|
||||
|
||||
@@ -14,51 +14,39 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
*/
|
||||
public abstract class AbstractExpression implements SpiExpression {
|
||||
|
||||
private static final long serialVersionUID = 4072786211853856174L;
|
||||
|
||||
protected final String propName;
|
||||
|
||||
protected final FilterExprPath pathPrefix;
|
||||
|
||||
protected AbstractExpression(FilterExprPath pathPrefix, String propName) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
this.propName = propName;
|
||||
}
|
||||
private static final long serialVersionUID = 4072786211853856174L;
|
||||
|
||||
public String getPropertyName() {
|
||||
if (pathPrefix == null){
|
||||
return propName;
|
||||
} else {
|
||||
String path = pathPrefix.getPath();
|
||||
if (path == null || path.length() == 0){
|
||||
return propName;
|
||||
} else {
|
||||
return path+"."+propName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
protected final String propName;
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
if (propertyName != null){
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(propertyName);
|
||||
if (elProp != null) {
|
||||
if (elProp.containsFormulaWithJoin()) {
|
||||
// for findRowCount query select clause
|
||||
manyWhereJoin.addFormulaWithJoin(propertyName);
|
||||
}
|
||||
if (elProp.containsMany()){
|
||||
// for findRowCount we join to a many property
|
||||
protected AbstractExpression(String propName) {
|
||||
this.propName = propName;
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propName;
|
||||
}
|
||||
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
if (propertyName != null) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(propertyName);
|
||||
if (elProp != null) {
|
||||
if (elProp.containsFormulaWithJoin()) {
|
||||
// for findRowCount query select clause
|
||||
manyWhereJoin.addFormulaWithJoin(propertyName);
|
||||
}
|
||||
if (elProp.containsMany()) {
|
||||
// for findRowCount we join to a many property
|
||||
manyWhereJoin.add(elProp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
return request.getBeanDescriptor().getElGetValue(propertyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
|
||||
String propertyName = getPropertyName();
|
||||
return request.getBeanDescriptor().getElGetValue(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
@@ -20,24 +19,12 @@ class AllEqualsExpression implements SpiExpression {
|
||||
|
||||
private final Map<String, Object> propMap;
|
||||
|
||||
private final FilterExprPath pathPrefix;
|
||||
|
||||
AllEqualsExpression(FilterExprPath pathPrefix, Map<String, Object> propMap) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
AllEqualsExpression(Map<String, Object> propMap) {
|
||||
this.propMap = propMap;
|
||||
}
|
||||
|
||||
protected String name(String propName) {
|
||||
if (pathPrefix == null) {
|
||||
return propName;
|
||||
} else {
|
||||
String path = pathPrefix.getPath();
|
||||
if (path == null || path.length() == 0) {
|
||||
return propName;
|
||||
} else {
|
||||
return path + "." + propName;
|
||||
}
|
||||
}
|
||||
return propName;
|
||||
}
|
||||
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
@@ -127,7 +114,7 @@ class AllEqualsExpression implements SpiExpression {
|
||||
|
||||
int hc = 31;
|
||||
for (Object value : propMap.values()) {
|
||||
hc = hc * 31 + Objects.hashCode(value);
|
||||
hc = hc * 31 + (value == null ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
return hc;
|
||||
|
||||
@@ -15,8 +15,8 @@ class BetweenExpression extends AbstractExpression {
|
||||
|
||||
private final Object valueLow;
|
||||
|
||||
BetweenExpression(FilterExprPath pathPrefix, String propertyName, Object valLo, Object valHigh) {
|
||||
super(pathPrefix, propertyName);
|
||||
BetweenExpression(String propertyName, Object valLo, Object valHigh) {
|
||||
super(propertyName);
|
||||
this.valueLow = valLo;
|
||||
this.valueHigh = valHigh;
|
||||
}
|
||||
|
||||
+2
-15
@@ -10,8 +10,6 @@ import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
|
||||
/**
|
||||
* Between expression where a value is between two properties.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
class BetweenPropertyExpression implements SpiExpression {
|
||||
|
||||
@@ -19,29 +17,18 @@ class BetweenPropertyExpression implements SpiExpression {
|
||||
|
||||
private static final String BETWEEN = " between ";
|
||||
|
||||
private final FilterExprPath pathPrefix;
|
||||
private final String lowProperty;
|
||||
private final String highProperty;
|
||||
private final Object value;
|
||||
|
||||
BetweenPropertyExpression(FilterExprPath pathPrefix, String lowProperty, String highProperty, Object value) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
BetweenPropertyExpression(String lowProperty, String highProperty, Object value) {
|
||||
this.lowProperty = lowProperty;
|
||||
this.highProperty = highProperty;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
protected String name(String propName) {
|
||||
if (pathPrefix == null) {
|
||||
return propName;
|
||||
} else {
|
||||
String path = pathPrefix.getPath();
|
||||
if (path == null || path.length() == 0) {
|
||||
return propName;
|
||||
} else {
|
||||
return path + "." + propName;
|
||||
}
|
||||
}
|
||||
return propName;
|
||||
}
|
||||
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@ class CaseInsensitiveEqualExpression extends AbstractExpression {
|
||||
|
||||
private final String value;
|
||||
|
||||
CaseInsensitiveEqualExpression(FilterExprPath pathPrefix, String propertyName, String value) {
|
||||
super(pathPrefix, propertyName);
|
||||
CaseInsensitiveEqualExpression(String propertyName, String value) {
|
||||
super(propertyName);
|
||||
this.value = value.toLowerCase();
|
||||
}
|
||||
|
||||
|
||||
+3
-6
@@ -66,8 +66,6 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
*/
|
||||
private ArrayList<SpiExpression> list;
|
||||
|
||||
private final FilterExprPath pathPrefix;
|
||||
|
||||
/**
|
||||
* Construct the query by example expression.
|
||||
*
|
||||
@@ -78,8 +76,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
* @param likeType
|
||||
* the type of Like wild card used
|
||||
*/
|
||||
public DefaultExampleExpression(FilterExprPath pathPrefix, Object entity, boolean caseInsensitive, LikeType likeType) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
public DefaultExampleExpression(Object entity, boolean caseInsensitive, LikeType likeType) {
|
||||
this.entity = entity;
|
||||
this.caseInsensitive = caseInsensitive;
|
||||
this.likeType = likeType;
|
||||
@@ -217,13 +214,13 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
|
||||
if (beanProperty.isScalar() && value != null) {
|
||||
if (value instanceof String) {
|
||||
list.add(new LikeExpression(pathPrefix, propName, (String) value, caseInsensitive, likeType));
|
||||
list.add(new LikeExpression(propName, (String) value, caseInsensitive, likeType));
|
||||
} else {
|
||||
if (!includeZeros && isZero(value)) {
|
||||
// exclude the zero values typically to weed out
|
||||
// primitive int and long that initialise to 0
|
||||
} else {
|
||||
list.add(new SimpleExpression(pathPrefix, propName, SimpleExpression.Op.EQ, value));
|
||||
list.add(new SimpleExpression(propName, SimpleExpression.Op.EQ, value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-35
@@ -21,19 +21,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
private static final Object[] EMPTY_ARRAY = new Object[] {};
|
||||
|
||||
private final FilterExprPath prefix = null;
|
||||
|
||||
public DefaultExpressionFactory() {
|
||||
//this();//null);
|
||||
}
|
||||
|
||||
// public DefaultExpressionFactory(FilterExprPath prefix) {
|
||||
// this.prefix = prefix;
|
||||
// }
|
||||
|
||||
public ExpressionFactory createExpressionFactory(){//FilterExprPath prefix) {
|
||||
public ExpressionFactory createExpressionFactory(){
|
||||
return this;
|
||||
//return new DefaultExpressionFactory(prefix);
|
||||
}
|
||||
|
||||
public String getLang() {
|
||||
@@ -47,7 +39,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
if (value == null) {
|
||||
return isNull(propertyName);
|
||||
}
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.EQ, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +49,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
if (value == null) {
|
||||
return isNotNull(propertyName);
|
||||
}
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.NOT_EQ, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.NOT_EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +60,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
if (value == null) {
|
||||
return isNull(propertyName);
|
||||
}
|
||||
return new CaseInsensitiveEqualExpression(prefix, propertyName, value);
|
||||
return new CaseInsensitiveEqualExpression(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,7 +68,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression between(String propertyName, Object value1, Object value2) {
|
||||
|
||||
return new BetweenExpression(prefix, propertyName, value1, value2);
|
||||
return new BetweenExpression(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,7 +76,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression betweenProperties(String lowProperty, String highProperty, Object value) {
|
||||
|
||||
return new BetweenPropertyExpression(prefix, lowProperty, highProperty, value);
|
||||
return new BetweenPropertyExpression(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +84,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression gt(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.GT, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.GT, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,7 +93,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression ge(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.GT_EQ, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.GT_EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +101,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression lt(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.LT, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.LT, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +109,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression le(String propertyName, Object value) {
|
||||
|
||||
return new SimpleExpression(prefix, propertyName, SimpleExpression.Op.LT_EQ, value);
|
||||
return new SimpleExpression(propertyName, SimpleExpression.Op.LT_EQ, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +117,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression isNull(String propertyName) {
|
||||
|
||||
return new NullExpression(prefix, propertyName, false);
|
||||
return new NullExpression(propertyName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,14 +125,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
public Expression isNotNull(String propertyName) {
|
||||
|
||||
return new NullExpression(prefix, propertyName, true);
|
||||
return new NullExpression(propertyName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive {@link #exampleLike(Object)}
|
||||
*/
|
||||
public ExampleExpression iexampleLike(Object example) {
|
||||
return new DefaultExampleExpression(prefix, example, true, LikeType.RAW);
|
||||
return new DefaultExampleExpression(example, true, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,14 +140,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* LikeType.RAW (you need to add you own wildcards % and _).
|
||||
*/
|
||||
public ExampleExpression exampleLike(Object example) {
|
||||
return new DefaultExampleExpression(prefix, example, false, LikeType.RAW);
|
||||
return new DefaultExampleExpression(example, false, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
public ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
|
||||
return new DefaultExampleExpression(prefix, example, caseInsensitive, likeType);
|
||||
return new DefaultExampleExpression(example, caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +155,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* characters % (percentage) and _ (underscore).
|
||||
*/
|
||||
public Expression like(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, false, LikeType.RAW);
|
||||
return new LikeExpression(propertyName, value, false, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,14 +164,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* a lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public Expression ilike(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, true, LikeType.RAW);
|
||||
return new LikeExpression(propertyName, value, true, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts With - property like value%.
|
||||
*/
|
||||
public Expression startsWith(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, false, LikeType.STARTS_WITH);
|
||||
return new LikeExpression(propertyName, value, false, LikeType.STARTS_WITH);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,14 +179,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public Expression istartsWith(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, true, LikeType.STARTS_WITH);
|
||||
return new LikeExpression(propertyName, value, true, LikeType.STARTS_WITH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends With - property like %value.
|
||||
*/
|
||||
public Expression endsWith(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, false, LikeType.ENDS_WITH);
|
||||
return new LikeExpression(propertyName, value, false, LikeType.ENDS_WITH);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,14 +194,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public Expression iendsWith(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, true, LikeType.ENDS_WITH);
|
||||
return new LikeExpression(propertyName, value, true, LikeType.ENDS_WITH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - property like %value%.
|
||||
*/
|
||||
public Expression contains(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, false, LikeType.CONTAINS);
|
||||
return new LikeExpression(propertyName, value, false, LikeType.CONTAINS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,28 +209,28 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public Expression icontains(String propertyName, String value) {
|
||||
return new LikeExpression(prefix, propertyName, value, true, LikeType.CONTAINS);
|
||||
return new LikeExpression(propertyName, value, true, LikeType.CONTAINS);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
public Expression in(String propertyName, Object[] values) {
|
||||
return new InExpression(prefix, propertyName, values);
|
||||
return new InExpression(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
public Expression in(String propertyName, Query<?> subQuery) {
|
||||
return new InQueryExpression(prefix, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new InQueryExpression(propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
public Expression in(String propertyName, Collection<?> values) {
|
||||
return new InExpression(prefix, propertyName, values);
|
||||
return new InExpression(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,7 +261,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* a map keyed by property names.
|
||||
*/
|
||||
public Expression allEq(Map<String, Object> propertyMap) {
|
||||
return new AllEqualsExpression(prefix, propertyMap);
|
||||
return new AllEqualsExpression(propertyMap);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,13 +13,13 @@ class InExpression extends AbstractExpression {
|
||||
|
||||
private final Object[] values;
|
||||
|
||||
InExpression(FilterExprPath pathPrefix, String propertyName, Collection<?> coll) {
|
||||
super(pathPrefix, propertyName);
|
||||
InExpression(String propertyName, Collection<?> coll) {
|
||||
super(propertyName);
|
||||
values = coll.toArray(new Object[coll.size()]);
|
||||
}
|
||||
|
||||
InExpression(FilterExprPath pathPrefix, String propertyName, Object[] array) {
|
||||
super(pathPrefix, propertyName);
|
||||
InExpression(String propertyName, Object[] array) {
|
||||
super(propertyName);
|
||||
this.values = array;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ class InQueryExpression extends AbstractExpression {
|
||||
|
||||
private transient CQuery<?> compiledSubQuery;
|
||||
|
||||
public InQueryExpression(FilterExprPath pathPrefix, String propertyName, SpiQuery<?> subQuery) {
|
||||
super(pathPrefix, propertyName);
|
||||
public InQueryExpression(String propertyName, SpiQuery<?> subQuery) {
|
||||
super(propertyName);
|
||||
this.subQuery = subQuery;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -375,18 +374,10 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
return exprList.select(properties);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return exprList.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setFirstRow(int firstRow) {
|
||||
return exprList.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return exprList.setListener(queryListener);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setMapKey(String mapKey) {
|
||||
return exprList.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ class LikeExpression extends AbstractExpression {
|
||||
|
||||
private final LikeType type;
|
||||
|
||||
LikeExpression(FilterExprPath pathPrefix, String propertyName, String value, boolean caseInsensitive, LikeType type) {
|
||||
super(pathPrefix, propertyName);
|
||||
LikeExpression(String propertyName, String value, boolean caseInsensitive, LikeType type) {
|
||||
super(propertyName);
|
||||
this.caseInsensitive = caseInsensitive;
|
||||
this.type = type;
|
||||
this.val = value;
|
||||
|
||||
@@ -43,7 +43,8 @@ final class NotExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder) {
|
||||
queryAutoFetchHash(builder);
|
||||
builder.add(NotExpression.class);
|
||||
exp.queryPlanHash(request, builder);
|
||||
}
|
||||
|
||||
public int queryBindHash() {
|
||||
|
||||
@@ -15,8 +15,8 @@ class NullExpression extends AbstractExpression {
|
||||
|
||||
private final boolean notNull;
|
||||
|
||||
NullExpression(FilterExprPath pathPrefix, String propertyName, boolean notNull) {
|
||||
super(pathPrefix, propertyName);
|
||||
NullExpression(String propertyName, boolean notNull) {
|
||||
super(propertyName);
|
||||
this.notNull = notNull;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ public class SimpleExpression extends AbstractExpression {
|
||||
|
||||
private final Object value;
|
||||
|
||||
public SimpleExpression(FilterExprPath pathPrefix, String propertyName, Op type, Object value) {
|
||||
super(pathPrefix, propertyName);
|
||||
public SimpleExpression(String propertyName, Op type, Object value) {
|
||||
super(propertyName);
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@@ -597,12 +597,35 @@ public class DataSourcePool implements DataSource {
|
||||
*/
|
||||
protected void returnConnection(PooledConnection pooledConnection) {
|
||||
|
||||
if (poolListener != null) {
|
||||
poolListener.onBeforeReturnConnection(pooledConnection);
|
||||
}
|
||||
queue.returnPooledConnection(pooledConnection);
|
||||
// return a normal 'good' connection
|
||||
returnTheConnection(pooledConnection, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is a bad connection and must be removed from the pool's busy list and fully closed.
|
||||
*/
|
||||
protected void returnConnectionForceClose(PooledConnection pooledConnection) {
|
||||
|
||||
returnTheConnection(pooledConnection, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return connection. If forceClose is true then this is a bad connection that
|
||||
* must be removed and closed fully.
|
||||
*/
|
||||
private void returnTheConnection(PooledConnection pooledConnection, boolean forceClose) {
|
||||
|
||||
if (poolListener != null && !forceClose) {
|
||||
poolListener.onBeforeReturnConnection(pooledConnection);
|
||||
}
|
||||
queue.returnPooledConnection(pooledConnection, forceClose);
|
||||
|
||||
if (forceClose) {
|
||||
// Got a bad connection so check the pool
|
||||
checkDataSource();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect statistics of a connection that is fully closing
|
||||
*/
|
||||
|
||||
@@ -508,9 +508,8 @@ public class PooledConnection extends ConnectionDelegator {
|
||||
|
||||
if (hadErrors) {
|
||||
if (!pool.validateConnection(this)) {
|
||||
// the connection is BAD, close it and test the pool
|
||||
closeConnectionFully(false);
|
||||
pool.checkDataSource();
|
||||
// the connection is BAD, remove it, close it and test the pool
|
||||
pool.returnConnectionForceClose(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -535,10 +534,9 @@ public class PooledConnection extends ConnectionDelegator {
|
||||
pool.returnConnection(this);
|
||||
|
||||
} catch (Exception ex) {
|
||||
// the connection is BAD, close it and test the pool
|
||||
// the connection is BAD, remove it, close it and test the pool
|
||||
logger.warn("Error when trying to return connection to pool, closing fully.", ex);
|
||||
closeConnectionFully(false);
|
||||
pool.checkDataSource();
|
||||
pool.returnConnectionForceClose(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ public class PooledConnectionQueue {
|
||||
/**
|
||||
* Return a PooledConnection.
|
||||
*/
|
||||
protected void returnPooledConnection(PooledConnection c) {
|
||||
protected void returnPooledConnection(PooledConnection c, boolean forceClose) {
|
||||
|
||||
final ReentrantLock lock = this.lock;
|
||||
lock.lock();
|
||||
@@ -246,7 +246,7 @@ public class PooledConnectionQueue {
|
||||
if (!busyList.remove(c)) {
|
||||
logger.error("Connection [{}] not found in BusyList? ", c);
|
||||
}
|
||||
if (c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
|
||||
if (forceClose || c.shouldTrimOnReturn(lastResetTime, maxAgeMillis)) {
|
||||
c.closeConnectionFully(false);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -28,8 +28,9 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
super(parent, desc, path, defaultBatchSize, queryProps);
|
||||
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
this.bufferList = queryFetch ? new ArrayList<DLoadBeanContext.LoadBuffer>() : null;
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<DLoadBeanContext.LoadBuffer>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
}
|
||||
|
||||
protected void configureQuery(SpiQuery<?> query, String lazyLoadProperty) {
|
||||
@@ -51,11 +52,11 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
protected void register(EntityBeanIntercept ebi){
|
||||
|
||||
ebi.setBeanLoader(0, currentBuffer, getPersistenceContext());
|
||||
if (currentBuffer.add(ebi)) {
|
||||
// the currentBuffer is full so create another one
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(secondaryBatchSize);
|
||||
}
|
||||
currentBuffer.add(ebi);
|
||||
ebi.setBeanLoader(0, currentBuffer, getPersistenceContext());
|
||||
}
|
||||
|
||||
private LoadBuffer createBuffer(int size) {
|
||||
@@ -98,22 +99,29 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
*/
|
||||
public static class LoadBuffer implements BeanLoader, LoadBeanBuffer {
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadBeanContext context;
|
||||
private final int batchSize;
|
||||
private final List<EntityBeanIntercept> list;
|
||||
|
||||
public LoadBuffer(DLoadBeanContext context, int batchSize) {
|
||||
this.context = context;
|
||||
// set the persistence context as at this moment in
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<EntityBeanIntercept>(batchSize);
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean add(EntityBeanIntercept ebi) {
|
||||
public void add(EntityBeanIntercept ebi) {
|
||||
list.add(ebi);
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +146,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return context.getPersistenceContext();
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,12 +52,14 @@ public class DLoadContext implements LoadContext {
|
||||
private List<OrmQueryProperties> secQuery;
|
||||
|
||||
|
||||
public DLoadContext(SpiEbeanServer ebeanServer, BeanDescriptor<?> rootDescriptor, Boolean readOnly, SpiQuery<?> query) {
|
||||
public DLoadContext(OrmQueryRequest<?> request) {
|
||||
|
||||
this.ebeanServer = ebeanServer;
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
this.ebeanServer = request.getServer();
|
||||
this.defaultBatchSize = ebeanServer.getLazyLoadBatchSize();
|
||||
this.rootDescriptor = rootDescriptor;
|
||||
this.readOnly = readOnly;
|
||||
this.rootDescriptor = request.getBeanDescriptor();
|
||||
SpiQuery<?> query = request.getQuery();
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.excludeBeanCache = Boolean.FALSE.equals(query.isUseBeanCache());
|
||||
this.useAutofetchManager = query.getAutoFetchManager() != null;
|
||||
|
||||
|
||||
@@ -17,70 +17,71 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
public class DLoadManyContext extends DLoadBaseContext implements LoadManyContext {
|
||||
|
||||
|
||||
protected final BeanPropertyAssocMany<?> property;
|
||||
|
||||
|
||||
private List<LoadBuffer> bufferList;
|
||||
|
||||
|
||||
private LoadBuffer currentBuffer;
|
||||
|
||||
public DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property,
|
||||
String path, int defaultBatchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
public DLoadManyContext(DLoadContext parent, BeanPropertyAssocMany<?> property, String path, int defaultBatchSize,
|
||||
OrmQueryProperties queryProps) {
|
||||
|
||||
this.property = property;
|
||||
this.bufferList = new ArrayList<DLoadManyContext.LoadBuffer>();
|
||||
super(parent, property.getBeanDescriptor(), path, defaultBatchSize, queryProps);
|
||||
|
||||
this.property = property;
|
||||
// bufferList only required when using query joins (queryFetch)
|
||||
this.bufferList = (!queryFetch) ? null : new ArrayList<DLoadManyContext.LoadBuffer>();
|
||||
this.currentBuffer = createBuffer(firstBatchSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private LoadBuffer createBuffer(int size) {
|
||||
LoadBuffer buffer = new LoadBuffer(this, size);
|
||||
bufferList.add(buffer);
|
||||
if (bufferList != null) {
|
||||
bufferList.add(buffer);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void configureQuery(SpiQuery<?> query){
|
||||
|
||||
// propagate the readOnly state
|
||||
if (parent.isReadOnly() != null){
|
||||
query.setReadOnly(parent.isReadOnly());
|
||||
}
|
||||
query.setParentNode(objectGraphNode);
|
||||
|
||||
if (queryProps != null){
|
||||
queryProps.configureBeanQuery(query);
|
||||
}
|
||||
|
||||
if (parent.isUseAutofetchManager()){
|
||||
query.setAutofetch(true);
|
||||
}
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return property;
|
||||
}
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
// propagate the readOnly state
|
||||
if (parent.isReadOnly() != null) {
|
||||
query.setReadOnly(parent.isReadOnly());
|
||||
}
|
||||
query.setParentNode(objectGraphNode);
|
||||
|
||||
|
||||
public String getName() {
|
||||
return parent.getEbeanServer().getName();
|
||||
}
|
||||
if (queryProps != null) {
|
||||
queryProps.configureBeanQuery(query);
|
||||
}
|
||||
|
||||
public void register(BeanCollection<?> bc){
|
||||
|
||||
bc.setLoader(0, currentBuffer);
|
||||
if (currentBuffer.add(bc)) {
|
||||
// the currentBuffer is full so create another one
|
||||
if (parent.isUseAutofetchManager()) {
|
||||
query.setAutofetch(true);
|
||||
}
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return property;
|
||||
}
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return parent.getEbeanServer().getName();
|
||||
}
|
||||
|
||||
public void register(BeanCollection<?> bc) {
|
||||
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(secondaryBatchSize);
|
||||
}
|
||||
}
|
||||
currentBuffer.add(bc);
|
||||
bc.setLoader(0, currentBuffer);
|
||||
}
|
||||
|
||||
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all){
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest, int requestedBatchSize, boolean all) {
|
||||
|
||||
if (!queryFetch) {
|
||||
throw new IllegalStateException("Not expecting loadSecondaryQuery() to be called?");
|
||||
@@ -89,33 +90,38 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest.getTransaction(), requestedBatchSize, false, false, false);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest.getTransaction(), requestedBatchSize,
|
||||
false, false, false);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
if (!queryProps.isQueryFetchAll()) {
|
||||
// Stop - only fetch the first batch ... the rest will be lazy loaded
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this is only run once - secondary query is a one shot deal
|
||||
this.bufferList = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffer for batch loading bean collections on a given path.
|
||||
* Supports batch lazy loading and secondary query loading.
|
||||
* A buffer for batch loading bean collections on a given path. Supports batch lazy loading and
|
||||
* secondary query loading.
|
||||
*/
|
||||
public static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
|
||||
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadManyContext context;
|
||||
private final int batchSize;
|
||||
private final List<BeanCollection<?>> list;
|
||||
|
||||
|
||||
public LoadBuffer(DLoadManyContext context, int batchSize) {
|
||||
this.context = context;
|
||||
// set the persistence context as at this moment in
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<BeanCollection<?>>(batchSize);
|
||||
}
|
||||
@@ -123,11 +129,17 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean add(BeanCollection<?> bc) {
|
||||
list.add(bc);
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public void add(BeanCollection<?> bc) {
|
||||
list.add(bc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BeanCollection<?>> getBatch() {
|
||||
return list;
|
||||
@@ -137,22 +149,22 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
return context.property;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getObjectGraphNode() {
|
||||
return context.objectGraphNode;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureQuery(SpiQuery<?> query){
|
||||
public void configureQuery(SpiQuery<?> query) {
|
||||
context.configureQuery(query);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return context.serverName;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return context.desc;
|
||||
@@ -160,9 +172,9 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return context.getPersistenceContext();
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
return context.fullPath;
|
||||
@@ -182,9 +194,10 @@ public class DLoadManyContext extends DLoadBaseContext implements LoadManyContex
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Should reduce the list by checking each beanCollection in the L2 first before executing the query
|
||||
|
||||
|
||||
// Should reduce the list by checking each beanCollection in the L2 first before executing
|
||||
// the query
|
||||
|
||||
LoadManyRequest req = new LoadManyRequest(this, null, batchSize, true, onlyIds, useCache);
|
||||
context.parent.getEbeanServer().loadMany(req);
|
||||
}
|
||||
|
||||
@@ -72,17 +72,11 @@ public final class DefaultPersister implements Persister {
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
// private final boolean defaultUpdateNullProperties;
|
||||
// private final boolean defaultDeleteMissingChildren;
|
||||
|
||||
public DefaultPersister(SpiEbeanServer server, Binder binder, BeanDescriptorManager descMgr, PstmtBatch pstmtBatch) {
|
||||
|
||||
this.server = server;
|
||||
this.beanDescriptorManager = descMgr;
|
||||
this.persistExecute = new DefaultPersistExecute(binder, pstmtBatch);
|
||||
|
||||
// this.defaultUpdateNullProperties = server.isDefaultUpdateNullProperties();
|
||||
// this.defaultDeleteMissingChildren = server.isDefaultDeleteMissingChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -508,7 +502,7 @@ public final class DefaultPersister implements Persister {
|
||||
SqlUpdate sqlDelete = manys[i].deleteByParentId(id, idList);
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
} else {
|
||||
// we need to fetch the Id's to delete (recurse or notify L2 cache/lucene)
|
||||
// we need to fetch the Id's to delete (recurse or notify L2 cache)
|
||||
List<Object> childIds = manys[i].findIdsByParentId(id, idList, t, null);
|
||||
if (!childIds.isEmpty()) {
|
||||
delete(targetDesc, null, childIds, t);
|
||||
@@ -770,7 +764,14 @@ public final class DefaultPersister implements Persister {
|
||||
// increase depth for batching order
|
||||
t.depth(+1);
|
||||
for (Object removedBean : modifyRemovals) {
|
||||
deleteRecurse(removedBean, t);
|
||||
if (removedBean instanceof EntityBean) {
|
||||
EntityBean eb = (EntityBean)removedBean;
|
||||
if (eb._ebean_getIntercept().isLoaded()) {
|
||||
// only delete if the bean was loaded meaning that
|
||||
// it is know to exist in the DB
|
||||
deleteRecurse(removedBean, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
t.depth(-1);
|
||||
}
|
||||
|
||||
+4
@@ -47,12 +47,16 @@ public class FactoryBaseProperties {
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
|
||||
if(DmlMode.WHERE.equals(mode) && !withLobs && !props[i].isDbUpdatable()) {
|
||||
// skip non-updatable column from where clause
|
||||
} else {
|
||||
Bindable item = factoryProperty.create(props[i], mode, withLobs);
|
||||
if (item != null) {
|
||||
list.add(item);
|
||||
} else {
|
||||
// null where readOnly (Secondary tables) or Lob exclusion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -24,7 +23,6 @@ import com.avaje.ebean.bean.NodeUsageListener;
|
||||
import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebeaninternal.api.LoadContext;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery.Mode;
|
||||
@@ -41,7 +39,6 @@ import com.avaje.ebeaninternal.server.deploy.DbReadContext;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.DataReader;
|
||||
|
||||
@@ -135,8 +132,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final QueryListener<T> queryListener;
|
||||
|
||||
private Map<String, String> currentPathMap;
|
||||
|
||||
private String currentPrefix;
|
||||
@@ -189,8 +184,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
*/
|
||||
private final ElPropertyValue manyPropertyEl;
|
||||
|
||||
private final int backgroundFetchAfter;
|
||||
|
||||
private final int maxRowsLimit;
|
||||
|
||||
/**
|
||||
@@ -198,8 +191,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
*/
|
||||
private boolean hasHitBackgroundFetchAfter;
|
||||
|
||||
private final PersistenceContext persistenceContext;
|
||||
|
||||
private DataReader dataReader;
|
||||
|
||||
/**
|
||||
@@ -276,20 +267,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
this.desc = request.getBeanDescriptor();
|
||||
this.predicates = predicates;
|
||||
|
||||
this.queryListener = query.getListener();
|
||||
if (queryListener == null) {
|
||||
// normal, use the one from the transaction
|
||||
this.persistenceContext = request.getPersistenceContext();
|
||||
} else {
|
||||
// 'Row Level Transaction Context'...
|
||||
// local transaction context that will be reset
|
||||
// after each 'master' bean is sent to the listener
|
||||
this.persistenceContext = new DefaultPersistenceContext();
|
||||
}
|
||||
|
||||
this.maxRowsLimit = query.getMaxRows() > 0 ? query.getMaxRows() : GLOBAL_ROW_LIMIT;
|
||||
this.backgroundFetchAfter = query.getBackgroundFetchAfter() > 0 ? query
|
||||
.getBackgroundFetchAfter() : Integer.MAX_VALUE;
|
||||
|
||||
this.help = createHelp(request);
|
||||
this.collection = (BeanCollection<T>) (help != null ? help.createEmpty(false) : null);
|
||||
@@ -386,6 +364,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (forwardOnlyHint) {
|
||||
// Use forward only hints for large resultset processing (Issue 56, MySql specific)
|
||||
pstmt = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
pstmt.setFetchSize(Integer.MIN_VALUE);
|
||||
} else {
|
||||
pstmt = conn.prepareStatement(sql);
|
||||
}
|
||||
@@ -442,7 +421,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
* Return the persistence context.
|
||||
*/
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return persistenceContext;
|
||||
return request.getPersistenceContext();
|
||||
}
|
||||
|
||||
public void setLoadedBean(Object bean, Object id, Object lazyLoadParentId) {
|
||||
@@ -465,7 +444,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
if (lazyLoadParentId != null) {
|
||||
if (!lazyLoadParentId.equals(this.lazyLoadParentId)) {
|
||||
// get the appropriate parent bean from the persistence context
|
||||
this.lazyLoadParentBean = persistenceContext.get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId);
|
||||
this.lazyLoadParentBean = getPersistenceContext().get(lazyLoadManyProperty.getBeanDescriptor().getBeanType(), lazyLoadParentId);
|
||||
this.lazyLoadParentId = lazyLoadParentId;
|
||||
}
|
||||
|
||||
@@ -563,12 +542,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inForeground && loadedBeanCount >= backgroundFetchAfter) {
|
||||
hasHitBackgroundFetchAfter = true;
|
||||
collection.setFinishedFetch(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!manyIncluded) {
|
||||
// simple query... no details...
|
||||
return readRow();
|
||||
@@ -686,13 +659,8 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
|
||||
private void readTheRows(boolean inForeground) throws SQLException {
|
||||
while (hasNextBean(inForeground)) {
|
||||
if (queryListener != null) {
|
||||
queryListener.process(getLoadedBean());
|
||||
|
||||
} else {
|
||||
// add to the list/set/map
|
||||
help.add(collection, getLoadedBean());
|
||||
}
|
||||
// add to the list/set/map
|
||||
help.add(collection, getLoadedBean());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,6 @@ public class CQueryFetchIds {
|
||||
private int rowCount;
|
||||
|
||||
private final int maxRows;
|
||||
private final int bgFetchAfter;
|
||||
|
||||
/**
|
||||
* Create the Sql select based on the request.
|
||||
@@ -86,7 +85,6 @@ public class CQueryFetchIds {
|
||||
this.query = request.getQuery();
|
||||
this.sql = sql;
|
||||
this.maxRows = query.getMaxRows();
|
||||
this.bgFetchAfter = query.getBackgroundFetchAfter();
|
||||
|
||||
query.setGeneratedSql(sql);
|
||||
|
||||
@@ -184,9 +182,6 @@ public class CQueryFetchIds {
|
||||
hasMoreRows = rset.next();
|
||||
break;
|
||||
|
||||
} else if (bgFetchAfter > 0 && rowCount >= bgFetchAfter) {
|
||||
useBackgroundToContinueFetch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.avaje.ebean.OrderBy.Property;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
@@ -31,7 +30,6 @@ import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.bean.ObjectGraphOrigin;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebean.meta.MetaAutoFetchStatistic;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.api.HashQuery;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
@@ -69,8 +67,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* Used to add beans to the PersistanceContext prior to query.
|
||||
*/
|
||||
private transient ArrayList<EntityBean> contextAdditions;
|
||||
|
||||
private transient QueryListener<T> queryListener;
|
||||
|
||||
/**
|
||||
* For lazy loading of ManyToMany we need to add a join to the intersection
|
||||
@@ -90,9 +86,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
* The name of the query.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private UseIndex useIndex;
|
||||
|
||||
|
||||
private Type type;
|
||||
|
||||
private Mode mode = Mode.NORMAL;
|
||||
@@ -145,11 +139,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
private boolean futureFetch;
|
||||
|
||||
private List<Object> partialIds;
|
||||
|
||||
/**
|
||||
* The rows after which the fetch continues in a bg thread.
|
||||
*/
|
||||
private int backgroundFetchAfter;
|
||||
|
||||
private int timeout = -1;
|
||||
|
||||
@@ -317,14 +306,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
public MetaAutoFetchStatistic getMetaAutoFetchStatistic() {
|
||||
if (parentNode != null && server != null){
|
||||
ObjectGraphOrigin origin = parentNode.getOriginQueryPoint();
|
||||
return server.find(MetaAutoFetchStatistic.class, origin.getKey());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the where expressions contains a many property.
|
||||
@@ -448,7 +429,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
copy.additionalWhere = additionalWhere;
|
||||
copy.additionalHaving = additionalHaving;
|
||||
copy.distinct = distinct;
|
||||
copy.backgroundFetchAfter = backgroundFetchAfter;
|
||||
copy.timeout = timeout;
|
||||
copy.mapKey = mapKey;
|
||||
copy.id = id;
|
||||
@@ -493,18 +473,9 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public UseIndex getUseIndex() {
|
||||
return useIndex;
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> setUseIndex(UseIndex useIndex) {
|
||||
this.useIndex = useIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getLoadDescription() {
|
||||
return loadDescription;
|
||||
}
|
||||
public String getLoadDescription() {
|
||||
return loadDescription;
|
||||
}
|
||||
|
||||
public String getLoadMode() {
|
||||
return loadMode;
|
||||
@@ -661,7 +632,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
builder.add((type == null ? 0 : type.ordinal()+1));
|
||||
builder.add(useIndex).add(autoFetchTuned).add(distinct).add(query);
|
||||
builder.add(autoFetchTuned).add(distinct).add(query);
|
||||
builder.add(firstRow).add(maxRows).add(orderBy).add(forUpdate);
|
||||
builder.add(rawWhereClause).add(additionalWhere).add(additionalHaving);
|
||||
builder.add(mapKey);
|
||||
@@ -1036,26 +1007,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the findListener is one has been set.
|
||||
*/
|
||||
public QueryListener<T> getListener() {
|
||||
return queryListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a FindListener. This is designed for large fetches where lots are
|
||||
* rows are to be processed and instead of returning all the rows they are
|
||||
* processed one at a time.
|
||||
* <p>
|
||||
* Note that the returning List Set or Map will be empty.
|
||||
* </p>
|
||||
*/
|
||||
public DefaultOrmQuery<T> setListener(QueryListener<T> queryListener) {
|
||||
this.queryListener = queryListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Class<T> getBeanType() {
|
||||
return beanType;
|
||||
}
|
||||
@@ -1132,15 +1083,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getBackgroundFetchAfter() {
|
||||
return backgroundFetchAfter;
|
||||
}
|
||||
|
||||
public DefaultOrmQuery<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
this.backgroundFetchAfter = backgroundFetchAfter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Object getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -1255,23 +1197,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return whereExpressions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if using background fetching or a queryListener.
|
||||
*/
|
||||
public boolean createOwnTransaction() {
|
||||
if (futureFetch){
|
||||
// the future fetches have already created
|
||||
// their own transaction
|
||||
return false;
|
||||
}
|
||||
if (backgroundFetchAfter > 0 || queryListener != null) {
|
||||
// run in own transaction as we can't know how long
|
||||
// the background fetching will continue etc
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getGeneratedSql() {
|
||||
return generatedSql;
|
||||
}
|
||||
|
||||
+13
-1
@@ -5,6 +5,8 @@ import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebeaninternal.api.Monitor;
|
||||
|
||||
@@ -124,7 +126,7 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
|
||||
private ClassContext getClassContext(Class<?> beanType) {
|
||||
|
||||
String clsName = beanType.getName();
|
||||
String clsName = getBeanBaseType(beanType).getName();
|
||||
ClassContext classMap = typeCache.get(clsName);
|
||||
if (classMap == null) {
|
||||
classMap = new ClassContext();
|
||||
@@ -132,6 +134,16 @@ public final class DefaultPersistenceContext implements PersistenceContext {
|
||||
}
|
||||
return classMap;
|
||||
}
|
||||
|
||||
private Class<?> getBeanBaseType(Class<?> beanType) {
|
||||
Class<?> parent = beanType.getSuperclass();
|
||||
|
||||
while (parent != null && parent.isAnnotationPresent(Entity.class)) {
|
||||
beanType = parent;
|
||||
parent = parent.getSuperclass();
|
||||
}
|
||||
return beanType;
|
||||
}
|
||||
|
||||
private static class ClassContext {
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.avaje.ebeaninternal.server.core.PersistRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
/**
|
||||
* Beans deleted by Id used for updating L2 Cache and Lucene indexes.
|
||||
* Beans deleted by Id used for updating L2 Cache.
|
||||
*/
|
||||
public final class DeleteByIdMap {
|
||||
|
||||
|
||||
@@ -593,12 +593,14 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
}
|
||||
connection.commit();
|
||||
}
|
||||
// these will not throw an exception
|
||||
deactivate();
|
||||
notifyCommit();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RollbackException(e);
|
||||
|
||||
} finally {
|
||||
// these will not throw an exception
|
||||
deactivate();
|
||||
notifyCommit();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -634,12 +636,13 @@ public class JdbcTransaction implements SpiTransaction {
|
||||
try {
|
||||
connection.rollback();
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
|
||||
} finally {
|
||||
// these will not throw an exception
|
||||
deactivate();
|
||||
notifyRollback(cause);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@ import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
/**
|
||||
* Manages transactions.
|
||||
* <p>
|
||||
* Keeps the Cache, Cluster and Lucene indexes in synch when transactions are
|
||||
* committed.
|
||||
* Keeps the Cache and Cluster in synch when transactions are committed.
|
||||
* </p>
|
||||
*/
|
||||
public class TransactionManager {
|
||||
@@ -426,7 +425,7 @@ public class TransactionManager {
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
String m = "NotifyOfCommit failed. Cache/Lucene potentially not notified.";
|
||||
String m = "NotifyOfCommit failed. L2 Cache potentially not notified.";
|
||||
logger.error(m, ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,15 +61,6 @@ public class ScalarTypeUtilDate {
|
||||
public java.util.Date parseDateTime(long systemTimeMillis) {
|
||||
return new java.util.Date(systemTimeMillis);
|
||||
}
|
||||
|
||||
public Object luceneFromIndexValue(Object value) {
|
||||
Long l = (Long)value;
|
||||
return new java.util.Date(l);
|
||||
}
|
||||
|
||||
public Object luceneToIndexValue(Object value) {
|
||||
return ((java.util.Date)value).getTime();
|
||||
}
|
||||
}
|
||||
|
||||
public static class DateType extends ScalarTypeBaseDate<java.util.Date> {
|
||||
|
||||
@@ -10,7 +10,6 @@ import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
@@ -26,10 +25,6 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.GlobalProperties;
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathReader;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchFilter;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchMatcher;
|
||||
import com.avaje.ebeaninternal.server.util.DefaultClassPathReader;
|
||||
|
||||
/**
|
||||
* Can search the class path for classes using a ClassPathSearchMatcher. A
|
||||
@@ -45,8 +40,8 @@ public class ClassPathSearch {
|
||||
|
||||
private ClassLoader classLoader;
|
||||
|
||||
private Object[] classPaths;
|
||||
|
||||
private List<Object> classPath = new ArrayList<Object>();
|
||||
|
||||
private ClassPathSearchFilter filter;
|
||||
|
||||
private ClassPathSearchMatcher matcher;
|
||||
@@ -79,16 +74,27 @@ public class ClassPathSearch {
|
||||
classPathReader = (ClassPathReader) ClassUtil.newInstance(cn, this.getClass());
|
||||
}
|
||||
|
||||
classPaths = classPathReader.readPath(classLoader);
|
||||
Object[] rawClassPaths = classPathReader.readPath(classLoader);
|
||||
|
||||
if (classPaths == null || classPaths.length == 0) {
|
||||
String msg = "ClassPath is EMPTY using ClassPathReader [" + classPathReader + "]";
|
||||
logger.warn(msg);
|
||||
if (rawClassPaths == null || rawClassPaths.length == 0) {
|
||||
logger.warn("ClassPath is EMPTY using ClassPathReader [" + classPathReader + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rawClassPaths.length; i++) {
|
||||
// check for a jarfile with a manifest classpath (e.g. maven surefire)
|
||||
List<URI> classPathFromManifest = getClassPathFromManifest(rawClassPaths[i]);
|
||||
if (classPathFromManifest.isEmpty()) {
|
||||
classPath.add(rawClassPaths[i]);
|
||||
} else {
|
||||
classPath.addAll(classPathFromManifest);
|
||||
}
|
||||
}
|
||||
|
||||
boolean debug = GlobalProperties.getBoolean("ebean.debug.classpath", false);
|
||||
if (debug || logger.isTraceEnabled()) {
|
||||
logger.info("Classpath " + Arrays.toString(classPaths));
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
for (Object entry : classPath) {
|
||||
logger.debug("Classpath Entry: {}",entry);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -133,47 +139,52 @@ public class ClassPathSearch {
|
||||
*/
|
||||
public List<Class<?>> findClasses() throws IOException {
|
||||
|
||||
if (classPaths == null || classPaths.length == 0) {
|
||||
if (classPath.isEmpty()) {
|
||||
// returning an empty list
|
||||
return matchList;
|
||||
}
|
||||
|
||||
for (int i = 0; i < classPaths.length; i++) {
|
||||
int classPathSize = classPath.size();
|
||||
for (int i = 0; i < classPathSize; i++) {
|
||||
|
||||
ClassPathElement element = getClassPathElement(classPaths[i]);
|
||||
ClassPathElement element = getClassPathElement(classPath.get(i));
|
||||
|
||||
if (element.isDirectory()) {
|
||||
scanDirectory(element);
|
||||
|
||||
} else if (element.isJarOrWar()) {
|
||||
// search name including the ! offset if it is there
|
||||
if (filter.isSearchJar(element.getJarNameWithOffset())) {
|
||||
if (classPathSize == 1 || filter.isSearchJar(element.getJarNameWithOffset())) {
|
||||
scanJar(element);
|
||||
}
|
||||
|
||||
} else {
|
||||
String msg = "Error: expected classPath entry [" + element
|
||||
+ "] to be a directory or a .jar file but it is not either of those?";
|
||||
logger.error(msg);
|
||||
logger.error("Error: expected classPath entry [" + element+ "] to be a directory or a .jar file but it is not either of those?");
|
||||
}
|
||||
}
|
||||
|
||||
if (matchList.isEmpty()) {
|
||||
String msg = "No Entities found in ClassPath using ClassPathReader [" + classPathReader + "] Classpath Searched["
|
||||
+ Arrays.toString(classPaths) + "]";
|
||||
logger.warn(msg);
|
||||
logger.warn("No Entities found in ClassPath using ClassPathReader [" + classPathReader + "] Classpath Searched[" + classPath + "]");
|
||||
}
|
||||
|
||||
return matchList;
|
||||
}
|
||||
|
||||
private ClassPathElement getClassPathElement(Object classPathEntry) {
|
||||
private ClassPathElement getClassPathElement(Object classPathEntry) throws MalformedURLException {
|
||||
|
||||
if (!URL.class.isInstance(classPathEntry)) {
|
||||
URL fileUrl = null;
|
||||
|
||||
if (URI.class.isInstance(classPathEntry)) {
|
||||
fileUrl = ((URI)classPathEntry).toURL();
|
||||
|
||||
} else if (!URL.class.isInstance(classPathEntry)) {
|
||||
// assumed to be a file path
|
||||
return new ClassPathElement(classPathEntry.toString());
|
||||
|
||||
} else {
|
||||
fileUrl = (URL) classPathEntry;
|
||||
}
|
||||
URL fileUrl = (URL) classPathEntry;
|
||||
|
||||
if (!fileUrl.getPath().contains("!")) {
|
||||
return new ClassPathElement(new File(fileUrl.getFile()));
|
||||
}
|
||||
@@ -371,6 +382,34 @@ public class ClassPathSearch {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If URL and actually a jarfile with manifest return the derived classpath.
|
||||
*/
|
||||
private static List<URI> getClassPathFromManifest(Object classPathElement) {
|
||||
|
||||
try {
|
||||
if (classPathElement instanceof URL) {
|
||||
File file = new File(((URL)classPathElement).getFile());
|
||||
if (file.isDirectory()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
JarFile jarFile = new JarFile(file);
|
||||
try {
|
||||
return getClassPathFromManifest(file, jarFile.getManifest());
|
||||
} finally {
|
||||
jarFile.close();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
|
||||
} catch (IOException e) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a jarfile with a manifest claspath return that.
|
||||
*/
|
||||
private static List<URI> getClassPathFromManifest(File jarFile, Manifest manifest) {
|
||||
|
||||
if (manifest == null) {
|
||||
|
||||
@@ -11,9 +11,9 @@ public class ClassPathSearchFilter {
|
||||
|
||||
private static final String COM_AVAJE_EBEANINTERNAL_SERVER_BEAN = "com.avaje.ebeaninternal.server.bean";
|
||||
|
||||
private static final String COM_AVAJE_EBEAN_META = "com.avaje.ebean.meta";
|
||||
private static final String COM_AVAJE_EBEAN_META = "com.avaje.ebean.meta";
|
||||
|
||||
private boolean defaultPackageMatch = true;
|
||||
private boolean defaultPackageMatch = true;
|
||||
|
||||
private boolean defaultJarMatch = false;
|
||||
|
||||
@@ -121,7 +121,7 @@ public class ClassPathSearchFilter {
|
||||
* Add a jar to explicitly exclude in the search.
|
||||
*/
|
||||
public void excludeJar(String jarName) {
|
||||
includeJarSet.add(jarName);
|
||||
excludeJarSet.add(jarName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,7 +129,6 @@ public class ClassPathSearchFilter {
|
||||
*/
|
||||
public void includeJar(String jarName) {
|
||||
includeJarSet.add(jarName);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,6 @@ import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -42,7 +41,6 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
protected transient ExpressionFactory expr;
|
||||
|
||||
private final String exprLang;
|
||||
private final String listAndStart;
|
||||
private final String listAndEnd;
|
||||
private final String listAndJoin;
|
||||
@@ -59,20 +57,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
this.list = list;
|
||||
this.query = query;
|
||||
this.expr = expr;
|
||||
this.exprLang = expr.getLang();
|
||||
this.parentExprList = parentExprList;
|
||||
|
||||
if ("ldap".equals(exprLang)) {
|
||||
// Language is LDAP
|
||||
listAndStart = "(&";
|
||||
listAndEnd = ")";
|
||||
listAndJoin = "";
|
||||
|
||||
} else {
|
||||
listAndStart = "";
|
||||
listAndEnd = "";
|
||||
listAndJoin = " and ";
|
||||
}
|
||||
this.listAndStart = "";
|
||||
this.listAndEnd = "";
|
||||
this.listAndJoin = " and ";
|
||||
}
|
||||
|
||||
public SpiExpressionList<?> trimPath(int prefixTrim) {
|
||||
@@ -223,18 +212,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.setMaxRows(maxRows);
|
||||
}
|
||||
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return query.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public Query<T> setMapKey(String mapKey) {
|
||||
return query.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
public Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return query.setListener(queryListener);
|
||||
}
|
||||
|
||||
public Query<T> setUseCache(boolean useCache) {
|
||||
return query.setUseCache(useCache);
|
||||
}
|
||||
|
||||
@@ -27,14 +27,6 @@ public class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
this.deployParser = deployParser;
|
||||
}
|
||||
|
||||
// public DefaultExpressionRequest(SpiOrmQueryRequest<?> queryRequest, LIndex
|
||||
// index) {
|
||||
// this.queryRequest = queryRequest;
|
||||
// this.beanDescriptor = queryRequest.getBeanDescriptor();
|
||||
// this.deployParser = null;
|
||||
// this.luceneIndex = index;
|
||||
// }
|
||||
|
||||
public DefaultExpressionRequest(BeanDescriptor<?> beanDescriptor) {
|
||||
this.beanDescriptor = beanDescriptor;
|
||||
this.queryRequest = null;
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.avaje.ebean.FutureRowCount;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExprPath;
|
||||
|
||||
@@ -128,18 +127,10 @@ public class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
throw new PersistenceException(notAllowedMessage);
|
||||
}
|
||||
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return rootQuery.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
return rootQuery.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
public Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return rootQuery.setListener(queryListener);
|
||||
}
|
||||
|
||||
|
||||
public Query<T> setMapKey(String mapKey) {
|
||||
return rootQuery.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ public class BaseTestCase {
|
||||
|
||||
static {
|
||||
logger.debug("... preStart");
|
||||
if (!AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent","debug=0")) {
|
||||
if (!AgentLoader.loadAgentFromClasspath("avaje-ebeanorm-agent","debug=0;packages=com.avaje.tests.**")) {
|
||||
logger.info("avaje-ebeanorm-agent not found in classpath - not dynamically loaded");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public class ClassPathSearchTests {
|
||||
ClassPathSearchFilter filter = new ClassPathSearchFilter();
|
||||
filter.includePackage("com.avaje.ebeaninternal.server");
|
||||
filter.includeJar("WEB-INF");
|
||||
filter.setDefaultJarMatch(false);
|
||||
|
||||
ClassPathSearch search = new ClassPathSearch(cl, filter, new ClassPathSearchMatcher() {
|
||||
@Override
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.avaje.tests.basic;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import com.avaje.tests.model.basic.ResetBasicData;
|
||||
|
||||
public class TestBackgroundFetchAfter extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testWrtJoin() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
SpiEbeanServer server = (SpiEbeanServer)Ebean.getServer(null);
|
||||
boolean h2Db = "h2".equals(server.getDatabasePlatform().getName());
|
||||
|
||||
// limit not in sql as join to many
|
||||
Query<Order> q = Ebean.find(Order.class)
|
||||
.fetch("details")
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
String sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") == -1);
|
||||
}
|
||||
|
||||
// allows limit use as no join to many
|
||||
q = Ebean.find(Order.class)
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") > -1);
|
||||
}
|
||||
|
||||
// allows limit use as join to one (not many)
|
||||
q = Ebean.find(Order.class)
|
||||
.fetch("customer")
|
||||
.setBackgroundFetchAfter(3)
|
||||
.setMaxRows(10);
|
||||
|
||||
q.findList();
|
||||
sql = q.getGeneratedSql();
|
||||
|
||||
if (h2Db){
|
||||
Assert.assertTrue(sql.indexOf("limit") > -1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.avaje.tests.cascade;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.basic.TSDetail;
|
||||
import com.avaje.tests.model.basic.TSMaster;
|
||||
|
||||
public class TestPrivateOwnedIgnoreTransientOrphan extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test(){
|
||||
|
||||
/** new object **/
|
||||
TSMaster master0 = new TSMaster();
|
||||
|
||||
/** recovered after first save **/
|
||||
TSMaster master1 = null;
|
||||
|
||||
/** recovered after transient child ignored **/
|
||||
TSMaster master2 = null;
|
||||
|
||||
Ebean.save(master0);
|
||||
|
||||
master1 = Ebean.find(master0.getClass(), master0.getId());
|
||||
|
||||
// Add then remove a bean that was never saved (to the DB)
|
||||
master1.getDetails().add(new TSDetail());
|
||||
master1.getDetails().clear();
|
||||
|
||||
try{
|
||||
Ebean.save(master1);
|
||||
} catch (OptimisticLockException exception) {
|
||||
// Occured when the "unsaved" bean was wrongly being deleted
|
||||
Assert.fail("Optimistic lock exception wrongly thrown: " + exception.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
master2 = master1 = Ebean.find(master1.getClass(), master1.getId());
|
||||
|
||||
Assert.assertTrue(master2.getDetails().isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.avaje.tests.model.basic;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
@@ -14,7 +15,7 @@ public class UUTwo {
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
@ManyToOne(cascade=CascadeType.PERSIST)
|
||||
UUOne master;
|
||||
|
||||
public UUID getId() {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.avaje.tests.model.inheritexposedtype;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue( "photo" )
|
||||
public class IXPhoto extends IXResource {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.avaje.tests.model.inheritexposedtype;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
|
||||
public class IXResource {
|
||||
|
||||
@Id
|
||||
UUID id;
|
||||
|
||||
@Column(insertable=false, updatable=false)
|
||||
String dtype;
|
||||
|
||||
String name;
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDtype() {
|
||||
return dtype;
|
||||
}
|
||||
|
||||
public void setDtype(String dtype) {
|
||||
this.dtype = dtype;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.avaje.tests.model.inheritexposedtype.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.inheritexposedtype.IXPhoto;
|
||||
|
||||
public class TestInheritExposeDtype extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
IXPhoto p = new IXPhoto();
|
||||
p.setName("the name");
|
||||
Ebean.save(p);
|
||||
|
||||
// update
|
||||
p.setName("new name");
|
||||
Ebean.save(p);
|
||||
|
||||
// delete
|
||||
Ebean.delete(p);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.avaje.tests.model.inheritmany;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class IMRelated {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne(optional=false)
|
||||
IMRoot owner;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public IMRoot getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(IMRoot owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.avaje.tests.model.inheritmany;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
public class IMRoot {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
@OneToMany(mappedBy="owner")
|
||||
List<IMRelated> related;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<IMRelated> getRelated() {
|
||||
return related;
|
||||
}
|
||||
|
||||
public void setRelated(List<IMRelated> related) {
|
||||
this.related = related;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.tests.model.inheritmany;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("ONE")
|
||||
public class IMRootOne extends IMRoot {
|
||||
|
||||
String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.avaje.tests.model.inheritmany;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("TWO")
|
||||
public class IMRootTwo extends IMRoot {
|
||||
|
||||
String title;
|
||||
|
||||
Date whenTitle;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Date getWhenTitle() {
|
||||
return whenTitle;
|
||||
}
|
||||
|
||||
public void setWhenTitle(Date whenTitle) {
|
||||
this.whenTitle = whenTitle;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import org.junit.Test;
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.Query.UseIndex;
|
||||
import com.avaje.tests.model.basic.Customer;
|
||||
import com.avaje.tests.model.basic.ResetBasicData;
|
||||
|
||||
@@ -21,7 +20,7 @@ public class TestExprNestedDisjunction extends BaseTestCase {
|
||||
|
||||
java.sql.Date onAfter = java.sql.Date.valueOf("2009-08-31");
|
||||
|
||||
Query<Customer> q = Ebean.find(Customer.class).setUseIndex(UseIndex.NO).where().disjunction()
|
||||
Query<Customer> q = Ebean.find(Customer.class).where().disjunction()
|
||||
.conjunction().startsWith("name", "r").eq("anniversary", onAfter).endJunction()
|
||||
.conjunction().eq("status", Customer.Status.ACTIVE).gt("id", 0).endJunction().orderBy()
|
||||
.asc("name");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.tests.query.other;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Expression;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.tests.model.basic.Customer;
|
||||
|
||||
public class TestSubQueryBinding extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
|
||||
Query<Customer> someCustomerIds = server.find(Customer.class).select("id").where().lt("id", 5).query();
|
||||
|
||||
Expression someCustIdsExpression = server.getExpressionFactory().in("id", someCustomerIds);
|
||||
|
||||
Query<Customer> query = server.find(Customer.class).where().like("name", "Rob%").not(someCustIdsExpression).query();
|
||||
|
||||
query.findList();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.avaje.tests.update;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import com.avaje.ebean.text.json.JsonWriteOptions;
|
||||
import com.avaje.tests.model.basic.UUOne;
|
||||
import com.avaje.tests.model.basic.UUTwo;
|
||||
|
||||
public class TestJsonStatelessUpdate extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
UUOne one = new UUOne();
|
||||
one.setName("oneName");
|
||||
|
||||
Ebean.save(one);
|
||||
|
||||
UUTwo two = new UUTwo();
|
||||
two.setMaster(one);
|
||||
two.setName("twoName");
|
||||
|
||||
Ebean.save(two);
|
||||
|
||||
UUTwo twoX = Ebean.find(UUTwo.class, two.getId());
|
||||
|
||||
JsonContext jsonContext = Ebean.createJsonContext();
|
||||
|
||||
JsonWriteOptions writeOptions = JsonWriteOptions.parsePath("(id,name,master(*))");
|
||||
String jsonString = jsonContext.toJsonString(twoX, true, writeOptions);
|
||||
|
||||
System.out.println(jsonString);
|
||||
jsonString = jsonString.replace("twoName", "twoNameModified");
|
||||
jsonString = jsonString.replace("oneName", "oneNameModified");
|
||||
|
||||
|
||||
UUTwo two2 = jsonContext.toBean(UUTwo.class, jsonString);
|
||||
|
||||
Assert.assertEquals(twoX.getId(), two2.getId());
|
||||
Assert.assertEquals("twoNameModified", two2.getName());
|
||||
Assert.assertEquals("oneNameModified", two2.getMaster().getName());
|
||||
|
||||
// The update below cascades to also save "master" and that fails
|
||||
// as it thinks it should INSERT master rather than UPDATE master
|
||||
|
||||
// Ebean.update(two2);
|
||||
|
||||
|
||||
// The following is a workaround, to explicitly update master first
|
||||
// so then Ebean doesn't try to save it when two2 is updated
|
||||
Ebean.beginTransaction();
|
||||
try {
|
||||
UUOne master = two2.getMaster();
|
||||
Ebean.update(master);
|
||||
Ebean.update(two2);
|
||||
|
||||
} finally {
|
||||
Ebean.endTransaction();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.avaje.test.model.inheritmany.test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.tests.model.inheritmany.IMRelated;
|
||||
import com.avaje.tests.model.inheritmany.IMRoot;
|
||||
import com.avaje.tests.model.inheritmany.IMRootOne;
|
||||
import com.avaje.tests.model.inheritmany.IMRootTwo;
|
||||
|
||||
|
||||
public class TestInheritWithMany extends BaseTestCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
Assert.assertNotNull(server);
|
||||
|
||||
SpiEbeanServer spiServer = (SpiEbeanServer)server;
|
||||
BeanDescriptor<IMRoot> beanDescriptor = spiServer.getBeanDescriptor(IMRoot.class);
|
||||
InheritInfo inheritInfo = beanDescriptor.getInheritInfo();
|
||||
Assert.assertNotNull(inheritInfo);
|
||||
|
||||
|
||||
IMRootOne one = new IMRootOne();
|
||||
one.setName("One Name");
|
||||
server.save(one);
|
||||
add(one, "aaa");
|
||||
add(one, "bbb");
|
||||
|
||||
|
||||
|
||||
IMRootTwo two = new IMRootTwo();
|
||||
two.setTitle("Two Title");
|
||||
server.save(two);
|
||||
add(two, "ccc");
|
||||
add(two, "ddd");
|
||||
|
||||
|
||||
List<IMRoot> list = server.find(IMRoot.class).select("id").findList();
|
||||
|
||||
for (IMRoot imRoot : list) {
|
||||
// lazy load the related OneToMany which is related to a non-leaf
|
||||
List<IMRelated> related = imRoot.getRelated();
|
||||
for (IMRelated imRelated : related) {
|
||||
imRelated.getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void add(IMRoot owner, String string) {
|
||||
|
||||
IMRelated relate = new IMRelated();
|
||||
relate.setName(string);
|
||||
relate.setOwner(owner);
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
server.save(relate);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user