mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
95
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e8b3f22de | ||
|
|
55e43ddc36 | ||
|
|
97d75c06a1 | ||
|
|
adcfa939e4 | ||
|
|
8a4d78a3f5 | ||
|
|
04e77d9949 | ||
|
|
76e7b8d199 | ||
|
|
00f85a42f8 | ||
|
|
e649a70509 | ||
|
|
2ec50d2c71 | ||
|
|
eaee3a9c02 | ||
|
|
221272328c | ||
|
|
1677917465 | ||
|
|
bfefdbac41 | ||
|
|
58755a51a9 | ||
|
|
b313809894 | ||
|
|
0f3b1eb812 | ||
|
|
306cc4adf4 | ||
|
|
ed88978173 | ||
|
|
ae266968b4 | ||
|
|
aa86454cc4 | ||
|
|
c99bec4940 | ||
|
|
7426274ef6 | ||
|
|
130b7e3327 | ||
|
|
de201715fc | ||
|
|
241f6f3d6d | ||
|
|
1210aca027 | ||
|
|
e653c34211 | ||
|
|
131750cf85 | ||
|
|
17b16fd5d9 | ||
|
|
1065a84709 | ||
|
|
13791a2e58 | ||
|
|
277703d750 | ||
|
|
637cbc6489 | ||
|
|
5d09ca16d6 | ||
|
|
6ed1f25e22 | ||
|
|
b8ae443074 | ||
|
|
ab9762bbd9 | ||
|
|
2c90b239cd | ||
|
|
13806767a3 | ||
|
|
40e43b9d5f | ||
|
|
29f1e63146 | ||
|
|
5cf008b521 | ||
|
|
3e788d4598 | ||
|
|
8a29454893 | ||
|
|
62c083a6ea | ||
|
|
7f8e4be396 | ||
|
|
2ad39974e8 | ||
|
|
664e95d87b | ||
|
|
5cf668f65b | ||
|
|
31f56621ff | ||
|
|
11a6cd04ea | ||
|
|
fdb573bfe2 | ||
|
|
ae0e1fe691 | ||
|
|
0511e01273 | ||
|
|
f3bd38536c | ||
|
|
139a558165 | ||
|
|
53b40f7ce0 | ||
|
|
e50656871d | ||
|
|
f7ece0f13c | ||
|
|
562c6fafc9 | ||
|
|
63e9f603ec | ||
|
|
0c4fc4eea3 | ||
|
|
2dca1bdf5b | ||
|
|
6403a83e0e | ||
|
|
b57b91ffef | ||
|
|
4ba5702211 | ||
|
|
2e7aeae004 | ||
|
|
3f2676ab49 | ||
|
|
3f29acb25c | ||
|
|
6d1a41f979 | ||
|
|
aee46955a7 | ||
|
|
38a93b9814 | ||
|
|
5f2ad0dc62 | ||
|
|
ece7f481bc | ||
|
|
fa4d0380e5 | ||
|
|
713ba4889d | ||
|
|
0543745e18 | ||
|
|
4e2bc6cce6 | ||
|
|
f2d422ff5a | ||
|
|
176197513d | ||
|
|
1e3035c558 | ||
|
|
17f7143447 | ||
|
|
394dfc96d1 | ||
|
|
452ce78c3d | ||
|
|
4cb13760c2 | ||
|
|
5cc2eff0d4 | ||
|
|
af9a01be77 | ||
|
|
cceb7c035c | ||
|
|
1ddc103582 | ||
|
|
b973cc3b86 | ||
|
|
10f0ea9bae | ||
|
|
c49dd54500 | ||
|
|
bf0944bb2a | ||
|
|
0ceda6406e |
@@ -6,6 +6,7 @@
|
||||
target/
|
||||
logs/
|
||||
log/
|
||||
/db
|
||||
/mydb.db
|
||||
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
[](https://waffle.io/ebean-orm/avaje-ebeanorm)
|
||||
avaje-ebeanorm
|
||||
==============
|
||||
- Release - 4.0.2 - May 19th: https://github.com/ebean-orm/avaje-ebeanorm/wiki/4.0.2-Release
|
||||
- Release - 4.0.3 and 4.0.4 contained some bug fixes plus the Model and Finder objects.
|
||||
|
||||
|
||||
Maven Dependency
|
||||
----------------
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.0.4</version>
|
||||
<version>4.1.8</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.1.1</version>
|
||||
<version>4.2.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -48,6 +48,18 @@
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.4.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
@@ -77,13 +89,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-agentloader</artifactId>
|
||||
@@ -94,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-agent</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<version>4.1.9</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -186,7 +191,7 @@
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<version>4.1.9</version>
|
||||
<executions>
|
||||
<!-- Not going to enhance Model bean -->
|
||||
<execution>
|
||||
@@ -218,7 +223,16 @@
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -1383,10 +1383,18 @@ public final class Ebean {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a JsonContext that will use the default configuration options.
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
*/
|
||||
public static JsonContext json() {
|
||||
return serverMgr.getPrimaryServer().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
public static JsonContext createJsonContext() {
|
||||
return serverMgr.getPrimaryServer().createJsonContext();
|
||||
return json();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -433,7 +433,7 @@ public interface EbeanServer {
|
||||
* @param id
|
||||
* the id value
|
||||
*/
|
||||
public <T> T getReference(Class<T> beanType, Object uid);
|
||||
public <T> T getReference(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Return the number of 'top level' or 'root' entities this query should
|
||||
@@ -489,7 +489,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @param query
|
||||
* the query to execute the row count on
|
||||
* @param t
|
||||
* @param transaction
|
||||
* the transaction (can be null).
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
@@ -505,7 +505,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @param query
|
||||
* the query to execute the fetch Id's on
|
||||
* @param t
|
||||
* @param transaction
|
||||
* the transaction (can be null).
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
@@ -521,7 +521,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @param query
|
||||
* the query to execute in the background
|
||||
* @param t
|
||||
* @param transaction
|
||||
* the transaction (can be null).
|
||||
* @return a Future object for the list result of the query
|
||||
* @deprecated
|
||||
@@ -538,7 +538,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @param query
|
||||
* the query to execute in the background
|
||||
* @param t
|
||||
* @param transaction
|
||||
* the transaction (can be null).
|
||||
* @return a Future object for the list result of the query
|
||||
* @deprecated
|
||||
@@ -1119,9 +1119,14 @@ public interface EbeanServer {
|
||||
public void runCacheWarming(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Create a JsonContext that will use the default configuration options.
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
public JsonContext createJsonContext();
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
*/
|
||||
public JsonContext json();
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import com.avaje.ebean.common.BootupEbeanManager;
|
||||
import com.avaje.ebean.config.GlobalProperties;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.util.ClassUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Creates EbeanServer instances.
|
||||
@@ -26,14 +24,9 @@ import org.slf4j.LoggerFactory;
|
||||
* methods on the Ebean singleton such as {@link Ebean#find(Class)} are just a
|
||||
* convenient way of using the 'default/primary' EbeanServer.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Bygrave
|
||||
*
|
||||
*/
|
||||
public class EbeanServerFactory {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(EbeanServerFactory.class);
|
||||
|
||||
private static BootupEbeanManager serverFactory = createServerFactory();
|
||||
|
||||
/**
|
||||
@@ -69,27 +62,10 @@ public class EbeanServerFactory {
|
||||
|
||||
private static BootupEbeanManager createServerFactory() {
|
||||
|
||||
// String d___ =
|
||||
// com.avaje.ebean.server.core.DefaultServerFactory.class.getName();
|
||||
String dflt = "com.avaje.ebeaninternal.server.core.DefaultServerFactory";
|
||||
String implClassName = GlobalProperties.get("ebean.serverfactory", dflt);
|
||||
String implClassName = System.getProperty("ebean.serverfactory", dflt);
|
||||
|
||||
int delaySecs = GlobalProperties.getInt("ebean.start.delay", 0);
|
||||
if (delaySecs > 0) {
|
||||
try {
|
||||
// perhaps useful to delay the startup to give time to
|
||||
// attach a debugger when running in a server like tomcat.
|
||||
String m = "Ebean sleeping " + delaySecs + " seconds due to ebean.start.delay";
|
||||
logger.info(m);
|
||||
Thread.sleep(delaySecs * 1000);
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
String m = "Interrupting debug.start.delay of " + delaySecs;
|
||||
logger.error(m, e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
// use a client side implementation?
|
||||
return (BootupEbeanManager) ClassUtil.newInstance(implClassName);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -87,6 +89,11 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setOrderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Apply the path properties to the query replacing the select and fetch clauses.
|
||||
*/
|
||||
public Query<T> apply(PathProperties pathProperties);
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
*
|
||||
@@ -242,7 +249,8 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* Specify a property (associated bean) to join and <em>fetch</em> including
|
||||
* all its properties.
|
||||
*
|
||||
* @see Query#join(String)
|
||||
* @see Query#fetch(String)
|
||||
* @deprecated
|
||||
*/
|
||||
public Query<T> join(String assocProperties);
|
||||
|
||||
@@ -250,7 +258,8 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* Specify a property (associated bean) to join and <em>fetch</em> with its
|
||||
* specific properties to include (aka partial object).
|
||||
*
|
||||
* @see Query#join(String,String)
|
||||
* @see Query#fetch(String,String)
|
||||
* @deprecated
|
||||
*/
|
||||
public Query<T> join(String assocProperty, String assocProperties);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -176,11 +178,11 @@ public abstract class Model {
|
||||
* Typically a Finder is defined as a public static field on an entity bean class to provide a
|
||||
* nice way to write queries.
|
||||
*
|
||||
* @param I
|
||||
* @param <I>
|
||||
* The Id type. This is most often a {@link Long} but is also often a {@link UUID} or
|
||||
* {@link String}.
|
||||
*
|
||||
* @param T
|
||||
*
|
||||
* @param <T>
|
||||
* The bean type
|
||||
*/
|
||||
public static class Finder<I, T> {
|
||||
@@ -265,7 +267,7 @@ public abstract class Model {
|
||||
* Retrieves an entity by ID.
|
||||
*
|
||||
* <p>
|
||||
* Equivilent to {@link EbeanServer#find(Class, Object)}
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
*/
|
||||
public T byId(I id) {
|
||||
return db().find(type, id);
|
||||
@@ -275,7 +277,7 @@ public abstract class Model {
|
||||
* Creates an entity reference for this ID.
|
||||
*
|
||||
* <p>
|
||||
* Equivilent to {@link EbeanServer#getReference(Class, Object)}
|
||||
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
|
||||
*/
|
||||
public T ref(I id) {
|
||||
return db().getReference(type, id);
|
||||
@@ -285,7 +287,7 @@ public abstract class Model {
|
||||
* Creates a filter for sorting and filtering lists of entities locally without going back to
|
||||
* the database.
|
||||
* <p>
|
||||
* Equivilent to {@link EbeanServer#filter(Class)}
|
||||
* Equivalent to {@link EbeanServer#filter(Class)}
|
||||
*/
|
||||
public Filter<T> filter() {
|
||||
return db().filter(type);
|
||||
@@ -294,12 +296,19 @@ public abstract class Model {
|
||||
/**
|
||||
* Creates a query.
|
||||
* <p>
|
||||
* Equivilent to {@link EbeanServer#find(Class)}
|
||||
* Equivalent to {@link EbeanServer#find(Class)}
|
||||
*/
|
||||
public Query<T> query() {
|
||||
return db().find(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query applying the path properties to set the select and fetch clauses.
|
||||
*/
|
||||
public Query<T> apply(PathProperties pathProperties) {
|
||||
return db().find(type).apply(pathProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next identity value.
|
||||
*
|
||||
@@ -313,7 +322,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Executes a query and returns the results as a list of IDs.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findIds()}
|
||||
* Equivalent to {@link Query#findIds()}
|
||||
*/
|
||||
public List<Object> findIds() {
|
||||
return query().findIds();
|
||||
@@ -324,7 +333,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* The same as {@link #all()}
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findList()}
|
||||
* Equivalent to {@link Query#findList()}
|
||||
*/
|
||||
public List<T> findList() {
|
||||
return query().findList();
|
||||
@@ -333,7 +342,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Returns all the entities of the given type as a set.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findSet()}
|
||||
* Equivalent to {@link Query#findSet()}
|
||||
*/
|
||||
public Set<T> findSet() {
|
||||
return query().findSet();
|
||||
@@ -342,7 +351,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Retrieves all entities of the given type as a map of objects.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findMap()}
|
||||
* Equivalent to {@link Query#findMap()}
|
||||
*/
|
||||
public Map<?, T> findMap() {
|
||||
return query().findMap();
|
||||
@@ -352,7 +361,7 @@ public abstract class Model {
|
||||
* Executes the query and returns the results as a map of the objects specifying the map key
|
||||
* property.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findMap(String, Class)}
|
||||
* Equivalent to {@link Query#findMap(String, Class)}
|
||||
*/
|
||||
public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType) {
|
||||
return query().findMap(keyProperty, keyType);
|
||||
@@ -362,7 +371,7 @@ public abstract class Model {
|
||||
* Return a PagedList of all entities of the given type (use where() to specify predicates as
|
||||
* needed).
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findPagedList(int, int)}
|
||||
* Equivalent to {@link Query#findPagedList(int, int)}
|
||||
*/
|
||||
public PagedList<T> findPagedList(int pageIndex, int pageSize) {
|
||||
return query().findPagedList(pageIndex, pageSize);
|
||||
@@ -371,7 +380,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Executes a find row count query in a background thread.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findFutureRowCount()}
|
||||
* Equivalent to {@link Query#findFutureRowCount()}
|
||||
*/
|
||||
public FutureRowCount<T> findFutureRowCount() {
|
||||
return query().findFutureRowCount();
|
||||
@@ -380,7 +389,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Returns the total number of entities for this type. *
|
||||
* <p>
|
||||
* Equivilent to {@link Query#findRowCount()}
|
||||
* Equivalent to {@link Query#findRowCount()}
|
||||
*/
|
||||
public int findRowCount() {
|
||||
return query().findRowCount();
|
||||
@@ -397,7 +406,7 @@ public abstract class Model {
|
||||
* Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean,
|
||||
* to load a partial object.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#select(String)}
|
||||
* Equivalent to {@link Query#select(String)}
|
||||
*/
|
||||
public Query<T> select(String fetchProperties) {
|
||||
return query().select(fetchProperties);
|
||||
@@ -406,7 +415,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Specifies a path to load including all its properties.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#fetch(String)}
|
||||
* Equivalent to {@link Query#fetch(String)}
|
||||
*/
|
||||
public Query<T> fetch(String path) {
|
||||
return query().fetch(path);
|
||||
@@ -416,7 +425,7 @@ public abstract class Model {
|
||||
* Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the
|
||||
* lazy loading query.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#fetch(String, FetchConfig)}
|
||||
* Equivalent to {@link Query#fetch(String, FetchConfig)}
|
||||
*/
|
||||
public Query<T> fetch(String path, FetchConfig joinConfig) {
|
||||
return query().fetch(path, joinConfig);
|
||||
@@ -426,7 +435,7 @@ public abstract class Model {
|
||||
* Specifies a path to fetch with a specific list properties to include, to load a partial
|
||||
* object.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#fetch(String, String)}
|
||||
* Equivalent to {@link Query#fetch(String, String)}
|
||||
*/
|
||||
public Query<T> fetch(String path, String fetchProperties) {
|
||||
return query().fetch(path, fetchProperties);
|
||||
@@ -436,7 +445,7 @@ public abstract class Model {
|
||||
* Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to
|
||||
* load this path.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#fetch(String, String, FetchConfig)}
|
||||
* Equivalent to {@link Query#fetch(String, String, FetchConfig)}
|
||||
*/
|
||||
public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) {
|
||||
return query().fetch(assocProperty, fetchProperties, fetchConfig);
|
||||
@@ -446,7 +455,7 @@ public abstract class Model {
|
||||
* Adds expressions to the <code>where</code> clause with the ability to chain on the
|
||||
* <code>ExpressionList</code>.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#where()}
|
||||
* Equivalent to {@link Query#where()}
|
||||
*/
|
||||
public ExpressionList<T> where() {
|
||||
return query().where();
|
||||
@@ -458,7 +467,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* This is exactly the same as {@link #orderBy}.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#order()}
|
||||
* Equivalent to {@link Query#order()}
|
||||
*/
|
||||
public OrderBy<T> order() {
|
||||
return query().order();
|
||||
@@ -480,7 +489,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* This is exactly the same as {@link #order}.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#orderBy()}
|
||||
* Equivalent to {@link Query#orderBy()}
|
||||
*/
|
||||
public OrderBy<T> orderBy() {
|
||||
return query().orderBy();
|
||||
@@ -499,7 +508,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Sets the first row to return for this query.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#setFirstRow(int)}
|
||||
* Equivalent to {@link Query#setFirstRow(int)}
|
||||
*/
|
||||
public Query<T> setFirstRow(int firstRow) {
|
||||
return query().setFirstRow(firstRow);
|
||||
@@ -508,7 +517,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Sets the maximum number of rows to return in the query.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#setMaxRows(int)}
|
||||
* Equivalent to {@link Query#setMaxRows(int)}
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows) {
|
||||
return query().setMaxRows(maxRows);
|
||||
@@ -521,7 +530,7 @@ public abstract class Model {
|
||||
* Use this to perform a find byId query but with additional control over the query such as
|
||||
* using select and fetch to control what parts of the object graph are returned.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#setId(Object)}
|
||||
* Equivalent to {@link Query#setId(Object)}
|
||||
*/
|
||||
public Query<T> setId(Object id) {
|
||||
return query().setId(id);
|
||||
@@ -530,7 +539,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Create and return a new query using the OQL.
|
||||
* <p>
|
||||
* Equivilent to {@link EbeanServer#createQuery(Class, String)}
|
||||
* Equivalent to {@link EbeanServer#createQuery(Class, String)}
|
||||
*/
|
||||
public Query<T> setQuery(String oql) {
|
||||
return db().createQuery(type, oql);
|
||||
@@ -539,7 +548,7 @@ public abstract class Model {
|
||||
/**
|
||||
* Create and return a new query based on the <code>RawSql</code>.
|
||||
* <p>
|
||||
* Equivilent to {@link Query#setRawSql(RawSql)}
|
||||
* Equivalent to {@link Query#setRawSql(RawSql)}
|
||||
*/
|
||||
public Query<T> setRawSql(RawSql rawSql) {
|
||||
return query().setRawSql(rawSql);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -413,6 +415,14 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> fetch(String path, FetchConfig joinConfig);
|
||||
|
||||
/**
|
||||
* Apply the path properties replacing the select and fetch clauses.
|
||||
* <p>
|
||||
* This is typically used when the PathProperties is applied to both the query and the JSON output.
|
||||
* </p>
|
||||
*/
|
||||
public Query<T> apply(PathProperties pathProperties);
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of Id's.
|
||||
* <p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
public class SimpleTextParser {
|
||||
class SimpleTextParser {
|
||||
|
||||
private final String oql;
|
||||
private final char[] chars;
|
||||
@@ -10,9 +10,7 @@ public class SimpleTextParser {
|
||||
private String word;
|
||||
private String lowerWord;
|
||||
|
||||
private int openParenthesisCount;
|
||||
|
||||
public SimpleTextParser(String oql) {
|
||||
SimpleTextParser(String oql) {
|
||||
this.oql = oql;
|
||||
this.chars = oql.toCharArray();
|
||||
this.eof = oql.length();
|
||||
@@ -22,10 +20,6 @@ public class SimpleTextParser {
|
||||
return pos;
|
||||
}
|
||||
|
||||
public String getOql() {
|
||||
return oql;
|
||||
}
|
||||
|
||||
public String getWord() {
|
||||
return word;
|
||||
}
|
||||
@@ -104,7 +98,7 @@ public class SimpleTextParser {
|
||||
private void moveToClose() {
|
||||
|
||||
pos++;
|
||||
openParenthesisCount = 0;
|
||||
int openParenthesisCount = 0;
|
||||
|
||||
for (; pos < eof; pos++) {
|
||||
char c = chars[pos];
|
||||
@@ -143,11 +137,7 @@ public class SimpleTextParser {
|
||||
if (isOperator(c)) {
|
||||
return !isOperator;
|
||||
}
|
||||
if (c == '(') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isOperator;
|
||||
return c == '(' || isOperator;
|
||||
}
|
||||
|
||||
private boolean isOperator(char c) {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* An annotation for declaring an index on a single column.
|
||||
*
|
||||
* @author rvbiljouw
|
||||
*/
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
* Name of the index
|
||||
*
|
||||
* @return index name
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -55,21 +55,6 @@ import com.avaje.ebean.TxType;
|
||||
* Ebean.save(order);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* During development and testing you can set a debug level which will log the
|
||||
* transaction begin, commit and rollback events so that you can easily confirm
|
||||
* it is behaving as you would expect.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* ## in ebean.properties file
|
||||
*
|
||||
* ## Log transaction begins and ends etc
|
||||
* ## (0=NoLogging 1=minimal ... 9=logAll)
|
||||
* ebean.debug.transaction=3
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -39,8 +39,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
private transient PersistenceContext persistenceContext;
|
||||
|
||||
private transient BeanLoader beanLoader;
|
||||
|
||||
private int beanLoaderIndex;
|
||||
|
||||
private String ebeanServerName;
|
||||
|
||||
@@ -200,34 +198,22 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index position for batch loading via BeanLoader.
|
||||
* Set the BeanLoader with PersistenceContext.
|
||||
*/
|
||||
public int getBeanLoaderIndex() {
|
||||
return beanLoaderIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Lazy Loading by ebeanServerName.
|
||||
* <p>
|
||||
* This is for reference beans created by themselves.
|
||||
* </p>
|
||||
*/
|
||||
public void setBeanLoaderByServerName(String ebeanServerName) {
|
||||
this.beanLoaderIndex = 0;
|
||||
this.beanLoader = null;
|
||||
this.ebeanServerName = ebeanServerName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the BeanLoader for general lazy loading.
|
||||
*/
|
||||
public void setBeanLoader(int index, BeanLoader beanLoader, PersistenceContext ctx) {
|
||||
this.beanLoaderIndex = index;
|
||||
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.persistenceContext = ctx;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the BeanLoader.
|
||||
*/
|
||||
public void setBeanLoader(BeanLoader beanLoader) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
}
|
||||
|
||||
public boolean isFullyLoadedBean() {
|
||||
return fullyLoadedBean;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@ public class DataSourceConfig {
|
||||
|
||||
private int isolationLevel = Transaction.READ_COMMITTED;
|
||||
|
||||
private boolean autoCommit;
|
||||
|
||||
private String heartbeatSql;
|
||||
|
||||
private int heartbeatFreqSecs = 30;
|
||||
@@ -131,6 +133,20 @@ public class DataSourceConfig {
|
||||
public void setIsolationLevel(int isolationLevel) {
|
||||
this.isolationLevel = isolationLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return autoCommit setting.
|
||||
*/
|
||||
public boolean isAutoCommit() {
|
||||
return autoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to turn on autoCommit.
|
||||
*/
|
||||
public void setAutoCommit(boolean autoCommit) {
|
||||
this.autoCommit = autoCommit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the minimum number of connections the pool should maintain.
|
||||
@@ -450,6 +466,7 @@ public class DataSourceConfig {
|
||||
String dbUrl = properties.get(prefix + "databaseUrl", null);
|
||||
this.url = properties.get(prefix + "url", dbUrl);
|
||||
|
||||
this.autoCommit = properties.getBoolean(prefix + "autoCommit", false);
|
||||
this.captureStackTrace = properties.getBoolean(prefix + "captureStackTrace", false);
|
||||
this.maxStackTraceSize = properties.getInt(prefix + "maxStackTraceSize", 5);
|
||||
this.leakTimeMinutes = properties.getInt(prefix + "leakTimeMinutes", 30);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A map like structure of properties.
|
||||
@@ -68,9 +67,8 @@ final class PropertyMap implements Serializable {
|
||||
}
|
||||
|
||||
synchronized void putAll(Map<String, String> keyValueMap) {
|
||||
Iterator<Entry<String, String>> it = keyValueMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<String, String> entry = it.next();
|
||||
|
||||
for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Helper used to load the PropertyMap.
|
||||
*/
|
||||
@@ -81,9 +79,7 @@ final class PropertyMapLoader {
|
||||
}
|
||||
|
||||
// put values in initially without any evaluation
|
||||
Iterator<Entry<Object, Object>> it = props.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<Object, Object> entry = it.next();
|
||||
for (Map.Entry<Object, Object> entry : props.entrySet()) {
|
||||
String key = ((String) entry.getKey()).toLowerCase();
|
||||
String val = ((String) entry.getValue());
|
||||
if (val != null) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.avaje.ebean.event.ServerConfigStartup;
|
||||
import com.avaje.ebean.event.TransactionEventListener;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.avaje.ebean.util.ClassUtil;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
|
||||
/**
|
||||
* The configuration used for creating a EbeanServer.
|
||||
@@ -175,6 +176,13 @@ public class ServerConfig {
|
||||
*/
|
||||
private DataSourceConfig dataSourceConfig = new DataSourceConfig();
|
||||
|
||||
/**
|
||||
* Set to true if the DataSource uses autoCommit.
|
||||
* <p>
|
||||
* Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
private boolean autoCommitMode;
|
||||
|
||||
/**
|
||||
* The data source JNDI name if using a JNDI DataSource.
|
||||
*/
|
||||
@@ -234,6 +242,8 @@ public class ServerConfig {
|
||||
|
||||
private boolean collectQueryOrigins;
|
||||
|
||||
private JsonFactory jsonFactory;
|
||||
|
||||
/**
|
||||
* Construct a Server Configuration for programmatically creating an
|
||||
* EbeanServer.
|
||||
@@ -241,6 +251,24 @@ public class ServerConfig {
|
||||
public ServerConfig() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
*/
|
||||
public JsonFactory getJsonFactory() {
|
||||
return jsonFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
*/
|
||||
public void setJsonFactory(JsonFactory jsonFactory) {
|
||||
this.jsonFactory = jsonFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the EbeanServer.
|
||||
@@ -582,6 +610,20 @@ public class ServerConfig {
|
||||
public void setDataSourceJndiName(String dataSourceJndiName) {
|
||||
this.dataSourceJndiName = dataSourceJndiName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on. This indicates to Ebean to use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
public boolean isAutoCommitMode() {
|
||||
return autoCommitMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if autoCommit mode is on and Ebean should use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
public void setAutoCommitMode(boolean autoCommitMode) {
|
||||
this.autoCommitMode = autoCommitMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a value used to represent TRUE in the database.
|
||||
@@ -1281,6 +1323,7 @@ public class ServerConfig {
|
||||
|
||||
loadDataSourceSettings(p);
|
||||
|
||||
autoCommitMode = p.getBoolean("autoCommitMode", false);
|
||||
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", false);
|
||||
namingConvention = createNamingConvention(p);
|
||||
databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform");
|
||||
|
||||
@@ -6,6 +6,7 @@ import javax.sql.DataSource;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -14,40 +15,61 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class DatabasePlatform {
|
||||
|
||||
/** The Constant logger. */
|
||||
private static final Logger logger = LoggerFactory.getLogger(DatabasePlatform.class);
|
||||
|
||||
/** The open quote used by quoted identifiers. */
|
||||
/**
|
||||
* The open quote used by quoted identifiers.
|
||||
*/
|
||||
protected String openQuote = "\"";
|
||||
|
||||
/** The close quote used by quoted identifiers. */
|
||||
/**
|
||||
* The close quote used by quoted identifiers.
|
||||
*/
|
||||
protected String closeQuote = "\"";
|
||||
|
||||
/** For limit/offset, row_number etc limiting of SQL queries. */
|
||||
/**
|
||||
* For limit/offset, row_number etc limiting of SQL queries.
|
||||
*/
|
||||
protected SqlLimiter sqlLimiter = new LimitOffsetSqlLimiter();
|
||||
|
||||
/** Mapping of JDBC to Database types. */
|
||||
/**
|
||||
* Mapping of JDBC to Database types.
|
||||
*/
|
||||
protected DbTypeMap dbTypeMap = new DbTypeMap();
|
||||
|
||||
/** DB specific DDL syntax. */
|
||||
/**
|
||||
* DB specific DDL syntax.
|
||||
*/
|
||||
protected DbDdlSyntax dbDdlSyntax = new DbDdlSyntax();
|
||||
|
||||
/** Defines DB identity/sequence features. */
|
||||
/**
|
||||
* Defines DB identity/sequence features.
|
||||
*/
|
||||
protected DbIdentity dbIdentity = new DbIdentity();
|
||||
|
||||
/** The JDBC type to map booleans to (by default). */
|
||||
/**
|
||||
* The JDBC type to map booleans to (by default).
|
||||
*/
|
||||
protected int booleanDbType = Types.BOOLEAN;
|
||||
|
||||
/** The JDBC type to map Blob to. */
|
||||
/**
|
||||
* The JDBC type to map Blob to.
|
||||
*/
|
||||
protected int blobDbType = Types.BLOB;
|
||||
|
||||
/** The JDBC type to map Clob to. */
|
||||
/**
|
||||
* The JDBC type to map Clob to.
|
||||
*/
|
||||
protected int clobDbType = Types.CLOB;
|
||||
|
||||
/** For Oracle treat empty strings as null. */
|
||||
/**
|
||||
* For Oracle treat empty strings as null.
|
||||
*/
|
||||
protected boolean treatEmptyStringsAsNull;
|
||||
|
||||
/** The name. */
|
||||
/**
|
||||
* The database platform name.
|
||||
*/
|
||||
protected String name = "generic";
|
||||
|
||||
/**
|
||||
@@ -57,6 +79,11 @@ public class DatabasePlatform {
|
||||
*/
|
||||
private static final char BACK_TICK = '`';
|
||||
|
||||
/**
|
||||
* The like clause. Can be overridden to disable default escape character.
|
||||
*/
|
||||
protected String likeClause = "like ?";
|
||||
|
||||
protected DbEncrypt dbEncrypt;
|
||||
|
||||
protected boolean idInExpandedForm;
|
||||
@@ -299,4 +326,13 @@ public class DatabasePlatform {
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the like clause used by this database platform.
|
||||
* <p>
|
||||
* This may include an escape clause to disable a default escape character.
|
||||
*/
|
||||
public String getLikeClause() {
|
||||
return likeClause;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public class DbDdlSyntax {
|
||||
|
||||
private boolean inlinePrimaryKeyConstraint = false;
|
||||
|
||||
private boolean addOneToOneUniqueContraint = false;
|
||||
private boolean addOneToOneUniqueContraint = true;
|
||||
|
||||
private int maxConstraintNameLength = 32;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ public class H2Platform extends DatabasePlatform {
|
||||
super();
|
||||
this.name = "h2";
|
||||
this.dbEncrypt = new H2DbEncrypt();
|
||||
this.likeClause = "like ? escape''";
|
||||
|
||||
// only support getGeneratedKeys with non-batch JDBC
|
||||
// so generally use SEQUENCE instead of IDENTITY for H2
|
||||
|
||||
@@ -20,6 +20,7 @@ public class MySqlPlatform extends DatabasePlatform {
|
||||
public MySqlPlatform() {
|
||||
super();
|
||||
this.name = "mysql";
|
||||
this.likeClause = "like ? escape''";
|
||||
this.selectCountWithAlias = true;
|
||||
this.dbEncrypt = new MySqlDbEncrypt();
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
public PostgresPlatform() {
|
||||
super();
|
||||
this.name = "postgres";
|
||||
this.likeClause = "like ? escape''";
|
||||
|
||||
this.dbDdlSyntax = new PostgresDdlSyntax();
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ class PathPropertiesParser {
|
||||
case '(':
|
||||
return currentWord();
|
||||
default:
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} while (pos < eof);
|
||||
throw new RuntimeException("Hit EOF while reading sectionTitle from " + startPos);
|
||||
@@ -91,6 +94,10 @@ class PathPropertiesParser {
|
||||
}
|
||||
|
||||
} while (pos < eof);
|
||||
if (startPos < pos) {
|
||||
String currentWord = source.substring(startPos, pos);
|
||||
currentPathProps.addProperty(currentWord);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSubpath() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebean.text;
|
||||
|
||||
/**
|
||||
* An exception occured typically in processing CSV, JSON or XML.
|
||||
* An exception occurred typically in processing CSV, JSON or XML.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
/**
|
||||
* Utility that converts between JSON content and simple java Maps/Lists.
|
||||
*/
|
||||
public class EJson {
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json.
|
||||
*/
|
||||
public static String write(Object object) throws IOException {
|
||||
return EJsonWriter.write(object);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json to the writer.
|
||||
*/
|
||||
public static void write(Object object, Writer writer) throws IOException {
|
||||
EJsonWriter.write(object, writer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the nested Map/List as json to the jsonGenerator.
|
||||
*/
|
||||
public static void write(Object object, JsonGenerator jsonGenerator) throws IOException {
|
||||
EJsonWriter.write(object, jsonGenerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(String json) throws IOException {
|
||||
return EJsonReader.parseObject(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map taking a reader.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(Reader reader) throws IOException {
|
||||
return EJsonReader.parseObject(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map taking a JsonParser.
|
||||
*/
|
||||
public static Map<String,Object> parseObject(JsonParser parser) throws IOException {
|
||||
return EJsonReader.parseObject(parser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a Map taking a JsonParser and a starting token.
|
||||
* <p>
|
||||
* Used when the first token is checked to see if the value is null prior to calling this.
|
||||
* </p>
|
||||
*/
|
||||
public static Map<String,Object> parseObject(JsonParser parser, JsonToken token) throws IOException {
|
||||
return EJsonReader.parseObject(parser, token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<Object> parseList(String json) throws IOException {
|
||||
return EJsonReader.parseList(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List taking a Reader.
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<Object> parseList(Reader reader) throws IOException {
|
||||
return EJsonReader.parseList(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List taking a JsonParser.
|
||||
*/
|
||||
public static List<Object> parseList(JsonParser parser) throws IOException {
|
||||
return EJsonReader.parseList(parser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List or Map.
|
||||
*/
|
||||
public static Object parse(String json) throws IOException {
|
||||
return EJsonReader.parse(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List or Map.
|
||||
*/
|
||||
public static Object parse(Reader reader) throws IOException {
|
||||
return EJsonReader.parse(reader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the json and return as a List or Map.
|
||||
*/
|
||||
public static Object parse(JsonParser parser) throws IOException {
|
||||
return EJsonReader.parse(parser);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
class EJsonReader {
|
||||
|
||||
static JsonFactory json = new JsonFactory();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(String json) throws IOException {
|
||||
return (Map<String, Object>) parse(json);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(Reader reader) throws IOException {
|
||||
return (Map<String, Object>) parse(reader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(JsonParser parser) throws IOException {
|
||||
return (Map<String, Object>) parse(parser);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static Map<String, Object> parseObject(JsonParser parser, JsonToken token) throws IOException {
|
||||
return (Map<String, Object>)parse(parser, token);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(String json) throws IOException {
|
||||
return (List<Object>) parse(json);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(Reader reader) throws IOException {
|
||||
return (List<Object>) parse(reader);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static List<Object> parseList(JsonParser parser) throws IOException {
|
||||
return (List<Object>) parse(parser);
|
||||
}
|
||||
|
||||
static Object parse(String json) throws IOException {
|
||||
return parse(new StringReader(json));
|
||||
}
|
||||
|
||||
static Object parse(Reader reader) throws IOException {
|
||||
return parse(json.createParser(reader));
|
||||
}
|
||||
|
||||
static Object parse(JsonParser parser) throws IOException {
|
||||
return parse(parser, null);
|
||||
}
|
||||
|
||||
static Object parse(JsonParser parser, JsonToken token) throws IOException {
|
||||
return new EJsonReader(parser).parseJson(token);
|
||||
}
|
||||
|
||||
private final JsonParser parser;
|
||||
|
||||
private int depth;
|
||||
|
||||
private Stack stack;
|
||||
|
||||
private Context currentContext;
|
||||
|
||||
EJsonReader(JsonParser parser) {
|
||||
this.parser = parser;
|
||||
}
|
||||
|
||||
private void startArray() {
|
||||
depth++;
|
||||
stack.push(currentContext);
|
||||
currentContext = new ArrayContext();
|
||||
}
|
||||
|
||||
private void startObject() {
|
||||
depth++;
|
||||
stack.push(currentContext);
|
||||
currentContext = new ObjectContext();
|
||||
}
|
||||
|
||||
private void endArray() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void endObject() {
|
||||
end();
|
||||
}
|
||||
|
||||
private void end() {
|
||||
depth--;
|
||||
if (!stack.isEmpty()) {
|
||||
currentContext = stack.pop(currentContext);
|
||||
}
|
||||
}
|
||||
|
||||
private void setValue(Object value) {
|
||||
currentContext.setValue(value);
|
||||
}
|
||||
|
||||
private void setValueNull() {
|
||||
currentContext.setValueNull();
|
||||
}
|
||||
|
||||
private Object parseJson(JsonToken token) throws IOException {
|
||||
|
||||
if (token == null) {
|
||||
// no initial token so expect to read START_OBJECT or similar
|
||||
token = parser.nextToken();
|
||||
if (JsonToken.VALUE_NULL == token) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
stack = new Stack();
|
||||
// it is a object or array, process the first JsonToken
|
||||
processJsonToken(token);
|
||||
|
||||
// process the rest of the object or array
|
||||
while (depth > 0) {
|
||||
token = parser.nextToken();
|
||||
processJsonToken(token);
|
||||
}
|
||||
|
||||
return currentContext.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the JsonToken for objects and arrays.
|
||||
*/
|
||||
private void processJsonToken(JsonToken token) throws IOException {
|
||||
switch (token) {
|
||||
|
||||
case START_ARRAY:
|
||||
startArray();
|
||||
break;
|
||||
|
||||
case START_OBJECT:
|
||||
startObject();
|
||||
break;
|
||||
|
||||
case FIELD_NAME:
|
||||
currentContext.setKey(parser.getCurrentName());
|
||||
break;
|
||||
|
||||
case VALUE_STRING:
|
||||
setValue(parser.getValueAsString());
|
||||
break;
|
||||
|
||||
case VALUE_NUMBER_INT:
|
||||
setValue(parser.getLongValue());
|
||||
break;
|
||||
|
||||
case VALUE_NUMBER_FLOAT:
|
||||
setValue(parser.getDecimalValue());
|
||||
break;
|
||||
|
||||
case VALUE_TRUE:
|
||||
setValue(Boolean.TRUE);
|
||||
break;
|
||||
|
||||
case VALUE_FALSE:
|
||||
setValue(Boolean.FALSE);
|
||||
break;
|
||||
|
||||
case VALUE_NULL:
|
||||
setValueNull();
|
||||
break;
|
||||
|
||||
case END_OBJECT:
|
||||
endObject();
|
||||
break;
|
||||
|
||||
case END_ARRAY:
|
||||
endArray();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Stack {
|
||||
|
||||
private Context head;
|
||||
|
||||
private void push(Context context) {
|
||||
if (context != null) {
|
||||
context.next = head;
|
||||
head = context;
|
||||
}
|
||||
}
|
||||
|
||||
private Context pop(Context endingContext) {
|
||||
if (head == null) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
Context temp = head;
|
||||
head = head.next;
|
||||
temp.popContext(endingContext);
|
||||
return temp;
|
||||
}
|
||||
|
||||
private boolean isEmpty() {
|
||||
return head == null;
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class Context {
|
||||
Context next;
|
||||
abstract void popContext(Context temp);
|
||||
abstract Object getValue();
|
||||
abstract void setKey(String key);
|
||||
abstract void setValue(Object value);
|
||||
abstract void setValueNull();
|
||||
}
|
||||
|
||||
private static class ObjectContext extends Context {
|
||||
|
||||
private final Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
private String key;
|
||||
|
||||
public void popContext(Context temp) {
|
||||
setValue(temp.getValue());
|
||||
}
|
||||
|
||||
Object getValue() {
|
||||
return map;
|
||||
}
|
||||
|
||||
void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
map.put(key, null);
|
||||
}
|
||||
}
|
||||
|
||||
private static class ArrayContext extends Context {
|
||||
|
||||
private final List<Object> values = new ArrayList<Object>();
|
||||
|
||||
public void popContext(Context temp) {
|
||||
values.add(temp.getValue());
|
||||
}
|
||||
|
||||
Object getValue() {
|
||||
return values;
|
||||
}
|
||||
|
||||
void setValue(Object value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
void setValueNull() {
|
||||
// ignore
|
||||
}
|
||||
void setKey(String key) {
|
||||
// not expected
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
|
||||
class EJsonWriter {
|
||||
|
||||
/**
|
||||
* Base jsonFactory implementation used when it is not passed in.
|
||||
*/
|
||||
static JsonFactory jsonFactory = new JsonFactory();
|
||||
|
||||
static String write(Object object) throws IOException {
|
||||
StringWriter writer = new StringWriter(200);
|
||||
write(object, writer);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
static void write(Object object, Writer writer) throws IOException {
|
||||
JsonGenerator generator = jsonFactory.createGenerator(writer);
|
||||
write(object, generator);
|
||||
generator.close();
|
||||
}
|
||||
|
||||
static void write(Object object, JsonGenerator jsonGenerator) {
|
||||
new EJsonWriter(jsonGenerator).writeJson(object);
|
||||
}
|
||||
|
||||
private final JsonGenerator jsonGenerator;
|
||||
|
||||
private EJsonWriter(JsonGenerator jsonGenerator) {
|
||||
this.jsonGenerator = jsonGenerator;
|
||||
}
|
||||
|
||||
private void writeJson(Object object) {
|
||||
writeJson(null, object);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void writeJson(String name, Object object) {
|
||||
try {
|
||||
if (object == null) {
|
||||
writeNull(name);
|
||||
|
||||
} else if (object instanceof Map) {
|
||||
writeMap(name, (Map<Object, Object>) object);
|
||||
|
||||
} else if (object instanceof Collection) {
|
||||
writeCollection(name, (Collection<Object>) object);
|
||||
|
||||
} else if (object instanceof Boolean) {
|
||||
writeBoolean(name, (Boolean) object);
|
||||
|
||||
} else if (object instanceof Number) {
|
||||
writeNumber(name, (Number) object);
|
||||
|
||||
} else if (object instanceof Date) {
|
||||
writeDate(name, (Date) object);
|
||||
|
||||
} else if (object instanceof String) {
|
||||
writeString(name, (String) object);
|
||||
|
||||
} else if (object instanceof Map.Entry<?, ?>) {
|
||||
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) object;
|
||||
writeJson(entry.getKey().toString(), entry.getValue());
|
||||
|
||||
} else {
|
||||
writeString(name, object.toString());
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBoolean(String name, Boolean object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeBoolean(object);
|
||||
} else {
|
||||
jsonGenerator.writeBooleanField(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDate(String name, Date object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber(object.getTime());
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, object.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNumber(String name, Number object) throws IOException {
|
||||
|
||||
if (object instanceof Long) {
|
||||
writeLong(name, object);
|
||||
|
||||
} else if (object instanceof Integer) {
|
||||
writeInteger(name, object);
|
||||
|
||||
} else if (object instanceof Double) {
|
||||
writeDouble(name, object);
|
||||
|
||||
} else if (object instanceof BigDecimal) {
|
||||
writeBigDecimal(name, object);
|
||||
|
||||
} else if (object instanceof BigInteger) {
|
||||
writeBigInteger(name, object);
|
||||
|
||||
} else {
|
||||
writeGeneralNumber(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeGeneralNumber(String name, Number object) throws IOException {
|
||||
writeBigDecimal(name, new BigDecimal(object.toString()));
|
||||
}
|
||||
|
||||
private void writeBigDecimal(String name, Number object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber((BigDecimal) object);
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, (BigDecimal) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeBigInteger(String name, Number object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber((BigInteger) object);
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, object.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDouble(String name, Number object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber((Double) object);
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, (Double) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeLong(String name, Number object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber((Long) object);
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, (Long) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeInteger(String name, Number object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNumber((Integer) object);
|
||||
} else {
|
||||
jsonGenerator.writeNumberField(name, (Integer) object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeNull(String name) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeNull();
|
||||
} else {
|
||||
jsonGenerator.writeNullField(name);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeString(String name, String object) throws IOException {
|
||||
if (name == null) {
|
||||
jsonGenerator.writeString(object);
|
||||
} else {
|
||||
jsonGenerator.writeStringField(name, object);
|
||||
}
|
||||
}
|
||||
|
||||
private void writeCollection(String name, Collection<Object> collection) throws IOException {
|
||||
if (name != null) {
|
||||
jsonGenerator.writeFieldName(name);
|
||||
}
|
||||
jsonGenerator.writeStartArray();
|
||||
for (Object object : collection) {
|
||||
writeJson(null, object);
|
||||
}
|
||||
jsonGenerator.writeEndArray();
|
||||
}
|
||||
|
||||
private void writeMap(String name, Map<Object, Object> map) throws IOException {
|
||||
|
||||
if (name != null) {
|
||||
jsonGenerator.writeFieldName(name);
|
||||
}
|
||||
jsonGenerator.writeStartObject();
|
||||
Set<Entry<Object, Object>> entrySet = map.entrySet();
|
||||
for (Entry<Object, Object> entry : entrySet) {
|
||||
writeJson(entry.getKey().toString(), entry.getValue());
|
||||
}
|
||||
jsonGenerator.writeEndObject();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,131 +1,99 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
/**
|
||||
* Converts objects to and from JSON format.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface JsonContext {
|
||||
|
||||
/**
|
||||
* Convert json string input into a Bean of a specific type.
|
||||
*/
|
||||
public <T> T toBean(Class<T> rootType, String json);
|
||||
public <T> T toBean(Class<T> rootType, String json) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert json reader input into a Bean of a specific type.
|
||||
*/
|
||||
public <T> T toBean(Class<T> rootType, Reader json);
|
||||
|
||||
/**
|
||||
* Convert json string input into a Bean of a specific type with options.
|
||||
*/
|
||||
public <T> T toBean(Class<T> rootType, String json, JsonReadOptions options);
|
||||
|
||||
/**
|
||||
* Convert json reader input into a Bean of a specific type with options.
|
||||
*/
|
||||
public <T> T toBean(Class<T> rootType, Reader json, JsonReadOptions options);
|
||||
public <T> T toBean(Class<T> rootType, Reader json) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert json string input into a list of beans of a specific type.
|
||||
*/
|
||||
public <T> List<T> toList(Class<T> rootType, String json);
|
||||
|
||||
/**
|
||||
* Convert json string input into a list of beans of a specific type with
|
||||
* options.
|
||||
*/
|
||||
public <T> List<T> toList(Class<T> rootType, String json, JsonReadOptions options);
|
||||
public <T> List<T> toList(Class<T> rootType, String json) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert json reader input into a list of beans of a specific type.
|
||||
* @throws IOException
|
||||
*/
|
||||
public <T> List<T> toList(Class<T> rootType, Reader json);
|
||||
|
||||
/**
|
||||
* Convert json reader input into a list of beans of a specific type with
|
||||
* options.
|
||||
*/
|
||||
public <T> List<T> toList(Class<T> rootType, Reader json, JsonReadOptions options);
|
||||
public <T> List<T> toList(Class<T> rootType, Reader json) throws IOException;
|
||||
|
||||
/**
|
||||
* Use the genericType to determine if this should be converted into a List or
|
||||
* bean.
|
||||
*/
|
||||
public Object toObject(Type genericType, Reader json, JsonReadOptions options);
|
||||
public Object toObject(Type genericType, Reader json) throws IOException;
|
||||
|
||||
/**
|
||||
* Use the genericType to determine if this should be converted into a List or
|
||||
* bean.
|
||||
*/
|
||||
public Object toObject(Type genericType, String json, JsonReadOptions options);
|
||||
public Object toObject(Type genericType, String json) throws IOException;
|
||||
|
||||
/**
|
||||
* Write the bean or collection in JSON format to the writer with default
|
||||
* options.
|
||||
*
|
||||
* @param o
|
||||
* @param value
|
||||
* the bean or collection of beans to write
|
||||
* @param writer
|
||||
* used to write the json output to
|
||||
*/
|
||||
public void toJsonWriter(Object o, Writer writer);
|
||||
|
||||
/**
|
||||
* With additional pretty output option.
|
||||
*/
|
||||
public void toJsonWriter(Object o, Writer writer, boolean pretty);
|
||||
public void toJson(Object value, Writer writer) throws IOException;
|
||||
|
||||
/**
|
||||
* With additional options to specify JsonValueAdapter and
|
||||
* JsonWriteBeanVisitor's.
|
||||
*
|
||||
* @param o
|
||||
* @param value
|
||||
* the bean or collection of beans to write
|
||||
* @param writer
|
||||
* used to write the json output to
|
||||
* @param options
|
||||
* additional options to control the JSON output
|
||||
*/
|
||||
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options);
|
||||
|
||||
/**
|
||||
* With additional JSONP callback function.
|
||||
*/
|
||||
public void toJsonWriter(Object o, Writer writer, boolean pretty, JsonWriteOptions options,
|
||||
String callback);
|
||||
public void toJson(Object value, Writer writer, JsonWriteOptions options) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert a bean or collection to json string using default options.
|
||||
*/
|
||||
public String toJsonString(Object o);
|
||||
public String toJson(Object value) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert a bean or collection to json string with pretty format using
|
||||
* default options.
|
||||
* Convert a bean or collection to json string.
|
||||
*/
|
||||
public String toJsonString(Object o, boolean pretty);
|
||||
public String toJson(Object value, JsonWriteOptions options) throws IOException;
|
||||
|
||||
/**
|
||||
* Convert a bean or collection to json string using options.
|
||||
*/
|
||||
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options);
|
||||
|
||||
/**
|
||||
* Convert a bean or collection to json string using a JSONP callback.
|
||||
*/
|
||||
public String toJsonString(Object o, boolean pretty, JsonWriteOptions options, String callback);
|
||||
|
||||
/**
|
||||
* Return true if the type is known as an Entity or Xml type or a List Set or
|
||||
* Map of known bean types.
|
||||
* Return true if the type is known as an Entity bean or a List Set or
|
||||
* Map of entity beans.
|
||||
*/
|
||||
public boolean isSupportedType(Type genericType);
|
||||
|
||||
/**
|
||||
* Create and return a new JsonGenerator for the given writer.
|
||||
*/
|
||||
public JsonGenerator createGenerator(Writer writer) throws IOException;
|
||||
|
||||
/**
|
||||
* Create and return a new JsonParser for the given reader.
|
||||
*/
|
||||
public JsonParser createParser(Reader reader) throws IOException;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* Marker interface for all the Raw JSON types.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface JsonElement {
|
||||
|
||||
/**
|
||||
* Return true if this is a JSON primitive type (null, boolean, number or
|
||||
* string).
|
||||
*/
|
||||
public boolean isPrimitive();
|
||||
|
||||
/**
|
||||
* Return the string value of this primitive JSON element.
|
||||
* <p>
|
||||
* This can not be used for JsonElementObject or JsonElementArray.
|
||||
* </p>
|
||||
*/
|
||||
public String toPrimitiveString();
|
||||
|
||||
public Object eval(String exp);
|
||||
|
||||
public int evalInt(String exp);
|
||||
|
||||
public String evalString(String exp);
|
||||
|
||||
public boolean evalBoolean(String exp);
|
||||
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JSON Array element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class JsonElementArray implements JsonElement {
|
||||
|
||||
private final List<JsonElement> values = new ArrayList<JsonElement>();
|
||||
|
||||
public List<JsonElement> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void add(JsonElement value) {
|
||||
values.add(value);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return values.toString();
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] split(String exp) {
|
||||
int pos = exp.indexOf('.');
|
||||
if (pos == -1) {
|
||||
return new String[] { exp, null };
|
||||
}
|
||||
String exp0 = exp.substring(0, pos);
|
||||
String exp1 = exp.substring(pos + 1);
|
||||
return new String[] { exp0, exp1 };
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
String[] e = split(exp);
|
||||
return eval(e[0], e[1]);
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
String[] e = split(exp);
|
||||
return evalInt(e[0], e[1]);
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
String[] e = split(exp);
|
||||
return evalString(e[0], e[1]);
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private Object eval(String exp0, String exp1) {
|
||||
if ("size".equals(exp0)) {
|
||||
return values.size();
|
||||
}
|
||||
if ("isEmpty".equals(exp0)) {
|
||||
return values.isEmpty();
|
||||
}
|
||||
int idx = Integer.parseInt(exp0);
|
||||
JsonElement element = values.get(idx);
|
||||
return element.eval(exp1);
|
||||
}
|
||||
|
||||
private int evalInt(String exp0, String exp1) {
|
||||
if ("size".equals(exp0)) {
|
||||
return values.size();
|
||||
}
|
||||
if ("isEmpty".equals(exp0)) {
|
||||
return values.isEmpty() ? 1 : 0;
|
||||
}
|
||||
int idx = Integer.parseInt(exp0);
|
||||
JsonElement element = values.get(idx);
|
||||
return element.evalInt(exp1);
|
||||
}
|
||||
|
||||
private String evalString(String exp0, String exp1) {
|
||||
if ("size".equals(exp0)) {
|
||||
return String.valueOf(values.size());
|
||||
}
|
||||
if ("isEmpty".equals(exp0)) {
|
||||
return String.valueOf(values.isEmpty());
|
||||
}
|
||||
int idx = Integer.parseInt(exp0);
|
||||
JsonElement element = values.get(idx);
|
||||
return element.evalString(exp1);
|
||||
}
|
||||
|
||||
public String getString() {
|
||||
return toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* JSON boolean element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
|
||||
public class JsonElementBoolean implements JsonElement {
|
||||
|
||||
public static final JsonElementBoolean TRUE = new JsonElementBoolean(true);
|
||||
|
||||
public static final JsonElementBoolean FALSE = new JsonElementBoolean(false);
|
||||
|
||||
private final Boolean value;
|
||||
|
||||
private JsonElementBoolean(Boolean value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Boolean getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Boolean.toString(value);
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on boolean");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
return value ? 1 : 0;
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* JSON null element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class JsonElementNull implements JsonElement {
|
||||
|
||||
public static final JsonElementNull NULL = new JsonElementNull();
|
||||
|
||||
private JsonElementNull() {
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return "null";
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "json null";
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on null");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* JSON number element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class JsonElementNumber implements JsonElement {
|
||||
|
||||
private final String value;
|
||||
|
||||
public JsonElementNumber(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return Double.parseDouble(value);
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* JSON Object element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class JsonElementObject implements JsonElement {
|
||||
|
||||
private final Map<String, JsonElement> map = new LinkedHashMap<String, JsonElement>();
|
||||
|
||||
public void put(String key, JsonElement value) {
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
private String[] split(String exp) {
|
||||
int pos = exp.indexOf('.');
|
||||
if (pos == -1) {
|
||||
return new String[] { exp, null };
|
||||
}
|
||||
String exp0 = exp.substring(0, pos);
|
||||
String exp1 = exp.substring(pos + 1);
|
||||
return new String[] { exp0, exp1 };
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
String[] e = split(exp);
|
||||
return eval(e[0], e[1]);
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
String[] e = split(exp);
|
||||
return evalInt(e[0], e[1]);
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
if (exp == null) {
|
||||
return map.toString();
|
||||
}
|
||||
String[] e = split(exp);
|
||||
return evalString(e[0], e[1]);
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
String[] e = split(exp);
|
||||
return evalBoolean(e[0], e[1]);
|
||||
}
|
||||
|
||||
private Object eval(String exp0, String exp1) {
|
||||
JsonElement e = map.get(exp0);
|
||||
return e == null ? null : e.eval(exp1);
|
||||
}
|
||||
|
||||
private int evalInt(String exp0, String exp1) {
|
||||
JsonElement e = map.get(exp0);
|
||||
return e == null ? 0 : e.evalInt(exp1);
|
||||
}
|
||||
|
||||
private String evalString(String exp0, String exp1) {
|
||||
JsonElement e = map.get(exp0);
|
||||
return e == null ? "" : e.evalString(exp1);
|
||||
}
|
||||
|
||||
private boolean evalBoolean(String exp0, String exp1) {
|
||||
JsonElement e = map.get(exp0);
|
||||
return e == null ? false : e.evalBoolean(exp1);
|
||||
}
|
||||
|
||||
public JsonElement get(String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public JsonElement getValue(String key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public Set<String> keySet() {
|
||||
return map.keySet();
|
||||
}
|
||||
|
||||
public Set<Map.Entry<String, JsonElement>> entrySet() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return map.toString();
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* JSON string element.
|
||||
* <p>
|
||||
* You will only use the JsonElements when you register a JsonReadBeanVisitor.
|
||||
* The JSON elements that are not mapped to a bean property are made available
|
||||
* to the JsonReadBeanVisitor.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadBeanVisitor
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class JsonElementString implements JsonElement {
|
||||
|
||||
private final String value;
|
||||
|
||||
public JsonElementString(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isPrimitive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toPrimitiveString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object eval(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public int evalInt(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String evalString(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean evalBoolean(String exp) {
|
||||
if (exp != null) {
|
||||
throw new IllegalArgumentException("expression [" + exp + "] not allowed on number");
|
||||
}
|
||||
return Boolean.parseBoolean(exp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides for some custom handling of json content as it is read.
|
||||
* <p>
|
||||
* This visit method is called after all the known properties of the bean have
|
||||
* been processed. Any JSON elements that could not be mapped to known bean
|
||||
* properties are available in the unmapped Map.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* @param <T>
|
||||
* The type of entity bean
|
||||
*/
|
||||
public interface JsonReadBeanVisitor<T> {
|
||||
|
||||
/**
|
||||
* Visit the bean that has just been processed.
|
||||
* <p>
|
||||
* This provides a method of customising the bean and processing any custom
|
||||
* JSON content.
|
||||
* </p>
|
||||
*
|
||||
* @param bean
|
||||
* the bean being processed
|
||||
* @param unmapped
|
||||
* Map of any JSON elements that didn't map to known bean properties
|
||||
*/
|
||||
public void visit(T bean, Map<String, JsonElement> unmapped);
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides the ability to customise the reading of JSON content.
|
||||
* <p>
|
||||
* You can optionally provide a custom JsonValueAdapter to handle specific
|
||||
* formatting for Date and DateTime types.
|
||||
* </p>
|
||||
* <p>
|
||||
* You can optionally register JsonReadBeanVisitors to customise the processing
|
||||
* of the beans as they are processed and handle any custom JSON elements that
|
||||
* could not be mapped to bean properties.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
*/
|
||||
public class JsonReadOptions {
|
||||
|
||||
protected JsonValueAdapter valueAdapter;
|
||||
|
||||
protected Map<String, JsonReadBeanVisitor<?>> visitorMap;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public JsonReadOptions() {
|
||||
this.visitorMap = new LinkedHashMap<String, JsonReadBeanVisitor<?>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonValueAdapter.
|
||||
*/
|
||||
public JsonValueAdapter getValueAdapter() {
|
||||
return valueAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map of JsonReadBeanVisitor's.
|
||||
*/
|
||||
public Map<String, JsonReadBeanVisitor<?>> getVisitorMap() {
|
||||
return visitorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JsonValueAdapter for custom DateTime and Date formatting.
|
||||
*/
|
||||
public JsonReadOptions setValueAdapter(JsonValueAdapter valueAdapter) {
|
||||
this.valueAdapter = valueAdapter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonReadBeanVisitor for the root level.
|
||||
*/
|
||||
public JsonReadOptions addRootVisitor(JsonReadBeanVisitor<?> visitor) {
|
||||
return addVisitor(null, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonReadBeanVisitor for a given path.
|
||||
*/
|
||||
public JsonReadOptions addVisitor(String path, JsonReadBeanVisitor<?> visitor) {
|
||||
visitorMap.put(path, visitor);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2009 Authors
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Allows you to customise the Date and Timestamp formats.
|
||||
* <p>
|
||||
* There is not a standard JSON format for Date or Timestamp types. By default
|
||||
* Ebean uses ISO8601 "yyyy-MM-dd'T'HH:mm:ss.SSSZ" and "yyyy-MM-dd".
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that Ebean will convert Joda types to either of the Date or Timestamp
|
||||
* types and back for you.
|
||||
* </p>
|
||||
*
|
||||
* @see JsonReadOptions
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface JsonValueAdapter {
|
||||
|
||||
/**
|
||||
* Convert the Date to json string.
|
||||
*/
|
||||
public String jsonFromDate(java.sql.Date date);
|
||||
|
||||
/**
|
||||
* Convert the DateTime to json string.
|
||||
*/
|
||||
public String jsonFromTimestamp(java.sql.Timestamp date);
|
||||
|
||||
/**
|
||||
* Parse the JSON string into a Date.
|
||||
*/
|
||||
public java.sql.Date jsonToDate(String jsonDate);
|
||||
|
||||
/**
|
||||
* Parse the JSON DateTime into a Timestamp.
|
||||
*/
|
||||
public Timestamp jsonToTimestamp(String jsonDateTime);
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* Allows for customising the JSON write processing.
|
||||
* <p>
|
||||
* You can use this to add raw JSON content via {@link JsonWriter}.
|
||||
* </p>
|
||||
* <p>
|
||||
* You register a JsonWriteBeanVisitor with {@link JsonWriteOptions}.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* @param <T>
|
||||
* the type of entity bean
|
||||
*
|
||||
* @see JsonWriteOptions
|
||||
*/
|
||||
public interface JsonWriteBeanVisitor<T> {
|
||||
|
||||
/**
|
||||
* Visit the bean that has just been writing it's content to JSON. You can
|
||||
* write your own additional JSON content to the JsonWriter if you wish.
|
||||
*
|
||||
* @param bean
|
||||
* the bean that has been writing it's content
|
||||
* @param jsonWriter
|
||||
* the JsonWriter which you can append custom json content to if you
|
||||
* wish.
|
||||
*/
|
||||
public void visit(T bean, JsonWriter jsonWriter);
|
||||
|
||||
}
|
||||
@@ -1,78 +1,23 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
|
||||
/**
|
||||
* Provides options for customising the JSON write process.
|
||||
* <p>
|
||||
* You can optionally provide a custom JsonValueAdapter to handle specific
|
||||
* formatting for Date and DateTime types.
|
||||
* </p>
|
||||
* <p>
|
||||
* You can optionally register JsonWriteBeanVisitors to customise the processing
|
||||
* of the beans as they are processed and <strong>add raw JSON
|
||||
* elements</strong>.
|
||||
* </p>
|
||||
* <p>
|
||||
* You can explicitly state which properties to include in the JSON output for
|
||||
* the root level and each path.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* // find some customers ...
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).select("id, name, status, shippingAddress")
|
||||
* .fetch("billingAddress",
|
||||
* "line1, city").fetch("billingAddress.country", "*").fetch("contacts", "firstName,email")
|
||||
* .order().desc("id")
|
||||
* .findList();
|
||||
*
|
||||
* JsonContext json = Ebean.createJsonContext();
|
||||
*
|
||||
* JsonWriteOptions writeOptions = new JsonWriteOptions();
|
||||
* writeOptions.setRootPathVisitor(new JsonWriteBeanVisitor<Customer>() {
|
||||
*
|
||||
* public void visit(Customer bean, JsonWriter ctx) {
|
||||
* System.out.println("write visit customer: " + bean);
|
||||
* ctx.appendKeyValue("dummyCust", "34");
|
||||
* ctx.appendKeyValue("smallCustObject", "{\"a\":34,\"b\":\"asdasdasd\"}");
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* writeOptions.setPathProperties("contacts", "firstName,id");
|
||||
* writeOptions.setPathVisitor("contacts", new JsonWriteBeanVisitor<Contact>() {
|
||||
*
|
||||
* public void visit(Contact bean, JsonWriter ctx) {
|
||||
* System.out.println("write additional custom json on customer: " + bean);
|
||||
* ctx.appendKeyValue("dummy", " 3400" + bean.getId() + "");
|
||||
* ctx.appendKeyValue("smallObject", "{\"contactA\":34,\"contactB\":\"banana\"}");
|
||||
* }
|
||||
*
|
||||
* });
|
||||
*
|
||||
|
||||
* // output as a JSON string with pretty formatting
|
||||
* String s = json.toJsonString(list, true, writeOptions);
|
||||
* String s = json.toJson(list, true, writeOptions);
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @see JsonContext#toList(Class, String, JsonReadOptions)
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
*/
|
||||
public class JsonWriteOptions {
|
||||
|
||||
protected String callback;
|
||||
|
||||
protected JsonValueAdapter valueAdapter;
|
||||
|
||||
protected Map<String, JsonWriteBeanVisitor<?>> visitorMap;
|
||||
|
||||
protected PathProperties pathProperties;
|
||||
|
||||
/**
|
||||
@@ -88,138 +33,6 @@ public class JsonWriteOptions {
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* This creates and returns a copy of these options.
|
||||
* <p>
|
||||
* Note that it assumes that the JsonWriteBeanVisitor (if defined) are
|
||||
* immutable and any JsonWriteBeanVisitor instances are shared between the
|
||||
* original and the copy.
|
||||
* </p>
|
||||
*/
|
||||
public JsonWriteOptions copy() {
|
||||
JsonWriteOptions copy = new JsonWriteOptions();
|
||||
copy.callback = callback;
|
||||
copy.valueAdapter = valueAdapter;
|
||||
copy.pathProperties = pathProperties;
|
||||
if (visitorMap != null) {
|
||||
copy.visitorMap = new HashMap<String, JsonWriteBeanVisitor<?>>(visitorMap);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a JSONP callback function.
|
||||
*/
|
||||
public String getCallback() {
|
||||
return callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JSONP callback function.
|
||||
*/
|
||||
public JsonWriteOptions setCallback(String callback) {
|
||||
this.callback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonValueAdapter.
|
||||
*/
|
||||
public JsonValueAdapter getValueAdapter() {
|
||||
return valueAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a JsonValueAdapter for custom DateTime and Date formatting.
|
||||
*/
|
||||
public JsonWriteOptions setValueAdapter(JsonValueAdapter valueAdapter) {
|
||||
this.valueAdapter = valueAdapter;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonWriteBeanVisitor for the root level.
|
||||
*/
|
||||
public JsonWriteOptions setRootPathVisitor(JsonWriteBeanVisitor<?> visitor) {
|
||||
return setPathVisitor(null, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonWriteBeanVisitor for the given path.
|
||||
*/
|
||||
public JsonWriteOptions setPathVisitor(String path, JsonWriteBeanVisitor<?> visitor) {
|
||||
if (visitorMap == null) {
|
||||
visitorMap = new HashMap<String, JsonWriteBeanVisitor<?>>();
|
||||
}
|
||||
visitorMap.put(path, visitor);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties to include in the JSON output for the given path.
|
||||
*
|
||||
* @param propertiesToInclude
|
||||
* The set of properties to output
|
||||
*/
|
||||
public JsonWriteOptions setPathProperties(String path, Set<String> propertiesToInclude) {
|
||||
if (pathProperties == null) {
|
||||
pathProperties = new PathProperties();
|
||||
}
|
||||
pathProperties.put(path, propertiesToInclude);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties to include in the JSON output for the given path.
|
||||
*
|
||||
* @param propertiesToInclude
|
||||
* Comma delimited list of properties to output
|
||||
*/
|
||||
public JsonWriteOptions setPathProperties(String path, String propertiesToInclude) {
|
||||
return setPathProperties(path, parseProps(propertiesToInclude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties to include in the JSON output for the root level.
|
||||
*
|
||||
* @param propertiesToInclude
|
||||
* Comma delimited list of properties to output
|
||||
*/
|
||||
public JsonWriteOptions setRootPathProperties(String propertiesToInclude) {
|
||||
return setPathProperties(null, parseProps(propertiesToInclude));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the properties to include in the JSON output for the root level.
|
||||
*
|
||||
* @param propertiesToInclude
|
||||
* The set of properties to output
|
||||
*/
|
||||
public JsonWriteOptions setRootPathProperties(Set<String> propertiesToInclude) {
|
||||
return setPathProperties(null, propertiesToInclude);
|
||||
}
|
||||
|
||||
private Set<String> parseProps(String propertiesToInclude) {
|
||||
|
||||
LinkedHashSet<String> props = new LinkedHashSet<String>();
|
||||
|
||||
String[] split = propertiesToInclude.split(",");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String s = split[i].trim();
|
||||
if (s.length() > 0) {
|
||||
props.add(s);
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Map of registered JsonWriteBeanVisitor's by path.
|
||||
*/
|
||||
public Map<String, JsonWriteBeanVisitor<?>> getVisitorMap() {
|
||||
return visitorMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Map of properties to include by path.
|
||||
*/
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
/**
|
||||
* The JSON Writer made available to JsonWriteBeanVisitor's so that you can
|
||||
* append your own JSON content into the output.
|
||||
*
|
||||
* @see JsonWriteBeanVisitor
|
||||
* @see JsonWriteOptions#setRootPathVisitor(JsonWriteBeanVisitor)
|
||||
* @see JsonWriteOptions#setPathVisitor(String, JsonWriteBeanVisitor)
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface JsonWriter {
|
||||
|
||||
/**
|
||||
* Use this to append some custom content into the JSON output.
|
||||
*
|
||||
* @param key
|
||||
* the json key
|
||||
*
|
||||
* @param rawJsonValue
|
||||
* raw json value
|
||||
*/
|
||||
public void appendRawValue(String key, String rawJsonValue);
|
||||
|
||||
public void appendQuoteEscapeValue(String key, String rawJsonValue);
|
||||
|
||||
}
|
||||
@@ -19,31 +19,10 @@
|
||||
* .order().desc("id")
|
||||
* .findList();
|
||||
*
|
||||
* JsonContext json = Ebean.createJsonContext();
|
||||
*
|
||||
* JsonWriteOptions writeOptions = new JsonWriteOptions();
|
||||
* writeOptions.setRootPathVisitor(new JsonWriteBeanVisitor<Customer>() {
|
||||
*
|
||||
* public void visit(Customer bean, JsonWriter ctx) {
|
||||
* System.out.println("write visit customer: " + bean);
|
||||
* ctx.appendKeyValue("dummyCust", "34");
|
||||
* ctx.appendKeyValue("smallCustObject", "{\"a\":34,\"b\":\"asdasdasd\"}");
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* writeOptions.setPathProperties("contacts", "firstName,id");
|
||||
* writeOptions.setPathVisitor("contacts", new JsonWriteBeanVisitor<Contact>() {
|
||||
*
|
||||
* public void visit(Contact bean, JsonWriter ctx) {
|
||||
* System.out.println("write additional custom json on customer: " + bean);
|
||||
* ctx.appendKeyValue("dummy", " 3400" + bean.getId() + "");
|
||||
* ctx.appendKeyValue("smallObject", "{\"contactA\":34,\"contactB\":\"banana\"}");
|
||||
* }
|
||||
*
|
||||
* });
|
||||
*
|
||||
* // output as a JSON string with pretty formatting
|
||||
* String s = json.toJsonString(list, true, writeOptions);
|
||||
* JsonContext json = Ebean.json();
|
||||
*
|
||||
* // output as a JSON string
|
||||
* String jsonOutput = json.toJson(list);
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
@@ -53,13 +53,15 @@ public class ManyWhereJoins implements Serializable {
|
||||
String join = elProp.getElPrefix();
|
||||
BeanProperty p = elProp.getBeanProperty();
|
||||
if (p instanceof BeanPropertyAssocMany<?>){
|
||||
join = addManyToJoin(join, p.getName());
|
||||
join = addManyToJoin(join, p.getName());
|
||||
}
|
||||
if (join != null){
|
||||
addJoin(join);
|
||||
String secondaryTableJoinPrefix = p.getSecondaryTableJoinPrefix();
|
||||
if (secondaryTableJoinPrefix != null) {
|
||||
addJoin(join+"."+secondaryTableJoinPrefix);
|
||||
if (p != null) {
|
||||
String secondaryTableJoinPrefix = p.getSecondaryTableJoinPrefix();
|
||||
if (secondaryTableJoinPrefix != null) {
|
||||
addJoin(join+"."+secondaryTableJoinPrefix);
|
||||
}
|
||||
}
|
||||
addParentJoins(join);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import com.avaje.ebean.ExpressionFactory;
|
||||
import com.avaje.ebeaninternal.server.expression.FilterExprPath;
|
||||
|
||||
public interface SpiExpressionFactory extends ExpressionFactory {
|
||||
|
||||
/**
|
||||
* Create another expression factory with a given sub path.
|
||||
*/
|
||||
public ExpressionFactory createExpressionFactory();//FilterExprPath prefix);
|
||||
|
||||
/**
|
||||
* Create another expression factory with a given sub path.
|
||||
*/
|
||||
public ExpressionFactory createExpressionFactory();
|
||||
|
||||
}
|
||||
|
||||
@@ -44,9 +44,14 @@ public interface SpiExpressionRequest {
|
||||
* Return the ordered list of bind values for all expressions in this request.
|
||||
*/
|
||||
public ArrayList<Object> getBindValues();
|
||||
|
||||
/**
|
||||
* Increments the parameter index and returns that value.
|
||||
*/
|
||||
public int nextParameter();
|
||||
|
||||
/**
|
||||
* Increments the parameter index and returns that value.
|
||||
*/
|
||||
public int nextParameter();
|
||||
|
||||
/**
|
||||
* Append a DB Like clause.
|
||||
*/
|
||||
public void appendLike();
|
||||
}
|
||||
|
||||
@@ -532,12 +532,24 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
* Return the index of the first row to return in the query.
|
||||
*/
|
||||
public int getFirstRow();
|
||||
|
||||
/**
|
||||
* Internally set by Ebean when this query must use the DISTINCT keyword.
|
||||
* <p>
|
||||
* This does not exclude/remove the use of the id property.
|
||||
*/
|
||||
public Query<T> setSqlDistinct(boolean sqlDistinct);
|
||||
|
||||
/**
|
||||
* return true if this query uses DISTINCT.
|
||||
* Return true if this query has been specified by a user or internally by Ebean to use DISTINCT.
|
||||
*/
|
||||
public boolean isDistinctQuery();
|
||||
|
||||
/**
|
||||
* Return true if this query has been specified by a user to use DISTINCT.
|
||||
*/
|
||||
public boolean isDistinct();
|
||||
|
||||
|
||||
/**
|
||||
* Set default select clauses where none have been explicitly defined.
|
||||
*/
|
||||
|
||||
@@ -15,6 +15,11 @@ import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
*/
|
||||
public interface SpiTransaction extends Transaction {
|
||||
|
||||
/**
|
||||
* End the transaction when had query only use.
|
||||
*/
|
||||
public void endQueryOnly();
|
||||
|
||||
/**
|
||||
* Return the string prefix with the transactin id and label used in logging.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.avaje.ebean.annotation.CacheTuning;
|
||||
@@ -89,9 +88,7 @@ public class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
public void clearAll() {
|
||||
Iterator<ServerCache> it = concMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
ServerCache serverCache = it.next();
|
||||
for (ServerCache serverCache : concMap.values()) {
|
||||
serverCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +111,7 @@ public class DefaultServerCache implements ServerCache {
|
||||
|
||||
int hc = reset ? removedHitCount.getAndSet(0) : removedHitCount.get();
|
||||
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
for (CacheEntry cacheEntry : map.values()) {
|
||||
hc += cacheEntry.getHitCount(reset);
|
||||
}
|
||||
|
||||
@@ -268,10 +266,6 @@ public class DefaultServerCache implements ServerCache {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
private Iterator<CacheEntry> cacheEntries() {
|
||||
return map.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* The task used to periodically trim the cache.
|
||||
*/
|
||||
@@ -296,7 +290,7 @@ public class DefaultServerCache implements ServerCache {
|
||||
long idleExpire = System.currentTimeMillis() - (maxIdleSecs*1000);
|
||||
long ttlExpire = System.currentTimeMillis() - (maxSecsToLive*1000);
|
||||
|
||||
Iterator<CacheEntry> it = cacheEntries();
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
if (maxIdleSecs > 0 && idleExpire > cacheEntry.getLastAccessTime()) {
|
||||
|
||||
@@ -32,8 +32,6 @@ public abstract class BeanRequest {
|
||||
|
||||
protected boolean createdTransaction;
|
||||
|
||||
protected boolean readOnly;
|
||||
|
||||
public BeanRequest(SpiEbeanServer ebeanServer, SpiTransaction t) {
|
||||
this.ebeanServer = ebeanServer;
|
||||
this.serverName = ebeanServer.getName();
|
||||
@@ -62,29 +60,19 @@ public abstract class BeanRequest {
|
||||
if (transaction == null || !transaction.isActive()) {
|
||||
// create an implicit transaction to execute this query
|
||||
transaction = ebeanServer.createServerTransaction(false, -1);
|
||||
// commented out for performance reasons...
|
||||
// TODO: review performance of trans.setReadOnly(true)
|
||||
//if (readOnlyTransaction) {
|
||||
// readOnly = true;
|
||||
// transaction.setReadOnly(true);
|
||||
//}
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit this transaction if it was created for this request.
|
||||
*/
|
||||
public void commitTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
if (readOnly) {
|
||||
transaction.rollback();
|
||||
} else {
|
||||
transaction.commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Commit this transaction if it was created for this request.
|
||||
*/
|
||||
public void commitTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
transaction.commit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the transaction if it was created for this request.
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
@@ -11,6 +10,7 @@ import javax.persistence.Table;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.CompoundType;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
@@ -65,7 +65,9 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
public BootupClasses(List<Class<?>> list) {
|
||||
if (list != null) {
|
||||
process(list.iterator());
|
||||
for (Class<?> cls : list) {
|
||||
isMatch(cls);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,13 +85,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
this.serverConfigStartupList.addAll(parent.serverConfigStartupList);
|
||||
}
|
||||
|
||||
private void process(Iterator<Class<?>> it) {
|
||||
while (it.hasNext()) {
|
||||
Class<?> cls = it.next();
|
||||
isMatch(cls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of this object so that classes can be added to it.
|
||||
*/
|
||||
@@ -297,13 +292,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
return beanListenerList;
|
||||
}
|
||||
|
||||
public void add(Iterator<Class<?>> it) {
|
||||
while (it.hasNext()) {
|
||||
Class<?> clazz = it.next();
|
||||
isMatch(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isMatch(Class<?> cls) {
|
||||
|
||||
if (isEmbeddable(cls)) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.avaje.ebeaninternal.api.SpiQuery.Mode;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
/**
|
||||
@@ -112,6 +113,15 @@ public class DefaultBeanLoader {
|
||||
if (orderBy != null) {
|
||||
query.orderBy(orderBy);
|
||||
}
|
||||
|
||||
String extraWhere = many.getExtraWhere();
|
||||
if (extraWhere != null) {
|
||||
// replace special ${ta} placeholder with the base table alias
|
||||
// which is always t0 and add the extra where clause
|
||||
String ew = StringHelper.replaceString(extraWhere, "${ta}", "t0");
|
||||
query.where().raw(ew);
|
||||
}
|
||||
|
||||
query.setLazyLoadForParents(idList, many);
|
||||
many.addWhereParentIdIn(query, idList);
|
||||
|
||||
@@ -405,6 +415,13 @@ public class DefaultBeanLoader {
|
||||
if (ebi.isReadOnly()) {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
|
||||
if (SpiQuery.Mode.REFRESH_BEAN.equals(mode)) {
|
||||
// explicitly state to load all properties on REFRESH.
|
||||
// Lobs default to fetch lazy so this forces lobs to be
|
||||
// included in a 'refresh' query
|
||||
query.select("*");
|
||||
}
|
||||
|
||||
Object dbBean = query.findUnique();
|
||||
if (dbBean == null) {
|
||||
|
||||
@@ -65,7 +65,6 @@ import com.avaje.ebean.meta.MetaBeanInfo;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.avaje.ebean.text.csv.CsvReader;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import com.avaje.ebean.text.json.JsonElement;
|
||||
import com.avaje.ebeaninternal.api.LoadBeanRequest;
|
||||
import com.avaje.ebeaninternal.api.LoadManyRequest;
|
||||
import com.avaje.ebeaninternal.api.ScopeTrans;
|
||||
@@ -286,6 +285,13 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
ddlGenerator = (DdlGenerator)plugin;
|
||||
}
|
||||
}
|
||||
|
||||
if (ddlGenerator == null) {
|
||||
// ServiceLoader not finding ddlGenerator (typically OSGi)
|
||||
ddlGenerator = new DdlGenerator();
|
||||
spiPlugins.add(ddlGenerator);
|
||||
ddlGenerator.setup(this, this.getDatabasePlatform(), config.getServerConfig());
|
||||
}
|
||||
|
||||
ebeanPlugins = Collections.unmodifiableList(spiPlugins);
|
||||
}
|
||||
@@ -1112,7 +1118,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
// predicates on *ToMany properties
|
||||
if (query.initManyWhereJoins()) {
|
||||
// we need a sql distinct now
|
||||
query.setDistinct(true);
|
||||
query.setSqlDistinct(true);
|
||||
}
|
||||
|
||||
boolean allowOneManyFetch = true;
|
||||
@@ -1198,18 +1204,12 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(desc, spiQuery, t);
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return (T) request.findId();
|
||||
|
||||
T bean = (T) request.findId();
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return bean;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1256,15 +1256,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
Set<T> set = (Set<T>) request.findSet();
|
||||
return (Set<T>) request.findSet();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return set;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
// String stackTrace = throwablePrinter.print(ex);
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1280,15 +1275,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
Map<?, T> map = (Map<?, T>) request.findMap();
|
||||
return (Map<?, T>) request.findMap();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return map;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
// String stackTrace = throwablePrinter.print(ex);
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1303,14 +1293,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ROWCOUNT, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
int rowCount = request.findRowCount();
|
||||
return request.findRowCount();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return rowCount;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,14 +1312,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ID_LIST, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
List<Object> list = request.findIds();
|
||||
return request.findIds();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return list;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1434,10 +1416,8 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
request.findVisit(visitor);
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
} finally {
|
||||
// do nothing - findVisit garuntee's cleanup of the transaction if required
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1448,10 +1428,9 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findIterate();
|
||||
// request.endTransIfRequired();
|
||||
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
request.endTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@@ -1468,14 +1447,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
List<T> list = request.findList();
|
||||
return request.findList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return list;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1518,14 +1493,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
List<SqlRow> list = request.findList();
|
||||
return request.findList();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return list;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1535,14 +1506,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
Set<SqlRow> set = request.findSet();
|
||||
return request.findSet();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return set;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1551,14 +1518,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, t);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
Map<?, SqlRow> map = request.findMap();
|
||||
return request.findMap();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
|
||||
return map;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1999,10 +1962,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (typeInfo == null) {
|
||||
return false;
|
||||
}
|
||||
Class<?> beanType = typeInfo.getBeanType();
|
||||
if (JsonElement.class.isAssignableFrom(beanType)) {
|
||||
return true;
|
||||
}
|
||||
return getBeanDescriptor(typeInfo.getBeanType()) != null;
|
||||
}
|
||||
|
||||
@@ -2122,11 +2081,18 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
return new CallStack(finalTrace);
|
||||
}
|
||||
|
||||
public JsonContext createJsonContext() {
|
||||
|
||||
@Override
|
||||
public JsonContext json() {
|
||||
// immutable thread safe so return shared instance
|
||||
return jsonContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonContext createJsonContext() {
|
||||
return json();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void collectQueryStats(ObjectGraphNode node, long loadedBeanCount, long timeMicros) {
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/**
|
||||
* Copyright (C) 2006 Robin Bygrave
|
||||
*
|
||||
* This file is part of Ebean.
|
||||
*
|
||||
* Ebean is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Ebean is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Ebean; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.sql.Connection;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -9,8 +11,6 @@ import com.avaje.ebean.config.ExternalTransactionManager;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import com.avaje.ebean.text.json.JsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
import com.avaje.ebeaninternal.api.SpiBackgroundExecutor;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManager;
|
||||
@@ -22,6 +22,7 @@ import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
@@ -30,7 +31,7 @@ import com.avaje.ebeaninternal.server.query.DefaultRelationalQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.resource.ResourceManager;
|
||||
import com.avaje.ebeaninternal.server.resource.ResourceManagerFactory;
|
||||
import com.avaje.ebeaninternal.server.text.json.DJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.DefaultJsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.transaction.AutoCommitTransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.JtaTransactionManager;
|
||||
@@ -38,6 +39,7 @@ import com.avaje.ebeaninternal.server.transaction.TransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.TransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.type.DefaultTypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
|
||||
/**
|
||||
* Used to extend the ServerConfig with additional objects used to configure and
|
||||
@@ -87,10 +89,13 @@ public class InternalConfiguration {
|
||||
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
private final JsonFactory jsonFactory;
|
||||
|
||||
public InternalConfiguration(XmlConfig xmlConfig, ClusterManager clusterManager,
|
||||
ServerCacheManager cacheManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses, PstmtBatch pstmtBatch) {
|
||||
|
||||
this.jsonFactory = serverConfig.getJsonFactory();
|
||||
this.xmlConfig = xmlConfig;
|
||||
this.pstmtBatch = pstmtBatch;
|
||||
this.clusterManager = clusterManager;
|
||||
@@ -113,8 +118,7 @@ public class InternalConfiguration {
|
||||
this.beanDescriptorManager = new BeanDescriptorManager(this);
|
||||
beanDescriptorManager.deploy();
|
||||
|
||||
this.transactionManager = new TransactionManager(clusterManager, backgroundExecutor,
|
||||
serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
this.transactionManager = createTransactionManager();
|
||||
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder);
|
||||
|
||||
@@ -131,19 +135,38 @@ public class InternalConfiguration {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the TransactionManager taking into account autoCommit mode.
|
||||
*/
|
||||
private TransactionManager createTransactionManager() {
|
||||
|
||||
if (isAutoCommitMode()) {
|
||||
return new AutoCommitTransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
return new TransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on.
|
||||
*/
|
||||
private boolean isAutoCommitMode() {
|
||||
if (serverConfig.isAutoCommitMode()) {
|
||||
// explicitly set
|
||||
return true;
|
||||
}
|
||||
DataSource dataSource = serverConfig.getDataSource();
|
||||
if (dataSource instanceof DataSourcePool && ((DataSourcePool)dataSource).getAutoCommit()) {
|
||||
// We know the DataSourcePool is using autoCommit
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsonContext createJsonContext(SpiEbeanServer server) {
|
||||
|
||||
String s = serverConfig.getProperty("json.pretty", "false");
|
||||
boolean dfltPretty = "true".equalsIgnoreCase(s);
|
||||
|
||||
s = serverConfig.getProperty("json.jsonValueAdapter", null);
|
||||
|
||||
JsonValueAdapter va = new DefaultJsonValueAdapter();
|
||||
if (s != null) {
|
||||
va = (JsonValueAdapter) ClassUtil.newInstance(s, this.getClass());
|
||||
}
|
||||
return new DJsonContext(server, va, dfltPretty);
|
||||
return new DJsonContext(server, jsonFactory);
|
||||
}
|
||||
|
||||
public XmlConfig getXmlConfig() {
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.ExpressionFactory;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.config.ExternalTransactionManager;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import com.avaje.ebeaninternal.api.SpiBackgroundExecutor;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManager;
|
||||
import com.avaje.ebeaninternal.server.autofetch.AutoFetchManagerFactory;
|
||||
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployOrmXml;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployCreateProperties;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionFactory;
|
||||
import com.avaje.ebeaninternal.server.lib.sql.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.query.DefaultOrmQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.query.DefaultRelationalQueryEngine;
|
||||
import com.avaje.ebeaninternal.server.resource.ResourceManager;
|
||||
import com.avaje.ebeaninternal.server.resource.ResourceManagerFactory;
|
||||
import com.avaje.ebeaninternal.server.text.json.DJsonContext;
|
||||
<<<<<<< HEAD
|
||||
import com.avaje.ebeaninternal.server.text.json.DefaultJsonValueAdapter;
|
||||
import com.avaje.ebeaninternal.server.transaction.AutoCommitTransactionManager;
|
||||
=======
|
||||
>>>>>>> json-refactor
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.ExternalTransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.JtaTransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.TransactionManager;
|
||||
import com.avaje.ebeaninternal.server.transaction.TransactionScopeManager;
|
||||
import com.avaje.ebeaninternal.server.type.DefaultTypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
/**
|
||||
* Used to extend the ServerConfig with additional objects used to configure and
|
||||
* construct an EbeanServer.
|
||||
*/
|
||||
public class InternalConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(InternalConfiguration.class);
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
|
||||
private final BootupClasses bootupClasses;
|
||||
|
||||
private final DeployInherit deployInherit;
|
||||
|
||||
private final ResourceManager resourceManager;
|
||||
|
||||
private final DeployOrmXml deployOrmXml;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final Binder binder;
|
||||
|
||||
private final DeployCreateProperties deployCreateProperties;
|
||||
|
||||
private final DeployUtil deployUtil;
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
private final TransactionManager transactionManager;
|
||||
|
||||
private final TransactionScopeManager transactionScopeManager;
|
||||
|
||||
private final CQueryEngine cQueryEngine;
|
||||
|
||||
private final ClusterManager clusterManager;
|
||||
|
||||
private final ServerCacheManager cacheManager;
|
||||
|
||||
private final ExpressionFactory expressionFactory;
|
||||
|
||||
private final SpiBackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final PstmtBatch pstmtBatch;
|
||||
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
public InternalConfiguration(XmlConfig xmlConfig, ClusterManager clusterManager,
|
||||
ServerCacheManager cacheManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses, PstmtBatch pstmtBatch) {
|
||||
|
||||
this.xmlConfig = xmlConfig;
|
||||
this.pstmtBatch = pstmtBatch;
|
||||
this.clusterManager = clusterManager;
|
||||
this.backgroundExecutor = backgroundExecutor;
|
||||
this.cacheManager = cacheManager;
|
||||
this.serverConfig = serverConfig;
|
||||
this.bootupClasses = bootupClasses;
|
||||
this.expressionFactory = new DefaultExpressionFactory();
|
||||
|
||||
this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses);
|
||||
this.binder = new Binder(typeManager);
|
||||
|
||||
this.resourceManager = ResourceManagerFactory.createResourceManager(serverConfig);
|
||||
this.deployOrmXml = new DeployOrmXml(resourceManager.getResourceSource());
|
||||
this.deployInherit = new DeployInherit(bootupClasses);
|
||||
|
||||
this.deployCreateProperties = new DeployCreateProperties(typeManager);
|
||||
this.deployUtil = new DeployUtil(typeManager, serverConfig);
|
||||
|
||||
this.beanDescriptorManager = new BeanDescriptorManager(this);
|
||||
beanDescriptorManager.deploy();
|
||||
|
||||
this.transactionManager = createTransactionManager();
|
||||
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder);
|
||||
|
||||
ExternalTransactionManager externalTransactionManager = serverConfig.getExternalTransactionManager();
|
||||
if (externalTransactionManager == null && serverConfig.isUseJtaTransactionManager()) {
|
||||
externalTransactionManager = new JtaTransactionManager();
|
||||
}
|
||||
if (externalTransactionManager != null) {
|
||||
externalTransactionManager.setTransactionManager(transactionManager);
|
||||
this.transactionScopeManager = new ExternalTransactionScopeManager(transactionManager, externalTransactionManager);
|
||||
logger.info("Using Transaction Manager [" + externalTransactionManager.getClass() + "]");
|
||||
} else {
|
||||
this.transactionScopeManager = new DefaultTransactionScopeManager(transactionManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the TransactionManager taking into account autoCommit mode.
|
||||
*/
|
||||
private TransactionManager createTransactionManager() {
|
||||
|
||||
if (isAutoCommitMode()) {
|
||||
return new AutoCommitTransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
return new TransactionManager(clusterManager, backgroundExecutor, serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if autoCommit mode is on.
|
||||
*/
|
||||
private boolean isAutoCommitMode() {
|
||||
if (serverConfig.isAutoCommitMode()) {
|
||||
// explicitly set
|
||||
return true;
|
||||
}
|
||||
DataSource dataSource = serverConfig.getDataSource();
|
||||
if (dataSource instanceof DataSourcePool && ((DataSourcePool)dataSource).getAutoCommit()) {
|
||||
// We know the DataSourcePool is using autoCommit
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public JsonContext createJsonContext(SpiEbeanServer server) {
|
||||
|
||||
return new DJsonContext(server);
|
||||
}
|
||||
|
||||
public XmlConfig getXmlConfig() {
|
||||
return xmlConfig;
|
||||
}
|
||||
|
||||
public AutoFetchManager createAutoFetchManager(SpiEbeanServer server) {
|
||||
return AutoFetchManagerFactory.create(server, serverConfig, resourceManager);
|
||||
}
|
||||
|
||||
public RelationalQueryEngine createRelationalQueryEngine() {
|
||||
return new DefaultRelationalQueryEngine(binder, serverConfig.getDatabaseBooleanTrue());
|
||||
}
|
||||
|
||||
public OrmQueryEngine createOrmQueryEngine() {
|
||||
return new DefaultOrmQueryEngine(beanDescriptorManager, cQueryEngine);
|
||||
}
|
||||
|
||||
public Persister createPersister(SpiEbeanServer server) {
|
||||
return new DefaultPersister(server, binder, beanDescriptorManager, pstmtBatch);
|
||||
}
|
||||
|
||||
public PstmtBatch getPstmtBatch() {
|
||||
return pstmtBatch;
|
||||
}
|
||||
|
||||
public ServerCacheManager getCacheManager() {
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
public BootupClasses getBootupClasses() {
|
||||
return bootupClasses;
|
||||
}
|
||||
|
||||
public DatabasePlatform getDatabasePlatform() {
|
||||
return serverConfig.getDatabasePlatform();
|
||||
}
|
||||
|
||||
public ServerConfig getServerConfig() {
|
||||
return serverConfig;
|
||||
}
|
||||
|
||||
public ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory;
|
||||
}
|
||||
|
||||
public TypeManager getTypeManager() {
|
||||
return typeManager;
|
||||
}
|
||||
|
||||
public Binder getBinder() {
|
||||
return binder;
|
||||
}
|
||||
|
||||
public BeanDescriptorManager getBeanDescriptorManager() {
|
||||
return beanDescriptorManager;
|
||||
}
|
||||
|
||||
public DeployInherit getDeployInherit() {
|
||||
return deployInherit;
|
||||
}
|
||||
|
||||
public ResourceManager getResourceManager() {
|
||||
return resourceManager;
|
||||
}
|
||||
|
||||
public DeployOrmXml getDeployOrmXml() {
|
||||
return deployOrmXml;
|
||||
}
|
||||
|
||||
public DeployCreateProperties getDeployCreateProperties() {
|
||||
return deployCreateProperties;
|
||||
}
|
||||
|
||||
public DeployUtil getDeployUtil() {
|
||||
return deployUtil;
|
||||
}
|
||||
|
||||
public TransactionManager getTransactionManager() {
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
public TransactionScopeManager getTransactionScopeManager() {
|
||||
return transactionScopeManager;
|
||||
}
|
||||
|
||||
public CQueryEngine getCQueryEngine() {
|
||||
return cQueryEngine;
|
||||
}
|
||||
|
||||
public ClusterManager getClusterManager() {
|
||||
return clusterManager;
|
||||
}
|
||||
|
||||
public SpiBackgroundExecutor getBackgroundExecutor() {
|
||||
return backgroundExecutor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,6 +71,15 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
this.readOnly = query.isReadOnly();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the database platform like clause.
|
||||
*/
|
||||
@Override
|
||||
public String getDBLikeClause() {
|
||||
return ebeanServer.getDatabasePlatform().getLikeClause();
|
||||
}
|
||||
|
||||
public void executeSecondaryQueries(int defaultQueryBatch) {
|
||||
loadContext.executeSecondaryQueries(this, defaultQueryBatch);
|
||||
}
|
||||
@@ -193,14 +202,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
/**
|
||||
* Will end a locally created transaction.
|
||||
* <p>
|
||||
* It ends the transaction by using a rollback() as the transaction is known
|
||||
* to be readOnly.
|
||||
* It ends the query only transaction.
|
||||
* </p>
|
||||
*/
|
||||
public void endTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
// we can rollback as readOnly transaction
|
||||
transaction.rollback();
|
||||
transaction.endQueryOnly();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
private List<BeanPropertyAssocMany<?>> updatedManys;
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type) {
|
||||
PersistExecute persistExecute, PersistRequest.Type type, boolean saveRecurse) {
|
||||
|
||||
super(server, t, persistExecute);
|
||||
this.entityBean = (EntityBean) bean;
|
||||
@@ -103,12 +103,9 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
this.bean = bean;
|
||||
this.parentBean = parentBean;
|
||||
this.controller = beanDescriptor.getPersistController();
|
||||
|
||||
if (PersistRequest.Type.DETERMINE != type) {
|
||||
this.type = type;
|
||||
} else {
|
||||
// determine mode during cascade save (supporting stateless update)
|
||||
this.type = beanDescriptor.isInsertMode(intercept) ? Type.INSERT : Type.UPDATE;
|
||||
this.type = type;
|
||||
|
||||
if (saveRecurse) {
|
||||
this.persistCascade = t.isPersistCascade();
|
||||
}
|
||||
|
||||
|
||||
@@ -40,15 +40,6 @@ public final class RelationalQueryRequest {
|
||||
this.trans = (SpiTransaction) t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the transaction if it was created for this request.
|
||||
*/
|
||||
public void rollbackTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
trans.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transaction if none currently exists.
|
||||
*/
|
||||
@@ -58,10 +49,6 @@ public final class RelationalQueryRequest {
|
||||
if (trans == null || !trans.isActive()) {
|
||||
// create a local readOnly transaction
|
||||
trans = ebeanServer.createServerTransaction(false, -1);
|
||||
|
||||
// commented out for performance reasons...
|
||||
// TODO: review performance of trans.setReadOnly(true)
|
||||
// trans.setReadOnly(true);
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
@@ -72,8 +59,7 @@ public final class RelationalQueryRequest {
|
||||
*/
|
||||
public void endTransIfRequired() {
|
||||
if (createdTransaction) {
|
||||
// we can rollback as a readOnly transaction.
|
||||
trans.rollback();
|
||||
trans.endQueryOnly();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ public interface SpiOrmQueryRequest<T> {
|
||||
*/
|
||||
public void endTransIfRequired();
|
||||
|
||||
public void rollbackTransIfRequired();
|
||||
|
||||
/**
|
||||
* Execute the query as findById.
|
||||
*/
|
||||
@@ -97,4 +95,9 @@ public interface SpiOrmQueryRequest<T> {
|
||||
*/
|
||||
public BeanCollection<T> getFromQueryCache();
|
||||
|
||||
/**
|
||||
* Return the Database platform like clause.
|
||||
*/
|
||||
public String getDBLikeClause();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.avaje.ebeaninternal.server.ddl;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
|
||||
/**
|
||||
* A visitor that creates indexes for columns annotated with ColumnIndex
|
||||
*
|
||||
* @author rvbiljouw
|
||||
* @see com.avaje.ebean.annotation.Index
|
||||
*/
|
||||
public class CreateIndexVisitor extends AbstractBeanVisitor {
|
||||
private final IndexPropertyVisitor iv;
|
||||
|
||||
public CreateIndexVisitor(DdlGenContext ctx) {
|
||||
this.iv = new IndexPropertyVisitor(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBegin() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visitBean(BeanDescriptor<?> descriptor) {
|
||||
return descriptor.isInheritanceRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PropertyVisitor visitProperty(BeanProperty p) {
|
||||
return iv;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBeanEnd(BeanDescriptor<?> descriptor) {
|
||||
visitInheritanceProperties(descriptor, iv);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
|
||||
}
|
||||
|
||||
private static final class IndexPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
private final DdlGenContext ctx;
|
||||
|
||||
public IndexPropertyVisitor(DdlGenContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitOneImported(BeanPropertyAssocOne<?> p) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitScalar(BeanProperty p) {
|
||||
String baseTable = p.getBeanDescriptor().getBaseTable();
|
||||
if (p.isIndexed()) {
|
||||
String indexName = p.getIndexName();
|
||||
if (indexName.length() == 0) {
|
||||
indexName = ctx.getDdlSyntax().getIndexName(baseTable, p.getDbColumn(), ctx.incrementIxCount());
|
||||
}
|
||||
ctx.write("create index ")
|
||||
.write(indexName)
|
||||
.write(" on ")
|
||||
.write(baseTable)
|
||||
.write("(")
|
||||
.write(p.getDbColumn())
|
||||
.write(");")
|
||||
.writeNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCompoundScalar(BeanPropertyCompound compound, BeanProperty p) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,17 +98,17 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeDrop(String dropFile) {
|
||||
protected void writeDrop(String dropFile) {
|
||||
|
||||
try {
|
||||
String c = generateDropDdl();
|
||||
writeFile(dropFile, c);
|
||||
try {
|
||||
String c = generateDropDdl();
|
||||
writeFile(dropFile, c);
|
||||
|
||||
} catch (IOException e) {
|
||||
String msg = "Error generating Drop DDL";
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
String msg = "Error generating Drop DDL";
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeCreate(String createFile) {
|
||||
|
||||
@@ -149,6 +149,9 @@ public class DdlGenerator implements SpiEbeanPlugin {
|
||||
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(ctx);
|
||||
VisitorUtil.visit(server, fkeys);
|
||||
|
||||
CreateIndexVisitor indexes = new CreateIndexVisitor(ctx);
|
||||
VisitorUtil.visit(server, indexes);
|
||||
|
||||
ctx.flush();
|
||||
createContent = ctx.getContent();
|
||||
return createContent;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
@@ -9,7 +10,7 @@ import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper functions for performing tasks on Lists Sets or Maps.
|
||||
@@ -59,9 +60,9 @@ public interface BeanCollectionHelp<T> {
|
||||
*/
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean);
|
||||
|
||||
/**
|
||||
* Write the collection out as json.
|
||||
*/
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude);
|
||||
/**
|
||||
* Write the collection out as json.
|
||||
*/
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
@@ -34,8 +35,6 @@ import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.meta.MetaBeanInfo;
|
||||
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebean.text.json.JsonWriteBeanVisitor;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlan;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
@@ -62,15 +61,13 @@ import com.avaje.ebeaninternal.server.query.CQueryPlan;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPlanStats.Snapshot;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext.ReadBeanState;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext.WriteBeanState;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.avaje.ebeaninternal.util.SortByClause;
|
||||
import com.avaje.ebeaninternal.util.SortByClause.Property;
|
||||
import com.avaje.ebeaninternal.util.SortByClauseParser;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
@@ -195,12 +192,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
/**
|
||||
* Inheritance information. Server side only.
|
||||
*/
|
||||
private final InheritInfo inheritInfo;
|
||||
protected final InheritInfo inheritInfo;
|
||||
|
||||
/**
|
||||
* Derived list of properties that make up the unique id.
|
||||
*/
|
||||
private final BeanProperty idProperty;
|
||||
protected final BeanProperty idProperty;
|
||||
private final int idPropertyIndex;
|
||||
|
||||
/**
|
||||
@@ -327,7 +324,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
private final boolean cacheSharableBeans;
|
||||
|
||||
private final BeanDescriptorCacheHelp<T> cacheHelp;
|
||||
|
||||
private final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
|
||||
private final String defaultSelectClause;
|
||||
private final Set<String> defaultSelectClauseSet;
|
||||
|
||||
@@ -422,7 +420,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
|
||||
this.cacheHelp = new BeanDescriptorCacheHelp<T>(this, owner.getCacheManager(), deploy.getCacheOptions(), cacheSharableBeans, propertiesOneImported);
|
||||
|
||||
this.jsonHelp = new BeanDescriptorJsonHelp<T>(this);
|
||||
|
||||
// Check if there are no cascade save associated beans ( subject to change
|
||||
// in initialiseOther()). Note that if we are in an inheritance hierarchy
|
||||
@@ -603,9 +601,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
if (isEmbedded()) {
|
||||
// initialise all the properties
|
||||
Iterator<BeanProperty> it = propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
BeanProperty prop = it.next();
|
||||
for (BeanProperty prop : propertiesAll()) {
|
||||
prop.initialise();
|
||||
}
|
||||
} else {
|
||||
@@ -623,9 +619,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
if (!isEmbedded()) {
|
||||
// initialise all the non-id properties
|
||||
Iterator<BeanProperty> it = propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
BeanProperty prop = it.next();
|
||||
for (BeanProperty prop : propertiesAll()) {
|
||||
if (!prop.isId()) {
|
||||
prop.initialise();
|
||||
}
|
||||
@@ -1028,9 +1022,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* Reset the statistics on all the query plans.
|
||||
*/
|
||||
public void clearQueryStatistics() {
|
||||
Iterator<CQueryPlan> it = queryPlanCache.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CQueryPlan queryPlan = (CQueryPlan) it.next();
|
||||
for (CQueryPlan queryPlan : queryPlanCache.values()) {
|
||||
queryPlan.resetStatistics();
|
||||
}
|
||||
}
|
||||
@@ -1046,13 +1038,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plans for this BeanDescriptor.
|
||||
*/
|
||||
public Iterator<CQueryPlan> queryPlans() {
|
||||
return queryPlanCache.values().iterator();
|
||||
}
|
||||
|
||||
public CQueryPlan getQueryPlan(HashQueryPlan key) {
|
||||
return queryPlanCache.get(key);
|
||||
}
|
||||
@@ -1223,8 +1208,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
convertSetId(id, eb);
|
||||
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
ebi.setBeanLoaderByServerName(ebeanServer.getName());
|
||||
|
||||
ebi.setBeanLoader(ebeanServer);
|
||||
|
||||
// Note: not creating proxies for many's...
|
||||
ebi.setReference(idPropertyIndex);
|
||||
@@ -1531,7 +1515,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
if (propertyDeploy && chain != null) {
|
||||
BeanFkeyProperty fk = fkeyMap.get(propName);
|
||||
if (fk != null) {
|
||||
return fk.create(chain.getExpression());
|
||||
return fk.create(chain.getExpression(), chain.isContainsMany());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1854,10 +1838,10 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an Iterator of all BeanProperty. This includes transient properties.
|
||||
* Return a collection of all BeanProperty. This includes transient properties.
|
||||
*/
|
||||
public Iterator<BeanProperty> propertiesAll() {
|
||||
return propMap.values().iterator();
|
||||
public Collection<BeanProperty> propertiesAll() {
|
||||
return propMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1886,21 +1870,31 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return idProperty;
|
||||
}
|
||||
|
||||
public boolean isInsertMode(EntityBeanIntercept ebi) {
|
||||
/**
|
||||
* Return true if this bean should be inserted rather than updated.
|
||||
*
|
||||
* @param ebi
|
||||
* The entity bean intercept
|
||||
* @param insertMode
|
||||
* true if the 'root request' was an insert rather than an update
|
||||
*/
|
||||
public boolean isInsertMode(EntityBeanIntercept ebi, boolean insertMode) {
|
||||
|
||||
if (ebi.isLoaded()) {
|
||||
// must be an update as the bean is loaded
|
||||
return false;
|
||||
}
|
||||
|
||||
// determine based on Id property
|
||||
if (idProperty.isEmbedded()) {
|
||||
// not using Id generator so just base on isLoaded()
|
||||
return !ebi.isLoaded();
|
||||
}
|
||||
//if (idGenerator == null) {
|
||||
// return !ebi.isLoaded();
|
||||
//} else {
|
||||
return !hasIdProperty(ebi);
|
||||
//}
|
||||
if (!hasIdProperty(ebi)) {
|
||||
// No Id property means it must be an insert
|
||||
return true;
|
||||
}
|
||||
// same as the 'root request'
|
||||
return insertMode;
|
||||
}
|
||||
|
||||
public boolean isReference(EntityBeanIntercept ebi) {
|
||||
@@ -2119,167 +2113,23 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return propertiesLocal;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
if (bean != null) {
|
||||
|
||||
ctx.appendObjectBegin();
|
||||
WriteBeanState prevState = ctx.pushBeanState(bean);
|
||||
|
||||
if (inheritInfo != null) {
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
|
||||
String discValue = localInheritInfo.getDiscriminatorStringValue();
|
||||
String discColumn = localInheritInfo.getDiscriminatorColumn();
|
||||
ctx.appendDiscriminator(discColumn, discValue);
|
||||
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
localDescriptor.jsonWriteProperties(ctx, bean);
|
||||
|
||||
} else {
|
||||
jsonWriteProperties(ctx, bean);
|
||||
}
|
||||
|
||||
ctx.pushPreviousState(prevState);
|
||||
ctx.appendObjectEnd();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void jsonWriteProperties(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
JsonWriteBeanVisitor<T> beanVisitor = (JsonWriteBeanVisitor<T>) ctx.getBeanVisitor();
|
||||
|
||||
Set<String> props = ctx.getIncludeProperties();
|
||||
|
||||
boolean explicitAllProps;
|
||||
if (props == null) {
|
||||
explicitAllProps = false;
|
||||
} else {
|
||||
explicitAllProps = props.contains("*");
|
||||
if (explicitAllProps || props.isEmpty()) {
|
||||
props = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (idProperty != null) {
|
||||
Object idValue = idProperty.getValue(bean);
|
||||
if (idValue != null) {
|
||||
if (props == null || props.contains(idProperty.getName())) {
|
||||
idProperty.jsonWrite(ctx, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!explicitAllProps && props == null) {
|
||||
// just render the loaded properties
|
||||
props = ((EntityBean)bean)._ebean_getIntercept().getLoadedPropertyNames();
|
||||
}
|
||||
if (props != null) {
|
||||
// render only the appropriate properties (when not all properties)
|
||||
for (String prop : props) {
|
||||
BeanProperty p = getBeanProperty(prop);
|
||||
if (p != null && !p.isId()) {
|
||||
p.jsonWrite(ctx, bean);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (explicitAllProps || !isReference(bean._ebean_getIntercept())) {
|
||||
// render all the properties and invoke lazy loading if required
|
||||
for (int j = 0; j < propertiesNonTransient.length; j++) {
|
||||
propertiesNonTransient[j].jsonWrite(ctx, bean);
|
||||
}
|
||||
for (int j = 0; j < propertiesTransient.length; j++) {
|
||||
propertiesTransient[j].jsonWrite(ctx, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (beanVisitor != null) {
|
||||
beanVisitor.visit((T) bean, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T jsonReadBean(ReadJsonContext ctx, String path) {
|
||||
ReadBeanState beanState = jsonRead(ctx, path);
|
||||
if (beanState == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (T) beanState.getBean();
|
||||
}
|
||||
}
|
||||
|
||||
public ReadBeanState jsonRead(ReadJsonContext ctx, String path) {
|
||||
if (!ctx.readObjectBegin()) {
|
||||
// the object is null
|
||||
return null;
|
||||
}
|
||||
|
||||
if (inheritInfo == null) {
|
||||
return jsonReadObject(ctx, path);
|
||||
|
||||
} else {
|
||||
|
||||
// check for the discriminator value to determine the correct sub type
|
||||
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
|
||||
|
||||
if (!ctx.readKeyNext()) {
|
||||
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
|
||||
throw new TextException(msg);
|
||||
}
|
||||
|
||||
String propName = ctx.getTokenKey();
|
||||
String discValue;
|
||||
if (propName.equalsIgnoreCase(discColumn)) {
|
||||
discValue = ctx.readScalarValue();
|
||||
if (!ctx.readValueNext()) {
|
||||
// Expected to read a comma to setup for reading the real properties of the bean
|
||||
String msg = "Error reading inheritance discriminator [" + discColumn + "]. Expected more json name values?";
|
||||
throw new TextException(msg);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Assume that the we are just reading using this bean type
|
||||
// Push the token key back so that it is re-read as it is one
|
||||
// of the real properties of the bean itself
|
||||
ctx.pushTokenKey();
|
||||
discValue = inheritInfo.getDiscriminatorStringValue();
|
||||
}
|
||||
|
||||
// determine the sub type for this particular json object
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(discValue);
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
return localDescriptor.jsonReadObject(ctx, path);
|
||||
}
|
||||
}
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean) throws IOException {
|
||||
jsonHelp.jsonWrite(writeJson, bean, null);
|
||||
}
|
||||
|
||||
private ReadBeanState jsonReadObject(ReadJsonContext ctx, String path) {
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean, String key) throws IOException {
|
||||
jsonHelp.jsonWrite(writeJson, bean, key);
|
||||
}
|
||||
|
||||
EntityBean bean = createEntityBean();
|
||||
ctx.pushBean(bean, path, this);
|
||||
|
||||
do {
|
||||
if (!ctx.readKeyNext()) {
|
||||
break;
|
||||
} else {
|
||||
// we read a property key ...
|
||||
String propName = ctx.getTokenKey();
|
||||
BeanProperty p = getBeanProperty(propName);
|
||||
if (p != null) {
|
||||
p.jsonRead(ctx, bean);
|
||||
ctx.setProperty(propName);
|
||||
} else {
|
||||
// unknown property key ...
|
||||
ctx.readUnmappedJson(propName);
|
||||
}
|
||||
|
||||
if (!ctx.readValueNext()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return ctx.popBeanState();
|
||||
protected void jsonWriteProperties(WriteJson writeJson, EntityBean bean) throws IOException {
|
||||
jsonHelp.jsonWriteProperties(writeJson, bean);
|
||||
}
|
||||
|
||||
public T jsonRead(JsonParser parser, String path) throws IOException {
|
||||
return jsonHelp.jsonRead(parser, path);
|
||||
}
|
||||
|
||||
protected T jsonReadObject(JsonParser parser, String path) throws IOException {
|
||||
return jsonHelp.jsonReadObject(parser, path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,18 +429,21 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
|
||||
EntityBean bean = desc.createEntityBean();
|
||||
desc.convertSetId(id, bean);
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
ebi.setBeanLoader(desc.getEbeanServer());
|
||||
|
||||
if (Boolean.TRUE.equals(readOnly)) {
|
||||
bean._ebean_getIntercept().setReadOnly(true);
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
|
||||
beanLoadData(bean, data);
|
||||
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" GET {}({}) - hit", cacheName, id);
|
||||
}
|
||||
return (T) bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a bean from the cache given its Id.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson.WriteBean;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class BeanDescriptorJsonHelp<T> {
|
||||
|
||||
private final BeanDescriptor<T> desc;
|
||||
|
||||
private final InheritInfo inheritInfo;
|
||||
|
||||
public BeanDescriptorJsonHelp(BeanDescriptor<T> desc) {
|
||||
this.desc = desc;
|
||||
this.inheritInfo = desc.inheritInfo;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean, String key) throws IOException {
|
||||
|
||||
writeJson.writeStartObject(key);
|
||||
|
||||
if (inheritInfo == null) {
|
||||
jsonWriteProperties(writeJson, bean);
|
||||
|
||||
} else {
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(bean.getClass());
|
||||
String discValue = localInheritInfo.getDiscriminatorStringValue();
|
||||
String discColumn = localInheritInfo.getDiscriminatorColumn();
|
||||
writeJson.gen().writeStringField(discColumn, discValue);
|
||||
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
localDescriptor.jsonWriteProperties(writeJson, bean);
|
||||
}
|
||||
|
||||
writeJson.writeEndObject();
|
||||
}
|
||||
|
||||
protected void jsonWriteProperties(WriteJson writeJson, EntityBean bean) throws IOException {
|
||||
|
||||
|
||||
WriteBean writeBean = writeJson.createWriteBean(desc, bean);
|
||||
writeBean.write(writeJson);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T jsonRead(JsonParser parser, String path) throws IOException {
|
||||
|
||||
JsonToken token = parser.nextToken();
|
||||
if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) {
|
||||
return null;
|
||||
}
|
||||
if (JsonToken.START_OBJECT != token) {
|
||||
throw new JsonParseException("Unexpected token "+token+" - expecting start_object", parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
if (desc.inheritInfo == null) {
|
||||
return jsonReadObject(parser, path);
|
||||
}
|
||||
|
||||
// check for the discriminator value to determine the correct sub type
|
||||
String discColumn = inheritInfo.getRoot().getDiscriminatorColumn();
|
||||
|
||||
token = parser.nextToken();
|
||||
if (token != JsonToken.FIELD_NAME) {
|
||||
String msg = "Error reading inheritance discriminator - expected [" + discColumn + "] but no json key?";
|
||||
throw new JsonParseException(msg, parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
String propName = parser.getCurrentName();
|
||||
if (!propName.equalsIgnoreCase(discColumn)) {
|
||||
// just try to assume this is the correct bean type in the inheritance
|
||||
BeanProperty property = desc.getBeanProperty(propName);
|
||||
if (property != null) {
|
||||
EntityBean bean = desc.createEntityBean();
|
||||
property.jsonRead(parser, bean);
|
||||
return jsonReadProperties(parser, bean);
|
||||
}
|
||||
String msg = "Error reading inheritance discriminator, expected property ["+discColumn+"] but got [" + propName + "] ?";
|
||||
throw new JsonParseException(msg, parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
String discValue = parser.nextTextValue();
|
||||
|
||||
// determine the sub type for this particular json object
|
||||
InheritInfo localInheritInfo = inheritInfo.readType(discValue);
|
||||
BeanDescriptor<?> localDescriptor = localInheritInfo.getBeanDescriptor();
|
||||
return (T) localDescriptor.jsonReadObject(parser, path);
|
||||
}
|
||||
|
||||
protected T jsonReadObject(JsonParser parser, String path) throws IOException {
|
||||
|
||||
EntityBean bean = desc.createEntityBean();
|
||||
return jsonReadProperties(parser, bean);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected T jsonReadProperties(JsonParser parser, EntityBean bean) throws IOException {
|
||||
|
||||
do {
|
||||
|
||||
JsonToken event = parser.nextToken();
|
||||
if (JsonToken.FIELD_NAME == event) {
|
||||
String key = parser.getCurrentName();
|
||||
BeanProperty p = desc.getBeanProperty(key);
|
||||
if (p != null) {
|
||||
p.jsonRead(parser, bean);
|
||||
|
||||
} else {
|
||||
// Object rawValue = EJson.parse(parser);
|
||||
// unknown property key ...
|
||||
// ctx.readUnmappedJson(propName);
|
||||
}
|
||||
|
||||
} else if (JsonToken.END_OBJECT == event) {
|
||||
break;
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected token " + event + " - expecting key or end_object at: " + parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
} while (true);
|
||||
return (T)bean;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +1,20 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -61,9 +64,7 @@ import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
|
||||
import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflect;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectFactory;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectProperties;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
|
||||
import com.avaje.ebeaninternal.server.reflect.EnhanceBeanReflectFactory;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
@@ -510,9 +511,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEntityBeanTable() {
|
||||
|
||||
Iterator<DeployBeanInfo<?>> it = deplyInfoMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanInfo<?> info = it.next();
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
BeanTable beanTable = createBeanTable(info);
|
||||
beanTableMap.put(beanTable.getBeanType(), beanTable);
|
||||
}
|
||||
@@ -526,18 +525,14 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEntityDeploymentAssociations() {
|
||||
|
||||
Iterator<DeployBeanInfo<?>> it = deplyInfoMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanInfo<?> info = it.next();
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
readDeployAssociations(info);
|
||||
}
|
||||
}
|
||||
|
||||
private void readInheritedIdGenerators() {
|
||||
|
||||
Iterator<DeployBeanInfo<?>> it = deplyInfoMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanInfo<?> info = it.next();
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
DeployBeanDescriptor<?> descriptor = info.getDescriptor();
|
||||
InheritInfo inheritInfo = descriptor.getInheritInfo();
|
||||
if (inheritInfo != null && !inheritInfo.isRoot()) {
|
||||
@@ -613,10 +608,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* @param info the new inheritance info
|
||||
*/
|
||||
private void setInheritanceInfo(DeployBeanInfo<?> info) {
|
||||
|
||||
for (DeployBeanPropertyAssocOne<?> oneProp : info.getDescriptor().propertiesAssocOne()) {
|
||||
if (!oneProp.isTransient()) {
|
||||
DeployBeanInfo<?> assoc = deplyInfoMap.get(oneProp.getTargetType());
|
||||
|
||||
if (assoc != null){
|
||||
oneProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
|
||||
}
|
||||
@@ -626,7 +621,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
for (DeployBeanPropertyAssocMany<?> manyProp : info.getDescriptor().propertiesAssocMany()) {
|
||||
if (!manyProp.isTransient()) {
|
||||
DeployBeanInfo<?> assoc = deplyInfoMap.get(manyProp.getTargetType());
|
||||
|
||||
if (assoc != null){
|
||||
manyProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
|
||||
}
|
||||
@@ -755,9 +749,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
String searchName = name.substring(0, p).toLowerCase();
|
||||
|
||||
// search for this in the possible matches
|
||||
Iterator<String> it = matchSet.iterator();
|
||||
while (it.hasNext()) {
|
||||
String possibleMappedBy = it.next();
|
||||
for (String possibleMappedBy : matchSet) {
|
||||
String possibleLower = possibleMappedBy.toLowerCase();
|
||||
if (possibleLower.indexOf(searchName) > -1) {
|
||||
// we have a match..
|
||||
@@ -877,7 +869,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
if (!tableJoin.hasJoinColumns()) {
|
||||
// define Join as the inverse of the mappedBy property
|
||||
DeployTableJoin otherTableJoin = mappedAssocOne.getTableJoin();
|
||||
otherTableJoin.copyTo(tableJoin, true, tableJoin.getTable());
|
||||
otherTableJoin.copyWithoutType(tableJoin, true, tableJoin.getTable());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,6 +1011,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// set bean controller, finder and listener
|
||||
setBeanControllerFinderListener(desc);
|
||||
deplyInherit.process(desc);
|
||||
desc.checkInheritanceMapping();
|
||||
|
||||
createProperties.createProperties(desc);
|
||||
|
||||
@@ -1153,12 +1146,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void setScalarType(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
Iterator<DeployBeanProperty> it = deployDesc.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?>) {
|
||||
|
||||
} else {
|
||||
for (DeployBeanProperty prop : deployDesc.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
|
||||
deployUtil.setScalarType(prop);
|
||||
}
|
||||
}
|
||||
@@ -1312,30 +1301,39 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
desc.setBeanReflect(beanReflect);
|
||||
desc.setProperties(reflectProps.getProperties());
|
||||
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : desc.propertiesAll()) {
|
||||
String propName = prop.getName();
|
||||
|
||||
Integer pos = reflectProps.getPropertyIndex(propName);
|
||||
if (pos == null) {
|
||||
throw new IllegalStateException("Property "+propName+" not found in "+reflectProps);
|
||||
}
|
||||
|
||||
BeanReflectGetter getter = beanReflect.getGetter(propName, pos.intValue());
|
||||
BeanReflectSetter setter = beanReflect.getSetter(propName, pos.intValue());
|
||||
prop.setGetter(getter);
|
||||
prop.setSetter(setter);
|
||||
prop.setPropertyIndex(pos.intValue());
|
||||
|
||||
if (getter == null) {
|
||||
String m = "BeanReflectGetter for " + prop.getFullBeanName() + " was not found?";
|
||||
throw new RuntimeException(m);
|
||||
|
||||
if (isPersistentField(prop)) {
|
||||
throw new IllegalStateException("Property "+propName+" not found in "+reflectProps);
|
||||
}
|
||||
|
||||
} else {
|
||||
int propertyIndex = pos.intValue();
|
||||
prop.setPropertyIndex(propertyIndex);
|
||||
prop.setGetter(beanReflect.getGetter(propName, propertyIndex));
|
||||
prop.setSetter(beanReflect.getSetter(propName, propertyIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a persistent field (not transient or static).
|
||||
*/
|
||||
private boolean isPersistentField(DeployBeanProperty prop) {
|
||||
|
||||
Field field = prop.getField();
|
||||
int modifiers = field.getModifiers();
|
||||
if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) {
|
||||
return false;
|
||||
}
|
||||
if (field.isAnnotationPresent(Transient.class)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* DevNote: It is assumed that Embedded can contain version properties. It is
|
||||
* also assumed that Embedded beans do NOT themselves contain Embedded beans
|
||||
@@ -1407,6 +1405,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
* enhanced or all dynamically subclassed).
|
||||
*/
|
||||
private void checkInheritedClasses(Class<?> beanClass) {
|
||||
|
||||
Class<?> superclass = beanClass.getSuperclass();
|
||||
if (Object.class.equals(superclass)) {
|
||||
// we got to the top of the inheritance
|
||||
@@ -1417,14 +1416,40 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return;
|
||||
}
|
||||
if (!EntityBean.class.isAssignableFrom(superclass)) {
|
||||
if (isMappedSuperWithNoProperties(superclass)) {
|
||||
// ok to stop and treat just the same as Object.class
|
||||
return;
|
||||
}
|
||||
throw new IllegalStateException("Super type "+superclass+" is not enhanced?");
|
||||
}
|
||||
|
||||
|
||||
// recursively continue up the inheritance hierarchy
|
||||
checkInheritedClasses(superclass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a MappedSuperclass bean with no persistent properties.
|
||||
* If so it is ok for it not to be enhanced.
|
||||
*/
|
||||
private boolean isMappedSuperWithNoProperties(Class<?> beanClass) {
|
||||
|
||||
MappedSuperclass annotation = beanClass.getAnnotation(MappedSuperclass.class);
|
||||
if (annotation == null) {
|
||||
return false;
|
||||
}
|
||||
Field[] fields = beanClass.getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) {
|
||||
// ignore this field
|
||||
} else if (field.isAnnotationPresent(Transient.class)) {
|
||||
// ignore this field
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to sort the BeanDescriptors by name.
|
||||
*/
|
||||
|
||||
@@ -10,182 +10,188 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
*/
|
||||
public final class BeanFkeyProperty implements ElPropertyValue {
|
||||
|
||||
private final String placeHolder;
|
||||
private final String prefix;
|
||||
private final String name;
|
||||
private final String dbColumn;
|
||||
private final String placeHolder;
|
||||
private final String prefix;
|
||||
private final String name;
|
||||
private final String dbColumn;
|
||||
private final boolean containsMany;
|
||||
|
||||
private int deployOrder;
|
||||
private int deployOrder;
|
||||
|
||||
public BeanFkeyProperty(String prefix, String name, String dbColumn, int deployOrder) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
this.dbColumn = dbColumn;
|
||||
this.deployOrder = deployOrder;
|
||||
this.placeHolder = calcPlaceHolder(prefix, dbColumn);
|
||||
}
|
||||
public BeanFkeyProperty(String prefix, String name, String dbColumn, int deployOrder) {
|
||||
this(prefix, name, dbColumn, deployOrder, false);
|
||||
}
|
||||
|
||||
private BeanFkeyProperty(String prefix, String name, String dbColumn, int deployOrder, boolean containsMany) {
|
||||
this.prefix = prefix;
|
||||
this.name = name;
|
||||
this.dbColumn = dbColumn;
|
||||
this.deployOrder = deployOrder;
|
||||
this.containsMany = containsMany;
|
||||
this.placeHolder = calcPlaceHolder(prefix, dbColumn);
|
||||
}
|
||||
|
||||
public int getDeployOrder() {
|
||||
return deployOrder;
|
||||
}
|
||||
public int getDeployOrder() {
|
||||
return deployOrder;
|
||||
}
|
||||
|
||||
private String calcPlaceHolder(String prefix, String dbColumn) {
|
||||
if (prefix != null) {
|
||||
return "${" + prefix + "}" + dbColumn;
|
||||
} else {
|
||||
return ROOT_ELPREFIX + dbColumn;
|
||||
}
|
||||
private String calcPlaceHolder(String prefix, String dbColumn) {
|
||||
if (prefix != null) {
|
||||
return "${" + prefix + "}" + dbColumn;
|
||||
} else {
|
||||
return ROOT_ELPREFIX + dbColumn;
|
||||
}
|
||||
}
|
||||
|
||||
public BeanFkeyProperty create(String expression) {
|
||||
int len = expression.length() - name.length() - 1;
|
||||
String prefix = expression.substring(0, len);
|
||||
public BeanFkeyProperty create(String expression, boolean containsMany) {
|
||||
int len = expression.length() - name.length() - 1;
|
||||
String prefix = expression.substring(0, len);
|
||||
|
||||
return new BeanFkeyProperty(prefix, name, dbColumn, deployOrder);
|
||||
}
|
||||
return new BeanFkeyProperty(prefix, name, dbColumn, deployOrder, containsMany);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false for keys.
|
||||
*/
|
||||
public boolean isDbEncrypted() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns false for keys.
|
||||
*/
|
||||
public boolean isDbEncrypted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false for keys.
|
||||
*/
|
||||
public boolean isLocalEncrypted() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns false for keys.
|
||||
*/
|
||||
public boolean isLocalEncrypted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only usable as ElPropertyDeploy.
|
||||
*/
|
||||
public boolean isDeployOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsFormulaWithJoin() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Only usable as ElPropertyDeploy.
|
||||
*/
|
||||
public boolean isDeployOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false.
|
||||
*/
|
||||
public boolean containsMany() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsManySince(String sinceProperty) {
|
||||
return containsMany();
|
||||
}
|
||||
@Override
|
||||
public boolean containsFormulaWithJoin() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getDbColumn() {
|
||||
return dbColumn;
|
||||
}
|
||||
/**
|
||||
* Returns false.
|
||||
*/
|
||||
public boolean containsMany() {
|
||||
return containsMany;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public boolean containsManySince(String sinceProperty) {
|
||||
return containsMany();
|
||||
}
|
||||
|
||||
public String getElName() {
|
||||
return name;
|
||||
}
|
||||
public String getDbColumn() {
|
||||
return dbColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public Object[] getAssocOneIdValues(EntityBean value) {
|
||||
return null;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
return null;
|
||||
}
|
||||
public String getElName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public Object[] getAssocOneIdValues(EntityBean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocIdInValueExpr(int size) {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false as not an AssocOne.
|
||||
*/
|
||||
public boolean isAssocId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAssocProperty() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getElPlaceholder(boolean encrypted) {
|
||||
return placeHolder;
|
||||
}
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public String getAssocIdInValueExpr(int size) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getElPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
/**
|
||||
* Returns false as not an AssocOne.
|
||||
*/
|
||||
public boolean isAssocId() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getJdbcType() {
|
||||
return 0;
|
||||
}
|
||||
public boolean isAssocProperty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object parseDateTime(long systemTimeMillis) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public String getElPlaceholder(boolean encrypted) {
|
||||
return placeHolder;
|
||||
}
|
||||
|
||||
public StringFormatter getStringFormatter() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public String getElPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
public StringParser getStringParser() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void elSetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public int getJdbcType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public Object elConvertType(Object value) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public BeanProperty getBeanProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public Object parseDateTime(long systemTimeMillis) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public StringFormatter getStringFormatter() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public StringParser getStringParser() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public BeanProperty getBeanProperty() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public void elSetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public String getDeployProperty() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
public Object elConvertType(Object value) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public String getDeployProperty() {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -12,7 +13,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanList;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper object for dealing with Lists.
|
||||
@@ -128,7 +129,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
|
||||
List<?> list;
|
||||
if (collection instanceof BeanCollection<?>) {
|
||||
@@ -147,15 +148,11 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
list = (List<?>) collection;
|
||||
}
|
||||
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.writeStartArray(name);
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
if (j > 0) {
|
||||
ctx.appendComma();
|
||||
}
|
||||
Object detailBean = list.get(j);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)list.get(j));
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
@@ -13,7 +14,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanMap;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper specifically for dealing with Maps.
|
||||
@@ -156,7 +157,7 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
|
||||
Map<?,?> map;
|
||||
if (collection instanceof BeanCollection<?>){
|
||||
@@ -175,19 +176,14 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
map = (Map<?,?>)collection;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.writeStartArray(name);
|
||||
Iterator<?> it = map.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Entry<?, ?> entry = (Entry<?, ?>)it.next();
|
||||
if (count++ > 0){
|
||||
ctx.appendComma();
|
||||
}
|
||||
//FIXME: json write map key ...
|
||||
Object detailBean = entry.getValue();
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import com.avaje.ebean.config.dbplatform.DbType;
|
||||
import com.avaje.ebean.text.StringFormatter;
|
||||
import com.avaje.ebean.text.StringParser;
|
||||
import com.avaje.ebean.text.TextException;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
@@ -30,10 +29,11 @@ import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
/**
|
||||
* Description of a property of a bean. Includes its deployment information such
|
||||
@@ -262,6 +262,9 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
final boolean jsonDeserialize;
|
||||
|
||||
final boolean indexed;
|
||||
|
||||
final String indexName;
|
||||
public BeanProperty(DeployBeanProperty deploy) {
|
||||
this(null, null, deploy);
|
||||
}
|
||||
@@ -271,7 +274,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
|
||||
this.indexed = deploy.isIndexed();
|
||||
this.indexName = deploy.getIndexName();
|
||||
this.unidirectionalShadow = deploy.isUndirectionalShadow();
|
||||
this.discriminator = deploy.isDiscriminator();
|
||||
this.localEncrypted = deploy.isLocalEncrypted();
|
||||
@@ -362,6 +366,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.name = InternString.intern(source.getName());
|
||||
this.propertyIndex = source.propertyIndex;
|
||||
|
||||
this.indexed = source.isIndexed();
|
||||
this.indexName = source.getIndexName();
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
this.sqlFormulaJoin = InternString.intern(override.getSqlFormulaJoin());
|
||||
this.sqlFormulaSelect = InternString.intern(override.getSqlFormulaSelect());
|
||||
@@ -446,7 +452,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
|
||||
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain,
|
||||
boolean propertyDeploy) {
|
||||
boolean propertyDeploy) {
|
||||
throw new PersistenceException("Not valid on scalar bean property " + getFullBeanName());
|
||||
}
|
||||
|
||||
@@ -475,17 +481,17 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Return true if this property maps to the inheritance discriminator column.
|
||||
*/
|
||||
public boolean isDiscriminator() {
|
||||
return discriminator;
|
||||
return discriminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the underlying type is mutable.
|
||||
*/
|
||||
public boolean isMutableScalarType() {
|
||||
if (scalarType == null) {
|
||||
return false;
|
||||
}
|
||||
return scalarType.isMutable();
|
||||
if (scalarType == null) {
|
||||
return false;
|
||||
}
|
||||
return scalarType.isMutable();
|
||||
}
|
||||
|
||||
public void copyProperty(EntityBean sourceBean, EntityBean destBean) {
|
||||
@@ -665,6 +671,14 @@ public class BeanProperty implements ElPropertyValue {
|
||||
public BeanProperty getBeanProperty() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the getter method.
|
||||
@@ -725,12 +739,12 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
private static Object[] NO_ARGS = new Object[0];
|
||||
|
||||
public Object getCacheDataValue(EntityBean bean){
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
public void setCacheDataValue(EntityBean bean, Object cacheData){
|
||||
setValue(bean, cacheData);
|
||||
public Object getCacheDataValue(EntityBean bean) {
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
public void setCacheDataValue(EntityBean bean, Object cacheData) {
|
||||
setValue(bean, cacheData);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -819,10 +833,9 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean containsFormulaWithJoin() {
|
||||
return formula && sqlFormulaJoin != null;
|
||||
return formula && sqlFormulaJoin != null;
|
||||
}
|
||||
|
||||
public boolean containsManySince(String sinceProperty) {
|
||||
@@ -880,10 +893,10 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
/**
|
||||
* Return true if the mutable value is considered dirty.
|
||||
* This is only used for 'mutable' scalar types like hstore etc.
|
||||
* This is only used for 'mutable' scalar types like hstore etc.
|
||||
*/
|
||||
public boolean isDirtyValue(Object value) {
|
||||
return scalarType.isDirty(value);
|
||||
return scalarType.isDirty(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -906,10 +919,10 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
|
||||
public int getJdbcType() {
|
||||
return scalarType == null ? 0 : scalarType.getJdbcType();
|
||||
return scalarType == null ? 0 : scalarType.getJdbcType();
|
||||
}
|
||||
|
||||
public Object parseDateTime(long systemTimeMillis) {
|
||||
public Object parseDateTime(long systemTimeMillis) {
|
||||
return scalarType.parseDateTime(systemTimeMillis);
|
||||
}
|
||||
|
||||
@@ -972,10 +985,10 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Return true if this is the natural key property.
|
||||
*/
|
||||
public boolean isNaturalKey() {
|
||||
return naturalKey;
|
||||
return naturalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Return true if this property is mandatory.
|
||||
*/
|
||||
public boolean isNullable() {
|
||||
@@ -1008,7 +1021,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Return true if this property is loadable from a resultSet.
|
||||
*/
|
||||
public boolean isLoadProperty() {
|
||||
return !isTransient || formula;
|
||||
return !isTransient || formula;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1051,10 +1064,10 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Lob's usually default to fetch lazy.
|
||||
*/
|
||||
public boolean isFetchEager() {
|
||||
return fetchEager;
|
||||
return fetchEager;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Return true if this is mapped to a Clob Blob LongVarchar or
|
||||
* LongVarbinary.
|
||||
*/
|
||||
@@ -1064,17 +1077,17 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
private boolean isLobType(int type) {
|
||||
switch (type) {
|
||||
case Types.CLOB:
|
||||
return true;
|
||||
case Types.BLOB:
|
||||
return true;
|
||||
case Types.LONGVARBINARY:
|
||||
return true;
|
||||
case Types.LONGVARCHAR:
|
||||
return true;
|
||||
case Types.CLOB:
|
||||
return true;
|
||||
case Types.BLOB:
|
||||
return true;
|
||||
case Types.LONGVARBINARY:
|
||||
return true;
|
||||
case Types.LONGVARCHAR:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1173,35 +1186,30 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
if(!jsonSerialize){
|
||||
return;
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
ctx.appendNull(name);
|
||||
} else {
|
||||
ctx.appendNameValue(name, scalarType, value);
|
||||
}
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean) throws IOException {
|
||||
if (!jsonSerialize) {
|
||||
return;
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
writeJson.writeNull(name);
|
||||
} else {
|
||||
scalarType.jsonWrite(writeJson.gen(), name, value);
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(JsonParser ctx, EntityBean bean) throws IOException {
|
||||
if (!jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean) {
|
||||
if(!jsonDeserialize){
|
||||
return;
|
||||
}
|
||||
String jsonValue;
|
||||
try {
|
||||
jsonValue = ctx.readScalarValue();
|
||||
} catch (TextException e){
|
||||
throw new TextException("Error reading property "+getFullBeanName(), e);
|
||||
}
|
||||
Object objValue;
|
||||
if (jsonValue == null) {
|
||||
objValue = null;
|
||||
} else {
|
||||
objValue = scalarType.jsonFromString(jsonValue, ctx.getValueAdapter());
|
||||
}
|
||||
setValue(bean, objValue);
|
||||
JsonToken event = ctx.nextToken();
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
setValue(bean, null);
|
||||
} else {
|
||||
// expect to read non-null json value
|
||||
Object objValue = scalarType.jsonRead(ctx, event);
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+51
@@ -0,0 +1,51 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
public class BeanPropertyAssocManyJsonHelp {
|
||||
|
||||
private final BeanPropertyAssocMany<?> many;
|
||||
|
||||
public BeanPropertyAssocManyJsonHelp(BeanPropertyAssocMany<?> many) {
|
||||
this.many = many;
|
||||
}
|
||||
|
||||
public void jsonRead(JsonParser parser, EntityBean parentBean) throws IOException {
|
||||
|
||||
if (!this.many.jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonToken event = parser.nextToken();
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
return;
|
||||
}
|
||||
if (JsonToken.START_ARRAY != event) {
|
||||
throw new JsonParseException("Unexpected token " + event + " - expecting start_array ", parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
Object collection = many.createEmpty(false);
|
||||
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
|
||||
do {
|
||||
EntityBean detailBean = (EntityBean) many.targetDescriptor.jsonRead(parser, many.name);
|
||||
if (detailBean == null) {
|
||||
// read the entire array
|
||||
break;
|
||||
}
|
||||
add.addBean(detailBean);
|
||||
|
||||
if (parentBean != null && many.childMasterProperty != null) {
|
||||
// bind detail bean back to master via mappedBy property
|
||||
many.childMasterProperty.setValue(detailBean, parentBean);
|
||||
}
|
||||
} while (true);
|
||||
|
||||
many.setValue(parentBean, collection);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -24,8 +25,8 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
/**
|
||||
* Property mapped to a joined bean.
|
||||
@@ -830,38 +831,40 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null){
|
||||
ctx.beginAssocOneIsNull(name);
|
||||
|
||||
} else {
|
||||
if (ctx.isParentBean(value)){
|
||||
// bi-directional and already rendered parent
|
||||
|
||||
} else {
|
||||
// Hmmm, not writing complex non-entity bean
|
||||
if (value instanceof EntityBean) {
|
||||
ctx.pushParentBean(bean);
|
||||
ctx.beginAssocOne(name);
|
||||
BeanDescriptor<?> refDesc = descriptor.getBeanDescriptor(value.getClass());
|
||||
refDesc.jsonWrite(ctx, (EntityBean)value);
|
||||
ctx.endAssocOne();
|
||||
ctx.popParentBean();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void jsonWrite(WriteJson writeJson, EntityBean bean) throws IOException {
|
||||
|
||||
if (!jsonSerialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
if (targetDescriptor != null) {
|
||||
T assocBean = targetDescriptor.jsonReadBean(ctx, name);
|
||||
setValue(bean, assocBean);
|
||||
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
writeJson.writeNull(name);
|
||||
|
||||
} else {
|
||||
if (writeJson.isParentBean(value)) {
|
||||
// bi-directional and already rendered parent
|
||||
|
||||
} else {
|
||||
// Hmmm, not writing complex non-entity bean
|
||||
if (value instanceof EntityBean) {
|
||||
writeJson.beginAssocOne(name, bean);
|
||||
BeanDescriptor<?> refDesc = descriptor.getBeanDescriptor(value.getClass());
|
||||
refDesc.jsonWrite(writeJson, (EntityBean) value, name);
|
||||
writeJson.endAssocOne();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonRead(JsonParser parser, EntityBean bean) throws IOException {
|
||||
if (jsonDeserialize && targetDescriptor != null) {
|
||||
T assocBean = targetDescriptor.jsonRead(parser, name);
|
||||
setValue(bean, assocBean);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReference(Object detailBean) {
|
||||
EntityBean eb = (EntityBean)detailBean;
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.text.json.EJson;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundType;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
|
||||
/**
|
||||
* Property mapped to an Immutable Compound Value Object.
|
||||
@@ -177,15 +180,32 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
Object valueObject = getValueIntercept(bean);
|
||||
compoundType.jsonWrite(ctx, valueObject, name);
|
||||
public void jsonWrite(WriteJson ctx, EntityBean bean) throws IOException {
|
||||
if (!jsonSerialize) {
|
||||
return;
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
ctx.writeNull(name);
|
||||
} else {
|
||||
compoundType.jsonWrite(ctx, value, name);
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
|
||||
Object objValue = compoundType.jsonRead(ctx);
|
||||
public void jsonRead(JsonParser ctx, EntityBean bean) throws IOException {
|
||||
|
||||
if (!jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object value = EJson.parse(ctx);
|
||||
if (value == null) {
|
||||
setValue(bean, null);
|
||||
} else {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String,Object> map = (Map<String,Object>)value;
|
||||
Object objValue = compoundType.jsonConvert(map);
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-11
@@ -1,19 +1,15 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertySimpleCollection;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
public class BeanPropertySimpleCollection<T> extends BeanPropertyAssocMany<T> {
|
||||
|
||||
private final ScalarType<T> collectionScalarType;
|
||||
|
||||
public BeanPropertySimpleCollection(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertySimpleCollection<T> deploy) {
|
||||
super(owner, descriptor, deploy);
|
||||
this.collectionScalarType = deploy.getCollectionScalarType();
|
||||
}
|
||||
public BeanPropertySimpleCollection(BeanDescriptorMap owner, BeanDescriptor<?> descriptor, DeployBeanPropertySimpleCollection<T> deploy) {
|
||||
super(owner, descriptor, deploy);
|
||||
}
|
||||
|
||||
public void initialise() {
|
||||
super.initialise();
|
||||
}
|
||||
|
||||
public void initialise() {
|
||||
super.initialise();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
@@ -12,7 +13,7 @@ import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanSet;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
|
||||
/**
|
||||
* Helper specifically for dealing with Sets.
|
||||
@@ -129,7 +130,7 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, String name, Object collection, boolean explicitInclude) {
|
||||
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
|
||||
Set<?> set;
|
||||
if (collection instanceof BeanCollection<?>){
|
||||
@@ -148,16 +149,11 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
set = (Set<?>)collection;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
ctx.beginAssocMany(name);
|
||||
ctx.writeStartArray(name);
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object detailBean = it.next();
|
||||
if (count++ > 0){
|
||||
ctx.appendComma();
|
||||
}
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)it.next());
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,9 @@ public abstract class DeployParser {
|
||||
sb.append(deployWord);
|
||||
if (pos < sourceLength) {
|
||||
sb.append(wordTerminator);
|
||||
if (wordTerminator == SINGLE_QUOTE) {
|
||||
readLiteral();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -8,33 +9,33 @@ import java.util.Set;
|
||||
*/
|
||||
public final class DeployPropertyParserMap extends DeployParser {
|
||||
|
||||
private final Map<String,String> map;
|
||||
private final Map<String, String> map;
|
||||
|
||||
public DeployPropertyParserMap(Map<String,String> map) {
|
||||
this.map = map;
|
||||
}
|
||||
public DeployPropertyParserMap(Map<String, String> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null for raw sql queries.
|
||||
*/
|
||||
public Set<String> getIncludes() {
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns null for raw sql queries.
|
||||
*/
|
||||
public Set<String> getIncludes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
public String convertWord() {
|
||||
String r = getDeployWord(word);
|
||||
return r == null ? word : r;
|
||||
}
|
||||
public String convertWord() {
|
||||
String r = getDeployWord(word);
|
||||
return r == null ? word : r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
|
||||
String deployExpr = map.get(expression);
|
||||
if (deployExpr == null) {
|
||||
return null;
|
||||
} else {
|
||||
return deployExpr;
|
||||
}
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
|
||||
String deployExpr = map.get(expression);
|
||||
if (deployExpr == null) {
|
||||
return null;
|
||||
} else {
|
||||
return deployExpr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
@@ -15,129 +13,113 @@ import com.avaje.ebeaninternal.util.DefaultExpressionRequest;
|
||||
|
||||
public class IntersectionRow {
|
||||
|
||||
private final String tableName;
|
||||
private final String tableName;
|
||||
|
||||
private final LinkedHashMap<String,Object> values = new LinkedHashMap<String,Object>();
|
||||
private final LinkedHashMap<String, Object> values = new LinkedHashMap<String, Object>();
|
||||
|
||||
private ArrayList<Object> excludeIds;
|
||||
private BeanDescriptor<?> excludeDescriptor;
|
||||
private ArrayList<Object> excludeIds;
|
||||
private BeanDescriptor<?> excludeDescriptor;
|
||||
|
||||
public IntersectionRow(String tableName){
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Id's to exclude. This is for deleting non-attached detail Id's.
|
||||
*/
|
||||
public void setExcludeIds(ArrayList<Object> excludeIds, BeanDescriptor<?> excludeDescriptor){
|
||||
this.excludeIds = excludeIds;
|
||||
this.excludeDescriptor = excludeDescriptor;
|
||||
}
|
||||
public IntersectionRow(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public void put(String key, Object value){
|
||||
values.put(key, value);
|
||||
}
|
||||
/**
|
||||
* Set Id's to exclude. This is for deleting non-attached detail Id's.
|
||||
*/
|
||||
public void setExcludeIds(ArrayList<Object> excludeIds, BeanDescriptor<?> excludeDescriptor) {
|
||||
this.excludeIds = excludeIds;
|
||||
this.excludeDescriptor = excludeDescriptor;
|
||||
}
|
||||
|
||||
public void put(String key, Object value) {
|
||||
values.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
public SqlUpdate createInsert(EbeanServer server){
|
||||
public SqlUpdate createInsert(EbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("insert into ").append(tableName).append(" (");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("insert into ").append(tableName).append(" (");
|
||||
|
||||
int count = 0;
|
||||
Iterator<Entry<String, Object>> it = values.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
if (count++ > 0){
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
sb.append(entry.getKey());
|
||||
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
|
||||
sb.append(") values (");
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i > 0){
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("?");
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDelete(EbeanServer server){
|
||||
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("delete from ").append(tableName).append(" where ");
|
||||
|
||||
int count = 0;
|
||||
Iterator<Entry<String, Object>> it = values.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
if (count++ > 0){
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
|
||||
sb.append(entry.getKey());
|
||||
sb.append(" = ?");
|
||||
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
if (excludeIds != null){
|
||||
IdInExpression idIn = new IdInExpression(excludeIds);
|
||||
|
||||
DefaultExpressionRequest er = new DefaultExpressionRequest(excludeDescriptor);
|
||||
idIn.addSqlNoAlias(er);
|
||||
idIn.addBindValues(er);
|
||||
|
||||
sb.append(" and not ( ");
|
||||
sb.append(er.getSql());
|
||||
sb.append(" ) ");
|
||||
|
||||
ArrayList<Object> bindValues = er.getBindValues();
|
||||
for (int i = 0; i < bindValues.size(); i++) {
|
||||
bindParams.setParameter(++count, bindValues.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDeleteChildren(EbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("delete from ").append(tableName).append(" where ");
|
||||
|
||||
int count = 0;
|
||||
Iterator<Entry<String, Object>> it = values.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
if (count++ > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
Map.Entry<String, Object> entry = it.next();
|
||||
|
||||
sb.append(entry.getKey());
|
||||
sb.append(" = ?");
|
||||
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
int count = 0;
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
if (count++ > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(entry.getKey());
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
|
||||
sb.append(") values (");
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append("?");
|
||||
}
|
||||
sb.append(")");
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDelete(EbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("delete from ").append(tableName).append(" where ");
|
||||
|
||||
int count = 0;
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
if (count++ > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(entry.getKey());
|
||||
sb.append(" = ?");
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
|
||||
if (excludeIds != null) {
|
||||
IdInExpression idIn = new IdInExpression(excludeIds);
|
||||
|
||||
DefaultExpressionRequest er = new DefaultExpressionRequest(excludeDescriptor);
|
||||
idIn.addSqlNoAlias(er);
|
||||
idIn.addBindValues(er);
|
||||
|
||||
sb.append(" and not ( ");
|
||||
sb.append(er.getSql());
|
||||
sb.append(" ) ");
|
||||
|
||||
ArrayList<Object> bindValues = er.getBindValues();
|
||||
for (int i = 0; i < bindValues.size(); i++) {
|
||||
bindParams.setParameter(++count, bindValues.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
|
||||
public SqlUpdate createDeleteChildren(EbeanServer server) {
|
||||
|
||||
BindParams bindParams = new BindParams();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("delete from ").append(tableName).append(" where ");
|
||||
|
||||
int count = 0;
|
||||
for (Map.Entry<String, Object> entry : values.entrySet()) {
|
||||
if (count++ > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
sb.append(entry.getKey());
|
||||
sb.append(" = ?");
|
||||
|
||||
bindParams.setParameter(count, entry.getValue());
|
||||
}
|
||||
|
||||
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,6 @@ import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
*/
|
||||
public final class TableJoin {
|
||||
|
||||
public static final String LEFT_OUTER = "left outer join";
|
||||
|
||||
public static final String JOIN = "join";
|
||||
|
||||
/**
|
||||
* Flag set when the imported key maps to the primary key. This occurs for
|
||||
* intersection tables (ManyToMany).
|
||||
|
||||
@@ -13,18 +13,17 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
|
||||
import com.avaje.ebeaninternal.server.persist.dmlbind.BindableRequest;
|
||||
import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
|
||||
/**
|
||||
* Imported Embedded id.
|
||||
*/
|
||||
public class ImportedIdEmbedded implements ImportedId {
|
||||
|
||||
final BeanPropertyAssoc<?> owner;
|
||||
private final BeanPropertyAssoc<?> owner;
|
||||
|
||||
final BeanPropertyAssocOne<?> foreignAssocOne;
|
||||
private final BeanPropertyAssocOne<?> foreignAssocOne;
|
||||
|
||||
final ImportedIdSimple[] imported;
|
||||
private final ImportedIdSimple[] imported;
|
||||
|
||||
public ImportedIdEmbedded(BeanPropertyAssoc<?> owner, BeanPropertyAssocOne<?> foreignAssocOne, ImportedIdSimple[] imported) {
|
||||
this.owner = owner;
|
||||
|
||||
+43
-33
@@ -6,13 +6,15 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -226,9 +228,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
boolean missingMethods = false;
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (!prop.isTransient()) {
|
||||
String m = "";
|
||||
if (prop.getReadMethod() == null) {
|
||||
@@ -704,10 +704,10 @@ public class DeployBeanDescriptor<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an Iterator of all BeanProperty.
|
||||
* Return a collection of all BeanProperty deployment information.
|
||||
*/
|
||||
public Iterator<DeployBeanProperty> propertiesAll() {
|
||||
return propMap.values().iterator();
|
||||
public Collection<DeployBeanProperty> propertiesAll() {
|
||||
return propMap.values();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -719,9 +719,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
boolean hasLazyFetch = false;
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop.isTransient()) {
|
||||
// ignore transient props etc
|
||||
} else if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
@@ -794,9 +792,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
ArrayList<DeployBeanProperty> list = new ArrayList<DeployBeanProperty>(2);
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop.isId()) {
|
||||
list.add(prop);
|
||||
}
|
||||
@@ -825,9 +821,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
ArrayList<DeployBeanPropertyAssocOne<?>> list = new ArrayList<DeployBeanPropertyAssocOne<?>>();
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
if (!prop.isEmbedded()) {
|
||||
list.add((DeployBeanPropertyAssocOne<?>) prop);
|
||||
@@ -846,9 +840,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
ArrayList<DeployBeanPropertyAssocMany<?>> list = new ArrayList<DeployBeanPropertyAssocMany<?>>();
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
list.add((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
@@ -866,13 +858,8 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
ArrayList<DeployBeanProperty> list = new ArrayList<DeployBeanProperty>();
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?>) {
|
||||
|
||||
} else {
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
|
||||
if (!prop.isId() && prop.isVersionColumn()) {
|
||||
list.add(prop);
|
||||
}
|
||||
@@ -889,13 +876,8 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
ArrayList<DeployBeanProperty> list = new ArrayList<DeployBeanProperty>();
|
||||
|
||||
Iterator<DeployBeanProperty> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?>) {
|
||||
|
||||
} else {
|
||||
for (DeployBeanProperty prop : propMap.values()) {
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?> == false) {
|
||||
if (!prop.isId()) {
|
||||
list.add(prop);
|
||||
}
|
||||
@@ -905,4 +887,32 @@ public class DeployBeanDescriptor<T> {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the mapping for class inheritance
|
||||
*/
|
||||
public void checkInheritanceMapping() {
|
||||
if (inheritInfo == null) {
|
||||
checkInheritance(getBeanType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check valid mapping annotations on the class hierarchy.
|
||||
*/
|
||||
private void checkInheritance(Class<?> beanType) {
|
||||
|
||||
Class<?> parent = beanType.getSuperclass();
|
||||
if (parent == null || Object.class.equals(parent)) {
|
||||
// all good
|
||||
return;
|
||||
}
|
||||
if (parent.isAnnotationPresent(Entity.class)) {
|
||||
String msg = "Checking "+getBeanType()+" and found "+parent+" that has @Entity annotation rather than MappedSuperclass?";
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
if (parent.isAnnotationPresent(MappedSuperclass.class)) {
|
||||
// continue checking
|
||||
checkInheritance(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,6 +217,9 @@ public class DeployBeanProperty {
|
||||
|
||||
private int sortOrder;
|
||||
|
||||
private boolean indexed;
|
||||
private String indexName;
|
||||
|
||||
public DeployBeanProperty(DeployBeanDescriptor<?> desc, Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
|
||||
this.desc = desc;
|
||||
this.propertyType = propertyType;
|
||||
@@ -930,4 +933,19 @@ public class DeployBeanProperty {
|
||||
return desc.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public void setIndexed(boolean indexed) {
|
||||
this.indexed = indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public void setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-9
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -76,18 +75,13 @@ public class DeployBeanPropertyLists {
|
||||
|
||||
this.propertyMap = new LinkedHashMap<String, BeanProperty>();
|
||||
|
||||
Iterator<DeployBeanProperty> deployIt = deploy.propertiesAll();
|
||||
while (deployIt.hasNext()) {
|
||||
DeployBeanProperty deployProp = deployIt.next();
|
||||
BeanProperty beanProp = createBeanProperty(owner, deployProp);
|
||||
for (DeployBeanProperty prop : deploy.propertiesAll()) {
|
||||
BeanProperty beanProp = createBeanProperty(owner, prop);
|
||||
propertyMap.put(beanProp.getName(), beanProp);
|
||||
}
|
||||
|
||||
Iterator<BeanProperty> it = propertyMap.values().iterator();
|
||||
|
||||
int order = 0;
|
||||
while (it.hasNext()) {
|
||||
BeanProperty prop = it.next();
|
||||
for (BeanProperty prop : propertyMap.values()) {
|
||||
prop.setDeployOrder(order++);
|
||||
allocateToList(prop);
|
||||
}
|
||||
|
||||
+18
-30
@@ -2,40 +2,28 @@ package com.avaje.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import com.avaje.ebeaninternal.server.deploy.ManyType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
public class DeployBeanPropertySimpleCollection<T> extends DeployBeanPropertyAssocMany<T> {
|
||||
|
||||
private final ScalarType<T> collectionScalarType;
|
||||
|
||||
public DeployBeanPropertySimpleCollection(DeployBeanDescriptor<?> desc, Class<T> targetType, ScalarType<T> scalarType, ManyType manyType) {
|
||||
super(desc, targetType, manyType);
|
||||
this.collectionScalarType = scalarType;
|
||||
this.modifyListenMode = ModifyListenMode.ALL;
|
||||
}
|
||||
public DeployBeanPropertySimpleCollection(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
|
||||
super(desc, targetType, manyType);
|
||||
this.modifyListenMode = ModifyListenMode.ALL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the scalarType of the collection elements.
|
||||
*/
|
||||
public ScalarType<T> getCollectionScalarType() {
|
||||
return collectionScalarType;
|
||||
}
|
||||
/**
|
||||
* Returns false as never a ManyToMany.
|
||||
*/
|
||||
@Override
|
||||
public boolean isManyToMany() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns false as never a ManyToMany.
|
||||
*/
|
||||
@Override
|
||||
public boolean isManyToMany() {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Returns true as always Unidirectional.
|
||||
*/
|
||||
@Override
|
||||
public boolean isUnidirectional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true as always Unidirectional.
|
||||
*/
|
||||
@Override
|
||||
public boolean isUnidirectional() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import java.util.ArrayList;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
/**
|
||||
@@ -19,205 +17,196 @@ import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
*/
|
||||
public class DeployTableJoin {
|
||||
|
||||
/**
|
||||
* Flag set when the imported key maps to the primary key.
|
||||
* This occurs for intersection tables (ManyToMany).
|
||||
*/
|
||||
private boolean importedPrimaryKey;
|
||||
|
||||
/**
|
||||
* The joined table.
|
||||
*/
|
||||
private String table;
|
||||
|
||||
/**
|
||||
* The type of join. LEFT OUTER etc.
|
||||
*/
|
||||
private SqlJoinType type = SqlJoinType.INNER;
|
||||
/**
|
||||
* Flag set when the imported key maps to the primary key. This occurs for intersection tables
|
||||
* (ManyToMany).
|
||||
*/
|
||||
private boolean importedPrimaryKey;
|
||||
|
||||
/**
|
||||
* The list of properties mapped to this joined table.
|
||||
*/
|
||||
private ArrayList<DeployBeanProperty> properties = new ArrayList<DeployBeanProperty>();
|
||||
/**
|
||||
* The joined table.
|
||||
*/
|
||||
private String table;
|
||||
|
||||
/**
|
||||
* The list of join column pairs. Used to generate the on clause.
|
||||
*/
|
||||
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<DeployTableJoinColumn>();
|
||||
/**
|
||||
* The type of join. LEFT OUTER etc.
|
||||
*/
|
||||
private SqlJoinType type = SqlJoinType.INNER;
|
||||
|
||||
/**
|
||||
* The persist cascade info.
|
||||
*/
|
||||
private BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
|
||||
|
||||
private InheritInfo inheritInfo;
|
||||
/**
|
||||
* The list of properties mapped to this joined table.
|
||||
*/
|
||||
private ArrayList<DeployBeanProperty> properties = new ArrayList<DeployBeanProperty>();
|
||||
|
||||
/**
|
||||
* Create a DeployTableJoin.
|
||||
*/
|
||||
public DeployTableJoin() {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + " " + table + " " + columns;
|
||||
/**
|
||||
* The list of join column pairs. Used to generate the on clause.
|
||||
*/
|
||||
private ArrayList<DeployTableJoinColumn> columns = new ArrayList<DeployTableJoinColumn>(4);
|
||||
|
||||
/**
|
||||
* The persist cascade info.
|
||||
*/
|
||||
private BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
|
||||
|
||||
private InheritInfo inheritInfo;
|
||||
|
||||
/**
|
||||
* Create a DeployTableJoin.
|
||||
*/
|
||||
public DeployTableJoin() {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return type + " " + table + " " + columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the imported foreign key maps to the primary key.
|
||||
*/
|
||||
public boolean isImportedPrimaryKey() {
|
||||
return importedPrimaryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag set when the imported key maps to the primary key. This occurs for intersection tables
|
||||
* (ManyToMany).
|
||||
*/
|
||||
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
|
||||
this.importedPrimaryKey = importedPrimaryKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the JoinOnPair have been set.
|
||||
*/
|
||||
public boolean hasJoinColumns() {
|
||||
return columns.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the persist info.
|
||||
*/
|
||||
public BeanCascadeInfo getCascadeInfo() {
|
||||
return cascadeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all the columns to this join potentially reversing the columns.
|
||||
*/
|
||||
public void setColumns(DeployTableJoinColumn[] cols, boolean reverse) {
|
||||
columns = new ArrayList<DeployTableJoinColumn>();
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
addJoinColumn(cols[i].copy(reverse));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the imported foreign key maps to the primary key.
|
||||
*/
|
||||
public boolean isImportedPrimaryKey() {
|
||||
return importedPrimaryKey;
|
||||
}
|
||||
/**
|
||||
* Add a join pair
|
||||
*/
|
||||
public void addJoinColumn(DeployTableJoinColumn pair) {
|
||||
columns.add(pair);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag set when the imported key maps to the primary key.
|
||||
* This occurs for intersection tables (ManyToMany).
|
||||
*/
|
||||
public void setImportedPrimaryKey(boolean importedPrimaryKey) {
|
||||
this.importedPrimaryKey = importedPrimaryKey;
|
||||
}
|
||||
/**
|
||||
* Add a JoinColumn
|
||||
* <p>
|
||||
* The order is generally true for OneToMany and false for ManyToOne relationships.
|
||||
* </p>
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
|
||||
if (!"".equals(jc.table())) {
|
||||
setTable(jc.table());
|
||||
}
|
||||
if (!"".equals(jc.name()) || !"".equals(jc.referencedColumnName())) {
|
||||
// only add the join column details when name or referencedColumnName is specified
|
||||
addJoinColumn(new DeployTableJoinColumn(order, jc, beanTable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the JoinOnPair have been set.
|
||||
*/
|
||||
public boolean hasJoinColumns() {
|
||||
return columns.size() > 0;
|
||||
/**
|
||||
* Add a JoinColumn array.
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn[] jcArray, BeanTable beanTable) {
|
||||
for (int i = 0; i < jcArray.length; i++) {
|
||||
addJoinColumn(order, jcArray[i], beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the persist info.
|
||||
*/
|
||||
public BeanCascadeInfo getCascadeInfo() {
|
||||
return cascadeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the join columns.
|
||||
*/
|
||||
public DeployTableJoinColumn[] columns() {
|
||||
return (DeployTableJoinColumn[]) columns.toArray(new DeployTableJoinColumn[columns.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy all the columns to this join potentially reversing the columns.
|
||||
*/
|
||||
public void setColumns(DeployTableJoinColumn[] cols, boolean reverse) {
|
||||
columns = new ArrayList<DeployTableJoinColumn>();
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
addJoinColumn(cols[i].copy(reverse));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a join pair
|
||||
*/
|
||||
public void addJoinColumn(DeployTableJoinColumn pair) {
|
||||
columns.add(pair);
|
||||
}
|
||||
/**
|
||||
* For secondary table joins returns the properties mapped to that table.
|
||||
*/
|
||||
public DeployBeanProperty[] properties() {
|
||||
return (DeployBeanProperty[]) properties.toArray(new DeployBeanProperty[properties.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JoinColumn
|
||||
* <p>
|
||||
* The order is generally true for OneToMany and false for ManyToOne relationships.
|
||||
* </p>
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
|
||||
if (!"".equals(jc.table())) {
|
||||
setTable(jc.table());
|
||||
}
|
||||
addJoinColumn(new DeployTableJoinColumn(order, jc, beanTable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a JoinColumn array.
|
||||
*/
|
||||
public void addJoinColumn(boolean order, JoinColumn[] jcArray, BeanTable beanTable) {
|
||||
for (int i = 0; i < jcArray.length; i++) {
|
||||
addJoinColumn(order, jcArray[i], beanTable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the join columns.
|
||||
*/
|
||||
public DeployTableJoinColumn[] columns() {
|
||||
return (DeployTableJoinColumn[])columns.toArray(new DeployTableJoinColumn[columns.size()]);
|
||||
}
|
||||
/**
|
||||
* Return the joined table name.
|
||||
*/
|
||||
public String getTable() {
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* For secondary table joins returns the properties mapped to that table.
|
||||
*/
|
||||
public DeployBeanProperty[] properties() {
|
||||
return (DeployBeanProperty[])properties.toArray(new DeployBeanProperty[properties.size()]);
|
||||
}
|
||||
/**
|
||||
* set the joined table name.
|
||||
*/
|
||||
public void setTable(String table) {
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the joined table name.
|
||||
*/
|
||||
public String getTable() {
|
||||
return table;
|
||||
}
|
||||
/**
|
||||
* Return the type of join. LEFT OUTER JOIN etc.
|
||||
*/
|
||||
public SqlJoinType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the joined table name.
|
||||
*/
|
||||
public void setTable(String table) {
|
||||
this.table = table;
|
||||
}
|
||||
/**
|
||||
* Return true if this join is a left outer join.
|
||||
*/
|
||||
public boolean isOuterJoin() {
|
||||
return type == SqlJoinType.OUTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of join. LEFT OUTER JOIN etc.
|
||||
*/
|
||||
public SqlJoinType getType() {
|
||||
return type;
|
||||
}
|
||||
public void setType(SqlJoinType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this join is a left outer join.
|
||||
*/
|
||||
public boolean isOuterJoin() {
|
||||
return type == SqlJoinType.OUTER;
|
||||
}
|
||||
|
||||
private void setType(SqlJoinType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type of join.
|
||||
*/
|
||||
public void setType(String joinType) {
|
||||
joinType = joinType.toUpperCase();
|
||||
if (joinType.equalsIgnoreCase(TableJoin.JOIN)) {
|
||||
type = SqlJoinType.INNER;
|
||||
} else if (joinType.indexOf("LEFT") > -1) {
|
||||
type = SqlJoinType.OUTER;
|
||||
} else if (joinType.indexOf("OUTER") > -1) {
|
||||
type = SqlJoinType.OUTER;
|
||||
} else if (joinType.indexOf("INNER") > -1) {
|
||||
type = SqlJoinType.INNER;
|
||||
} else {
|
||||
throw new RuntimeException(Message.msg("join.type.unknown", joinType));
|
||||
}
|
||||
}
|
||||
|
||||
public DeployTableJoin createInverse(String tableName) {
|
||||
|
||||
DeployTableJoin inverse = new DeployTableJoin();
|
||||
public DeployTableJoin createInverse(String tableName) {
|
||||
|
||||
return copyTo(inverse, true, tableName);
|
||||
DeployTableJoin inverse = new DeployTableJoin();
|
||||
return copyInternal(inverse, true, tableName, true);
|
||||
}
|
||||
|
||||
public DeployTableJoin copyTo(DeployTableJoin destJoin, boolean reverse, String tableName) {
|
||||
return copyInternal(destJoin, reverse, tableName, true);
|
||||
}
|
||||
|
||||
public DeployTableJoin copyWithoutType(DeployTableJoin destJoin, boolean reverse, String tableName) {
|
||||
return copyInternal(destJoin, reverse, tableName, false);
|
||||
}
|
||||
|
||||
private DeployTableJoin copyInternal(DeployTableJoin destJoin, boolean reverse, String tableName, boolean withType) {
|
||||
|
||||
destJoin.setTable(tableName);
|
||||
if (withType) {
|
||||
destJoin.setType(type);
|
||||
}
|
||||
|
||||
public DeployTableJoin copyTo(DeployTableJoin destJoin, boolean reverse, String tableName) {
|
||||
|
||||
destJoin.setTable(tableName);
|
||||
destJoin.setType(type);
|
||||
destJoin.setColumns(columns(), reverse);
|
||||
|
||||
return destJoin;
|
||||
}
|
||||
destJoin.setColumns(columns(), reverse);
|
||||
|
||||
public InheritInfo getInheritInfo() {
|
||||
return inheritInfo;
|
||||
}
|
||||
return destJoin;
|
||||
}
|
||||
|
||||
public void setInheritInfo(InheritInfo inheritInfo) {
|
||||
this.inheritInfo = inheritInfo;
|
||||
}
|
||||
public InheritInfo getInheritInfo() {
|
||||
return inheritInfo;
|
||||
}
|
||||
|
||||
public void setInheritInfo(InheritInfo inheritInfo) {
|
||||
this.inheritInfo = inheritInfo;
|
||||
}
|
||||
}
|
||||
|
||||
+6
-10
@@ -1,7 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinColumns;
|
||||
import javax.persistence.JoinTable;
|
||||
@@ -18,12 +16,12 @@ import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
/**
|
||||
* Read the deployment annotation for Assoc Many beans.
|
||||
@@ -44,9 +42,7 @@ public class AnnotationAssocManys extends AnnotationParser {
|
||||
* Parse the annotations.
|
||||
*/
|
||||
public void parse() {
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
read((DeployBeanPropertyAssocMany<?>) prop);
|
||||
}
|
||||
@@ -160,7 +156,7 @@ public class AnnotationAssocManys extends AnnotationParser {
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
destJoin.addJoinColumn(false, joinTable.inverseJoinColumns(), prop.getBeanTable());
|
||||
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
|
||||
// reverse join from dest back to intersection
|
||||
DeployTableJoin inverseDest = destJoin.createInverse(intTableName);
|
||||
@@ -216,7 +212,7 @@ public class AnnotationAssocManys extends AnnotationParser {
|
||||
intTableName = getM2MJoinTableName(localTable, otherTable);
|
||||
|
||||
intJoin.setTable(intTableName);
|
||||
intJoin.setType(TableJoin.LEFT_OUTER);
|
||||
intJoin.setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
DeployTableJoin destJoin = prop.getTableJoin();
|
||||
@@ -282,7 +278,7 @@ public class AnnotationAssocManys extends AnnotationParser {
|
||||
manyProp.setManyToMany(true);
|
||||
manyProp.setModifyListenMode(ModifyListenMode.ALL);
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
private void readToOne(OneToMany propAnn, DeployBeanPropertyAssocMany<?> manyProp) {
|
||||
@@ -307,7 +303,7 @@ public class AnnotationAssocManys extends AnnotationParser {
|
||||
}
|
||||
|
||||
manyProp.setBeanTable(assoc);
|
||||
manyProp.getTableJoin().setType(TableJoin.LEFT_OUTER);
|
||||
manyProp.getTableJoin().setType(SqlJoinType.OUTER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.Column;
|
||||
@@ -19,10 +18,10 @@ import com.avaje.ebean.annotation.Where;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanTable;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
/**
|
||||
* Read the deployment annotations for Associated One beans.
|
||||
@@ -44,9 +43,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
readAssocOne((DeployBeanPropertyAssocOne<?>) prop);
|
||||
}
|
||||
@@ -99,7 +96,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
if (notNull != null) {
|
||||
prop.setNullable(false);
|
||||
// overrides optional attribute of ManyToOne etc
|
||||
prop.getTableJoin().setType(TableJoin.JOIN);
|
||||
prop.getTableJoin().setType(SqlJoinType.INNER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +1,21 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import com.avaje.ebean.annotation.CreatedTimestamp;
|
||||
import com.avaje.ebean.annotation.EmbeddedColumns;
|
||||
import com.avaje.ebean.annotation.Encrypted;
|
||||
import com.avaje.ebean.annotation.Expose;
|
||||
import com.avaje.ebean.annotation.Formula;
|
||||
import com.avaje.ebean.annotation.UpdatedTimestamp;
|
||||
import com.avaje.ebean.annotation.*;
|
||||
import com.avaje.ebean.config.EncryptDeploy;
|
||||
import com.avaje.ebean.config.EncryptDeploy.Mode;
|
||||
import com.avaje.ebean.config.GlobalProperties;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncrypt;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
|
||||
@@ -66,7 +47,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
|
||||
if (GlobalProperties.getBoolean("ebean.lobEagerFetch", false)) {
|
||||
defaultLobFetchType = FetchType.EAGER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,15 +55,12 @@ public class AnnotationFields extends AnnotationParser {
|
||||
*/
|
||||
public void parse() {
|
||||
|
||||
Iterator<DeployBeanProperty> it = descriptor.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : descriptor.propertiesAll()) {
|
||||
if (prop instanceof DeployBeanPropertyAssoc<?>) {
|
||||
readAssocOne(prop);
|
||||
} else {
|
||||
readField(prop);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +86,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (prop.isId() && !prop.isEmbedded()) {
|
||||
prop.setEmbedded(true);
|
||||
}
|
||||
readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>)prop);
|
||||
readEmbeddedAttributeOverrides((DeployBeanPropertyAssocOne<?>) prop);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +131,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (id != null) {
|
||||
readId(id, prop);
|
||||
}
|
||||
|
||||
|
||||
// determine the JDBC type using Lob/Temporal
|
||||
// otherwise based on the property Class
|
||||
Lob lob = get(prop, Lob.class);
|
||||
@@ -203,9 +181,9 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (notNull != null && isNotNullOnAllValidationGroups(notNull.groups())) {
|
||||
// Not null on all validation groups so enable
|
||||
// DDL generation of Not Null Constraint
|
||||
prop.setNullable(false);
|
||||
prop.setNullable(false);
|
||||
}
|
||||
|
||||
|
||||
Size size = get(prop, Size.class);
|
||||
if (size != null) {
|
||||
if (size.max() < Integer.MAX_VALUE) {
|
||||
@@ -233,7 +211,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
|
||||
} else {
|
||||
throw new RuntimeException("Can't use EmbeddedColumns on ScalarType "
|
||||
+ prop.getFullBeanName());
|
||||
+ prop.getFullBeanName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +228,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (!prop.isTransient()) {
|
||||
|
||||
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(),
|
||||
prop.getDbColumn());
|
||||
prop.getDbColumn());
|
||||
if (encryptDeploy == null || encryptDeploy.getMode().equals(Mode.MODE_ANNOTATION)) {
|
||||
Encrypted encrypted = get(prop, Encrypted.class);
|
||||
if (encrypted != null) {
|
||||
@@ -261,6 +239,20 @@ public class AnnotationFields extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
Index index = get(prop, Index.class);
|
||||
if (index != null) {
|
||||
if(hasRelationshipItem(prop)) {
|
||||
throw new RuntimeException("Can't use Index on foreign key relationships.");
|
||||
}
|
||||
prop.setIndexed(true);
|
||||
prop.setIndexName(index.value());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasRelationshipItem(DeployBeanProperty prop) {
|
||||
return get(prop, OneToMany.class) != null ||
|
||||
get(prop, ManyToOne.class) != null ||
|
||||
get(prop, OneToOne.class) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -317,7 +309,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private ScalarTypeEncryptedWrapper<?> createScalarType(DeployBeanProperty prop, ScalarType<?> st) {
|
||||
|
||||
// Use Java Encryptor wrapping the logical scalar type
|
||||
|
||||
@@ -9,34 +9,33 @@ import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
|
||||
*/
|
||||
public class AnnotationSql extends AnnotationParser {
|
||||
|
||||
public AnnotationSql(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
public AnnotationSql(DeployBeanInfo<?> info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = cls.getAnnotation(Sql.class);
|
||||
if (sql != null){
|
||||
setSql(sql);
|
||||
}
|
||||
|
||||
|
||||
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
|
||||
if (sqlSelect != null){
|
||||
setSqlSelect(sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSql(Sql sql) {
|
||||
SqlSelect[] select = sql.select();
|
||||
for (int i = 0; i < select.length; i++) {
|
||||
setSqlSelect(select[i]);
|
||||
}
|
||||
}
|
||||
public void parse() {
|
||||
Class<?> cls = descriptor.getBeanType();
|
||||
Sql sql = cls.getAnnotation(Sql.class);
|
||||
if (sql != null) {
|
||||
setSql(sql);
|
||||
}
|
||||
|
||||
private void setSqlSelect(SqlSelect sqlSelect) {
|
||||
SqlSelect sqlSelect = cls.getAnnotation(SqlSelect.class);
|
||||
if (sqlSelect != null) {
|
||||
setSqlSelect(sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
|
||||
descriptor.add(rawSqlMeta);
|
||||
}
|
||||
private void setSql(Sql sql) {
|
||||
SqlSelect[] select = sql.select();
|
||||
for (int i = 0; i < select.length; i++) {
|
||||
setSqlSelect(select[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSqlSelect(SqlSelect sqlSelect) {
|
||||
|
||||
DRawSqlMeta rawSqlMeta = new DRawSqlMeta(sqlSelect);
|
||||
descriptor.add(rawSqlMeta);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@ package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
import com.avaje.ebeaninternal.server.query.SqlJoinType;
|
||||
|
||||
/**
|
||||
* Wraps information about a bean during deployment parsing.
|
||||
@@ -58,7 +58,7 @@ public class DeployBeanInfo<T> {
|
||||
if (tableJoin == null) {
|
||||
tableJoin = new DeployTableJoin();
|
||||
tableJoin.setTable(tableName);
|
||||
tableJoin.setType(TableJoin.JOIN);
|
||||
tableJoin.setType(SqlJoinType.INNER);
|
||||
descriptor.addTableJoin(tableJoin);
|
||||
|
||||
tableJoinMap.put(key, tableJoin);
|
||||
@@ -71,13 +71,8 @@ public class DeployBeanInfo<T> {
|
||||
*/
|
||||
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
|
||||
|
||||
String joinType = TableJoin.JOIN;
|
||||
if (outerJoin){// && util.isUseOneToOneOptional()) {
|
||||
joinType = TableJoin.LEFT_OUTER;
|
||||
}
|
||||
|
||||
DeployTableJoin tableJoin = beanProp.getTableJoin();
|
||||
tableJoin.setType(joinType);
|
||||
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+17
-9
@@ -5,11 +5,14 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.annotation.ColumnHstore;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.deploy.DetermineManyType;
|
||||
@@ -26,9 +29,6 @@ import com.avaje.ebeaninternal.server.type.ScalarTypePostgresHstore;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.reflect.CheckImmutableResponse;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Create the properties for a bean.
|
||||
* <p>
|
||||
@@ -58,10 +58,7 @@ public class DeployCreateProperties {
|
||||
desc.sortProperties();
|
||||
|
||||
// check the transient properties...
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
for (DeployBeanProperty prop : desc.propertiesAll()) {
|
||||
if (prop.isTransient()) {
|
||||
if (prop.getWriteMethod() == null || prop.getReadMethod() == null) {
|
||||
// Typically a helper method ... this is expected
|
||||
@@ -264,7 +261,7 @@ public class DeployCreateProperties {
|
||||
try {
|
||||
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, scalarType, manyType);
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
logger.debug("expected non-scalar type" + e.getMessage());
|
||||
@@ -277,6 +274,17 @@ public class DeployCreateProperties {
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
|
||||
ManyToOne manyToOne = field.getAnnotation(ManyToOne.class);
|
||||
|
||||
if (manyToOne != null){
|
||||
Class<?> tt = manyToOne.targetEntity();
|
||||
|
||||
if (tt != null && !tt.equals(void.class)){
|
||||
propertyType = tt;
|
||||
logger.debug("target type" + tt);
|
||||
}
|
||||
}
|
||||
Class<?> innerType = propertyType;
|
||||
|
||||
String specialTypeKey = getSpecialScalarType(field);
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.sql.Types;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -51,9 +50,7 @@ public class DeployInherit {
|
||||
private void findInheritClasses(List<Class<?>> entityList) {
|
||||
|
||||
// go through each class and initialise the info object...
|
||||
Iterator<Class<?>> it = entityList.iterator();
|
||||
while (it.hasNext()) {
|
||||
Class<?> cls = (Class<?>) it.next();
|
||||
for (Class<?> cls : entityList) {
|
||||
if (isInheritanceClass(cls)) {
|
||||
DeployInheritInfo info = createInfo(cls);
|
||||
deployMap.put(cls, info);
|
||||
@@ -62,9 +59,8 @@ public class DeployInherit {
|
||||
}
|
||||
|
||||
private void buildDeployTree() {
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo info = it.next();
|
||||
|
||||
for (DeployInheritInfo info : deployMap.values()) {
|
||||
if (!info.isRoot()) {
|
||||
DeployInheritInfo parent = getInfo(info.getParent());
|
||||
parent.addChild(info);
|
||||
@@ -74,19 +70,15 @@ public class DeployInherit {
|
||||
|
||||
private void buildFinalTree() {
|
||||
|
||||
Iterator<DeployInheritInfo> it = deployMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo deploy = it.next();
|
||||
for (DeployInheritInfo deploy : deployMap.values()) {
|
||||
if (deploy.isRoot()) {
|
||||
// build tree top down...
|
||||
createFinalInfo(null, null, deploy);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent,
|
||||
DeployInheritInfo deploy) {
|
||||
private InheritInfo createFinalInfo(InheritInfo root, InheritInfo parent, DeployInheritInfo deploy) {
|
||||
|
||||
InheritInfo node = new InheritInfo(root, parent, deploy);
|
||||
if (parent != null) {
|
||||
@@ -99,12 +91,7 @@ public class DeployInherit {
|
||||
}
|
||||
|
||||
// buildFinalChildren(root, child, deploy);
|
||||
|
||||
Iterator<DeployInheritInfo> it = deploy.children();
|
||||
|
||||
while (it.hasNext()) {
|
||||
DeployInheritInfo childDeploy = it.next();
|
||||
|
||||
for (DeployInheritInfo childDeploy : deploy.children()) {
|
||||
createFinalInfo(root, node, childDeploy);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
@@ -80,8 +79,8 @@ public class DeployInheritInfo {
|
||||
/**
|
||||
* Return the child nodes.
|
||||
*/
|
||||
public Iterator<DeployInheritInfo> children() {
|
||||
return children.iterator();
|
||||
public List<DeployInheritInfo> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -29,9 +27,7 @@ class AllEqualsExpression implements SpiExpression {
|
||||
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
if (propMap != null) {
|
||||
Iterator<String> it = propMap.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
String propertyName = it.next();
|
||||
for (String propertyName : propMap.keySet()) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(name(propertyName));
|
||||
if (elProp != null && elProp.containsMany()) {
|
||||
manyWhereJoin.add(elProp);
|
||||
@@ -45,9 +41,7 @@ class AllEqualsExpression implements SpiExpression {
|
||||
if (propMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Iterator<Object> it = propMap.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
Object value = it.next();
|
||||
for (Object value : propMap.values()) {
|
||||
if (value != null) {
|
||||
request.addBindValue(value);
|
||||
} else {
|
||||
@@ -64,12 +58,9 @@ class AllEqualsExpression implements SpiExpression {
|
||||
|
||||
request.append("(");
|
||||
|
||||
Set<Entry<String, Object>> entries = propMap.entrySet();
|
||||
Iterator<Entry<String, Object>> it = entries.iterator();
|
||||
|
||||
int count = 0;
|
||||
while (it.hasNext()) {
|
||||
Map.Entry<java.lang.String, java.lang.Object> entry = it.next();
|
||||
for (Map.Entry<String,Object> entry : propMap.entrySet()) {
|
||||
|
||||
Object value = entry.getValue();
|
||||
String propName = entry.getKey();
|
||||
|
||||
|
||||
+2
-5
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.avaje.ebean.ExampleExpression;
|
||||
import com.avaje.ebean.LikeType;
|
||||
@@ -207,10 +206,8 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
OrmQueryRequest<?> r = (OrmQueryRequest<?>) request;
|
||||
BeanDescriptor<?> beanDescriptor = r.getBeanDescriptor();
|
||||
|
||||
Iterator<BeanProperty> propIter = beanDescriptor.propertiesAll();
|
||||
|
||||
while (propIter.hasNext()) {
|
||||
BeanProperty beanProperty = propIter.next();
|
||||
for (BeanProperty beanProperty : beanDescriptor.propertiesAll()) {
|
||||
|
||||
String propName = beanProperty.getName();
|
||||
Object value = beanProperty.getValue(entity);
|
||||
|
||||
|
||||
@@ -5,18 +5,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.Expression;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.FutureIds;
|
||||
import com.avaje.ebean.FutureList;
|
||||
import com.avaje.ebean.FutureRowCount;
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagedList;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
@@ -206,6 +197,11 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
throw new RuntimeException("filterMany not allowed on Junction expression list");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> apply(PathProperties pathProperties) {
|
||||
return exprList.apply(pathProperties);
|
||||
}
|
||||
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return exprList.findFutureIds();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,8 @@ class LikeExpression extends AbstractExpression {
|
||||
if (type.equals(LikeType.EQUAL_TO)) {
|
||||
request.append(" = ? ");
|
||||
} else {
|
||||
request.append(" like ? ");
|
||||
// append db platform like clause
|
||||
request.appendLike();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user