mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#716 - Remove createNamedQuery() and createQuery(Class<T> beanType, String query) ... use criteria API, query beans and RawSql
This commit is contained in:
@@ -932,19 +932,6 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().createSqlQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named sql query.
|
||||
* <p>
|
||||
* The query statement will be defined in a deployment orm xml file.
|
||||
* </p>
|
||||
*
|
||||
* @param namedQuery
|
||||
* the name of the query
|
||||
*/
|
||||
public static SqlQuery createNamedSqlQuery(String namedQuery) {
|
||||
return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sql update for executing native dml statements.
|
||||
* <p>
|
||||
@@ -954,10 +941,6 @@ public final class Ebean {
|
||||
* <p>
|
||||
* See {@link SqlUpdate} for example usage.
|
||||
* </p>
|
||||
* <p>
|
||||
* Where possible it would be expected practice to put the statement in a orm
|
||||
* xml file (named update) and use {@link #createNamedSqlUpdate(String)} .
|
||||
* </p>
|
||||
*/
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return serverMgr.getDefaultServer().createSqlUpdate(sql);
|
||||
@@ -972,144 +955,6 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().createCallableSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named sql update.
|
||||
* <p>
|
||||
* The statement (an Insert Update or Delete statement) will be defined in a
|
||||
* deployment orm xml file.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Use a namedQuery
|
||||
* UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count");
|
||||
*
|
||||
* update.setParameter("count", 1);
|
||||
* update.setParameter("topicId", 50);
|
||||
*
|
||||
* int modifiedCount = update.execute();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
|
||||
return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a named Query that will have defined fetch paths, predicates etc.
|
||||
* <p>
|
||||
* The query is created from a statement that will be defined in a deployment
|
||||
* orm xml file or NamedQuery annotations. The query will typically already
|
||||
* define fetch paths, predicates, order by clauses etc so often you will just
|
||||
* need to bind required parameters and then execute the query.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example
|
||||
* Query<Order> query = Ebean.createNamedQuery(Order.class, "new.for.customer");
|
||||
* query.setParameter("customerId", 23);
|
||||
* List<Order> newOrders = query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param beanType
|
||||
* the class of entity to be fetched
|
||||
* @param namedQuery
|
||||
* the name of the query
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query using the query language.
|
||||
* <p>
|
||||
* Note that you are allowed to add additional clauses using where() as well
|
||||
* as use fetch() and setOrderBy() after the query has been created.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that this method signature used to map to named queries and that has
|
||||
* moved to {@link #createNamedQuery(Class, String)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String q = "find order fetch details where status = :st";
|
||||
*
|
||||
* List<Order> newOrders = Ebean.>findOrder.class, q)
|
||||
* .setParameter("st", Order.Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param query
|
||||
* the object query
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType, String query) {
|
||||
return serverMgr.getDefaultServer().createQuery(beanType, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named orm update. The update statement is specified via the
|
||||
* NamedUpdate annotation.
|
||||
* <p>
|
||||
* The orm update differs from the SqlUpdate in that it uses the bean name and
|
||||
* bean property names rather than table and column names.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that named update statements can be specified in raw sql (with column
|
||||
* and table names) or using bean name and bean property names. This can be
|
||||
* specified with the isSql flag.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example named updates:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* package app.data;
|
||||
*
|
||||
* import ...
|
||||
*
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate( name = "setTitle",
|
||||
* isSql = false,
|
||||
* notifyCache = false,
|
||||
* update = "update topic set title = :title, postCount = :postCount where id = :id"),
|
||||
* @NamedUpdate( name = "setPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update f_topic set post_count = :postCount where id = :id"),
|
||||
* @NamedUpdate( name = "incrementPostCount",
|
||||
* notifyCache = false,
|
||||
* isSql = false,
|
||||
* update = "update Topic set postCount = postCount + 1 where id = :id") })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* public class Topic { ...
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example using a named update:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Update<Topic> update = Ebean.createNamedUpdate(Topic.class, "setPostCount");
|
||||
* update.setParameter("postCount", 10);
|
||||
* update.setParameter("id", 3);
|
||||
*
|
||||
* int rows = update.execute();
|
||||
* System.out.println("rows updated: " + rows);
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) {
|
||||
|
||||
return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a orm update where you will supply the insert/update or delete
|
||||
* statement (rather than using a named one that is already defined using the
|
||||
|
||||
@@ -179,52 +179,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> CsvReader<T> createCsvReader(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Return a named Query that will have defined fetch paths, predicates etc.
|
||||
* <p>
|
||||
* The query is created from a statement that will be defined in a deployment
|
||||
* orm xml file or NamedQuery annotations. The query will typically already
|
||||
* define fetch paths, predicates, order by clauses etc so often you will just
|
||||
* need to bind required parameters and then execute the query.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example
|
||||
* Query<Order> query = ebeanServer.createNamedQuery(Order.class, "new.for.customer");
|
||||
* query.setParameter("customerId", 23);
|
||||
* List<Order> newOrders = query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
|
||||
|
||||
/**
|
||||
* Create a query using the query language.
|
||||
* <p>
|
||||
* Note that you are allowed to add additional clauses using where() as well
|
||||
* as use fetch() and setOrderBy() after the query has been created.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that this method signature used to map to named queries and that has
|
||||
* moved to {@link #createNamedQuery(Class, String)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* EbeanServer ebeanServer = ... ;
|
||||
* String q = "find order fetch details where status = :st";
|
||||
*
|
||||
* List<Order> newOrders
|
||||
* = ebeanServer.createQuery(Order.class, q)
|
||||
* .setParameter("st", Order.Status.NEW)
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*
|
||||
* @param query
|
||||
* the object query
|
||||
*/
|
||||
<T> Query<T> createQuery(Class<T> beanType, String query);
|
||||
|
||||
/**
|
||||
* Create a query for an entity bean and synonym for {@link #find(Class)}.
|
||||
*
|
||||
@@ -344,62 +298,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> void sort(List<T> list, String sortByClause);
|
||||
|
||||
/**
|
||||
* Create a named orm update. The update statement is specified via the
|
||||
* NamedUpdate annotation.
|
||||
* <p>
|
||||
* The orm update differs from the SqlUpdate in that it uses the bean name and
|
||||
* bean property names rather than table and column names.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that named update statements can be specified in raw sql (with column
|
||||
* and table names) or using bean name and bean property names. This can be
|
||||
* specified with the isSql flag.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example named updates:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* package app.data;
|
||||
*
|
||||
* import ...
|
||||
*
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate( name = "setTitle",
|
||||
* isSql = false,
|
||||
* notifyCache = false,
|
||||
* update = "update topic set title = :title, postCount = :postCount where id = :id"),
|
||||
* @NamedUpdate( name = "setPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update f_topic set post_count = :postCount where id = :id"),
|
||||
* @NamedUpdate( name = "incrementPostCount",
|
||||
* notifyCache = false,
|
||||
* isSql = false,
|
||||
* update = "update Topic set postCount = postCount + 1 where id = :id") })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* public class Topic { ...
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example using a named update:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Update<Topic> update = ebeanServer.createNamedUpdate(Topic.class, "setPostCount");
|
||||
* update.setParameter("postCount", 10);
|
||||
* update.setParameter("id", 3);
|
||||
*
|
||||
* int rows = update.execute();
|
||||
* System.out.println("rows updated: " + rows);
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate);
|
||||
|
||||
/**
|
||||
* Create a orm update where you will supply the insert/update or delete
|
||||
* statement (rather than using a named one that is already defined using the
|
||||
@@ -441,17 +339,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
SqlQuery createSqlQuery(String sql);
|
||||
|
||||
/**
|
||||
* Create a named sql query.
|
||||
* <p>
|
||||
* The query statement will be defined in a deployment orm xml file.
|
||||
* </p>
|
||||
*
|
||||
* @param namedQuery
|
||||
* the name of the query
|
||||
*/
|
||||
SqlQuery createNamedSqlQuery(String namedQuery);
|
||||
|
||||
/**
|
||||
* Create a sql update for executing native dml statements.
|
||||
* <p>
|
||||
@@ -461,10 +348,6 @@ public interface EbeanServer {
|
||||
* <p>
|
||||
* See {@link SqlUpdate} for example usage.
|
||||
* </p>
|
||||
* <p>
|
||||
* Where possible it would be expected practice to put the statement in a orm
|
||||
* xml file (named update) and use {@link #createNamedSqlUpdate(String)} .
|
||||
* </p>
|
||||
*/
|
||||
SqlUpdate createSqlUpdate(String sql);
|
||||
|
||||
@@ -473,27 +356,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
CallableSql createCallableSql(String callableSql);
|
||||
|
||||
/**
|
||||
* Create a named sql update.
|
||||
* <p>
|
||||
* The statement (an Insert Update or Delete statement) will be defined in a
|
||||
* deployment orm xml file.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Use a namedQuery
|
||||
* UpdateSql update = Ebean.createNamedSqlUpdate("update.topic.count");
|
||||
*
|
||||
* update.setParameter("count", 1);
|
||||
* update.setParameter("topicId", 50);
|
||||
*
|
||||
* int modifiedCount = update.execute();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SqlUpdate createNamedSqlUpdate(String namedQuery);
|
||||
|
||||
/**
|
||||
* Register a TransactionCallback on the currently active transaction.
|
||||
* <p/>
|
||||
|
||||
@@ -843,15 +843,6 @@ public abstract class Model {
|
||||
return query().setId(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new query using the OQL.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#createQuery(Class, String)}
|
||||
*/
|
||||
public Query<T> setQuery(String oql) {
|
||||
return db().createQuery(type, oql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new query based on the <code>RawSql</code>.
|
||||
* <p>
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
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 Update statement for a particular entity bean type.
|
||||
* <p>
|
||||
* The update can either be a sql insert,update or delete statement with tables
|
||||
* and columns etc or the equivalent statement but with table names and columns
|
||||
* expressed as bean types and bean properties.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NamedUpdate {
|
||||
|
||||
/**
|
||||
* The name of the update.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* The insert, update or delete statement.
|
||||
*/
|
||||
String update();
|
||||
|
||||
/**
|
||||
* Set this to false if you do not want the cache to be notified. If true the
|
||||
* cache will invalidate appropriate objects from the cache (after a
|
||||
* successful transaction commit).
|
||||
*/
|
||||
boolean notifyCache() default true;
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* Holds an array of named Update statements for a particular entity bean type.
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NamedUpdates {
|
||||
|
||||
/**
|
||||
* An array of named updates.
|
||||
*/
|
||||
NamedUpdate[] value();
|
||||
|
||||
}
|
||||
@@ -436,11 +436,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
void setUsageProfiling(boolean usageProfiling);
|
||||
|
||||
/**
|
||||
* Return the query name.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Prepare the query which prepares sub-query expressions and calculates
|
||||
* and returns the query plan key.
|
||||
@@ -464,12 +459,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
HashQuery queryHash();
|
||||
|
||||
/**
|
||||
* Return true if this is a query based on a SqlSelect rather than
|
||||
* generated.
|
||||
*/
|
||||
boolean isSqlSelect();
|
||||
|
||||
/**
|
||||
* Return true if this is a RawSql query.
|
||||
*/
|
||||
|
||||
@@ -114,8 +114,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
SpiBackgroundExecutor executor = createBackgroundExecutor(serverConfig);
|
||||
ServerCacheManager cacheManager = getCacheManager(online, serverConfig, executor);
|
||||
|
||||
XmlConfig xmlConfig = new XmlConfigLoader(null).load();
|
||||
InternalConfiguration c = new InternalConfiguration(xmlConfig, clusterManager, cacheManager, executor, serverConfig, bootupClasses);
|
||||
InternalConfiguration c = new InternalConfiguration(clusterManager, cacheManager, executor, serverConfig, bootupClasses);
|
||||
|
||||
DefaultServer server = new DefaultServer(c, cacheManager);
|
||||
|
||||
|
||||
@@ -38,9 +38,6 @@ import com.avaje.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.DNativeQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.el.ElFilter;
|
||||
import com.avaje.ebeaninternal.server.lib.ShutdownManager;
|
||||
@@ -851,25 +848,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
beanDescriptor.sort(list, sortByClause);
|
||||
}
|
||||
|
||||
public <T> Query<T> createQuery(Class<T> beanType) throws PersistenceException {
|
||||
return createQuery(beanType, null);
|
||||
}
|
||||
|
||||
public <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) throws PersistenceException {
|
||||
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
throw new PersistenceException("Is " + beanType.getName() + " an Entity Bean? BeanDescriptor not found?");
|
||||
}
|
||||
DeployNamedQuery deployQuery = desc.getNamedQuery(namedQuery);
|
||||
if (deployQuery == null) {
|
||||
throw new PersistenceException("named query " + namedQuery + " was not found for " + desc.getFullName());
|
||||
}
|
||||
|
||||
// this will parse the query
|
||||
return new DefaultOrmQuery<T>(desc, this, expressionFactory, deployQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Set<String> validateQuery(Query<T> query) {
|
||||
|
||||
@@ -901,38 +879,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return createQuery(beanType);
|
||||
}
|
||||
|
||||
public <T> Query<T> createQuery(Class<T> beanType, String query) {
|
||||
public <T> Query<T> createQuery(Class<T> beanType) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
throw new PersistenceException(beanType.getName() + " is NOT an Entity Bean registered with this server?");
|
||||
}
|
||||
switch (desc.getEntityType()) {
|
||||
case SQL:
|
||||
if (query != null) {
|
||||
throw new PersistenceException("You must used Named queries for this Entity " + desc.getFullName());
|
||||
}
|
||||
// use the "default" SqlSelect
|
||||
DeployNamedQuery defaultSqlSelect = desc.getNamedQuery("default");
|
||||
return new DefaultOrmQuery<T>(desc, this, expressionFactory, defaultSqlSelect);
|
||||
|
||||
default:
|
||||
return new DefaultOrmQuery<T>(desc, this, expressionFactory, query);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) {
|
||||
BeanDescriptor<?> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
String m = beanType.getName() + " is NOT an Entity Bean registered with this server?";
|
||||
throw new PersistenceException(m);
|
||||
}
|
||||
|
||||
DeployNamedUpdate deployUpdate = desc.getNamedUpdate(namedUpdate);
|
||||
if (deployUpdate == null) {
|
||||
throw new PersistenceException("named update " + namedUpdate + " was not found for " + desc.getFullName());
|
||||
}
|
||||
|
||||
return new DefaultOrmUpdate<T>(beanType, this, desc.getBaseTable(), deployUpdate);
|
||||
return new DefaultOrmQuery<T>(desc, this, expressionFactory);
|
||||
}
|
||||
|
||||
public <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
|
||||
@@ -949,14 +901,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return new DefaultRelationalQuery(this, sql);
|
||||
}
|
||||
|
||||
public SqlQuery createNamedSqlQuery(String namedQuery) {
|
||||
DNativeQuery nq = beanDescriptorManager.getNativeQuery(namedQuery);
|
||||
if (nq == null) {
|
||||
throw new PersistenceException("SqlQuery " + namedQuery + " not found.");
|
||||
}
|
||||
return new DefaultRelationalQuery(this, nq.getQuery());
|
||||
}
|
||||
|
||||
public SqlUpdate createSqlUpdate(String sql) {
|
||||
return new DefaultSqlUpdate(this, sql);
|
||||
}
|
||||
@@ -965,14 +909,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return new DefaultCallableSql(this, sql);
|
||||
}
|
||||
|
||||
public SqlUpdate createNamedSqlUpdate(String namedQuery) {
|
||||
DNativeQuery nq = beanDescriptorManager.getNativeQuery(namedQuery);
|
||||
if (nq == null) {
|
||||
throw new PersistenceException("SqlUpdate " + namedQuery + " not found.");
|
||||
}
|
||||
return new DefaultSqlUpdate(this, nq.getQuery());
|
||||
}
|
||||
|
||||
public <T> T find(Class<T> beanType, Object uid) {
|
||||
|
||||
return find(beanType, uid, null);
|
||||
|
||||
@@ -23,17 +23,15 @@ import com.avaje.ebeaninternal.server.changelog.DefaultChangeLogPrepare;
|
||||
import com.avaje.ebeaninternal.server.changelog.DefaultChangeLogRegister;
|
||||
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
|
||||
import com.avaje.ebeaninternal.server.core.timezone.CloneDataTimeZone;
|
||||
import com.avaje.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
import com.avaje.ebeaninternal.server.core.timezone.NoDataTimeZone;
|
||||
import com.avaje.ebeaninternal.server.core.timezone.SimpleDataTimeZone;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployOrmXml;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
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.core.timezone.DataTimeZone;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.persist.DefaultPersister;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryEngine;
|
||||
@@ -56,6 +54,7 @@ import com.avaje.ebeanservice.docstore.api.DocStoreIntegration;
|
||||
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
|
||||
import com.avaje.ebeanservice.docstore.none.NoneDocStoreFactory;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import org.avaje.datasource.DataSourcePool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -79,8 +78,6 @@ public class InternalConfiguration {
|
||||
|
||||
private final DeployInherit deployInherit;
|
||||
|
||||
private final DeployOrmXml deployOrmXml;
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
private final DataTimeZone dataTimeZone;
|
||||
@@ -103,8 +100,6 @@ public class InternalConfiguration {
|
||||
|
||||
private final SpiBackgroundExecutor backgroundExecutor;
|
||||
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
private final JsonFactory jsonFactory;
|
||||
|
||||
private final DocStoreFactory docStoreFactory;
|
||||
@@ -114,13 +109,12 @@ public class InternalConfiguration {
|
||||
*/
|
||||
private final List<Plugin> plugins = new ArrayList<Plugin>();
|
||||
|
||||
public InternalConfiguration(XmlConfig xmlConfig, ClusterManager clusterManager,
|
||||
public InternalConfiguration(ClusterManager clusterManager,
|
||||
ServerCacheManager cacheManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses) {
|
||||
|
||||
this.docStoreFactory = initDocStoreFactory(serverConfig.service(DocStoreFactory.class));
|
||||
this.jsonFactory = serverConfig.getJsonFactory();
|
||||
this.xmlConfig = xmlConfig;
|
||||
this.clusterManager = clusterManager;
|
||||
this.backgroundExecutor = backgroundExecutor;
|
||||
this.cacheManager = cacheManager;
|
||||
@@ -131,7 +125,6 @@ public class InternalConfiguration {
|
||||
this.expressionFactory = initExpressionFactory(serverConfig, databasePlatform);
|
||||
this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses);
|
||||
|
||||
this.deployOrmXml = new DeployOrmXml();
|
||||
this.deployInherit = new DeployInherit(bootupClasses);
|
||||
|
||||
this.deployCreateProperties = new DeployCreateProperties(typeManager);
|
||||
@@ -264,10 +257,6 @@ public class InternalConfiguration {
|
||||
return new DJsonContext(server, jsonFactory, typeManager);
|
||||
}
|
||||
|
||||
public XmlConfig getXmlConfig() {
|
||||
return xmlConfig;
|
||||
}
|
||||
|
||||
public AutoTuneService createAutoTuneService(SpiEbeanServer server) {
|
||||
return AutoTuneServiceFactory.create(server, serverConfig);
|
||||
}
|
||||
@@ -316,10 +305,6 @@ public class InternalConfiguration {
|
||||
return deployInherit;
|
||||
}
|
||||
|
||||
public DeployOrmXml getDeployOrmXml() {
|
||||
return deployOrmXml;
|
||||
}
|
||||
|
||||
public DeployCreateProperties getDeployCreateProperties() {
|
||||
return deployCreateProperties;
|
||||
}
|
||||
|
||||
@@ -174,14 +174,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a query using generated sql. If false this query
|
||||
* will use raw sql (Entity bean based on raw sql select).
|
||||
*/
|
||||
public boolean isSqlSelect() {
|
||||
return query.isSqlSelect() && query.getRawSql() == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistenceContext used for this request.
|
||||
*/
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
|
||||
/**
|
||||
* Holds the orm.xml and ebean-orm.xml deployment information.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class XmlConfig {
|
||||
|
||||
private final List<Dnode> ebeanOrmXml;
|
||||
private final List<Dnode> ormXml;
|
||||
private final List<Dnode> allXml;
|
||||
|
||||
public XmlConfig(List<Dnode> ormXml, List<Dnode> ebeanOrmXml){
|
||||
this.ormXml = ormXml;
|
||||
this.ebeanOrmXml = ebeanOrmXml;
|
||||
this.allXml = new ArrayList<Dnode>(ormXml.size() + ebeanOrmXml.size());
|
||||
allXml.addAll(ormXml);
|
||||
allXml.addAll(ebeanOrmXml);
|
||||
}
|
||||
|
||||
public List<Dnode> getEbeanOrmXml() {
|
||||
return ebeanOrmXml;
|
||||
}
|
||||
|
||||
public List<Dnode> getOrmXml() {
|
||||
return ormXml;
|
||||
}
|
||||
|
||||
public List<Dnode> find(List<Dnode> entityXml, String element) {
|
||||
ArrayList<Dnode> hits = new ArrayList<Dnode>();
|
||||
for (int i = 0; i < entityXml.size(); i++) {
|
||||
hits.addAll(entityXml.get(i).findAll(element, 1));
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the deployment xml for a given entity.
|
||||
* <p>
|
||||
* This searches all the orm.xml and ebean-orm.xml files.
|
||||
* </p>
|
||||
*/
|
||||
public List<Dnode> findEntityXml(String className) {
|
||||
|
||||
ArrayList<Dnode> hits = new ArrayList<Dnode>(2);
|
||||
|
||||
for (Dnode ormXml : allXml) {
|
||||
Dnode entityMappings = ormXml.find("entity-mappings");
|
||||
|
||||
List<Dnode> entities = entityMappings.findAll("entity", "class", className, 1);
|
||||
if (entities.size() == 1) {
|
||||
hits.add(entities.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
return hits;
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
import com.avaje.ebeaninternal.server.lib.util.DnodeReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used to read the orm.xml and ebean-orm.xml configuration files.
|
||||
*
|
||||
* @author rbygrave
|
||||
* @author Richard Vowles - http://plus.google.com/RichardVowles
|
||||
*/
|
||||
public class XmlConfigLoader {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(XmlConfigLoader.class);
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public XmlConfigLoader(ClassLoader classLoader) {
|
||||
|
||||
if (classLoader == null) {
|
||||
classLoader = getClass().getClassLoader();
|
||||
}
|
||||
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public XmlConfig load() {
|
||||
List<Dnode> ormXml = search("META-INF/orm.xml");
|
||||
List<Dnode> ebeanOrmXml = search("META-INF/ebean-orm.xml");
|
||||
|
||||
return new XmlConfig(ormXml, ebeanOrmXml);
|
||||
}
|
||||
|
||||
public List<Dnode> search(String resourceName) {
|
||||
ArrayList<Dnode> xmlList = new ArrayList<Dnode>();
|
||||
|
||||
try {
|
||||
Enumeration<URL> resources = classLoader.getResources(resourceName);
|
||||
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
|
||||
InputStream is = url.openStream();
|
||||
processInputStream(xmlList, is);
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Unable to find resources {}", resourceName);
|
||||
}
|
||||
|
||||
return xmlList;
|
||||
}
|
||||
|
||||
private void processInputStream(ArrayList<Dnode> xmlList, InputStream is) throws IOException {
|
||||
|
||||
DnodeReader reader = new DnodeReader();
|
||||
Dnode xmlDoc = reader.parseXml(is);
|
||||
is.close();
|
||||
|
||||
xmlList.add(xmlDoc);
|
||||
}
|
||||
}
|
||||
@@ -347,10 +347,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
*/
|
||||
private final String fullName;
|
||||
|
||||
private final Map<String, DeployNamedQuery> namedQueries;
|
||||
|
||||
private final Map<String, DeployNamedUpdate> namedUpdates;
|
||||
|
||||
/**
|
||||
* Flag used to determine if saves can be skipped.
|
||||
*/
|
||||
@@ -414,9 +410,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.beanType = deploy.getBeanType();
|
||||
this.rootBeanType = PersistenceContextUtil.root(beanType);
|
||||
this.prototypeEntityBean = createPrototypeEntityBean(beanType);
|
||||
|
||||
this.namedQueries = deploy.getNamedQueries();
|
||||
this.namedUpdates = deploy.getNamedUpdates();
|
||||
|
||||
this.inheritInfo = deploy.getInheritInfo();
|
||||
|
||||
@@ -703,14 +696,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
softDeleteByIdSql = null;
|
||||
softDeleteByIdInSql = null;
|
||||
}
|
||||
|
||||
if (!isEmbedded()) {
|
||||
// parse every named update up front into sql dml
|
||||
for (DeployNamedUpdate namedUpdate : namedUpdates.values()) {
|
||||
DeployUpdateParser parser = new DeployUpdateParser(this);
|
||||
namedUpdate.initialise(parser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1532,24 +1517,6 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
return idBinder.getBindValues(idValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a named query.
|
||||
*/
|
||||
public DeployNamedQuery getNamedQuery(String name) {
|
||||
return namedQueries.get(name);
|
||||
}
|
||||
|
||||
public void addNamedQuery(DeployNamedQuery deployNamedQuery) {
|
||||
namedQueries.put(deployNamedQuery.getName(), deployNamedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a named update.
|
||||
*/
|
||||
public DeployNamedUpdate getNamedUpdate(String name) {
|
||||
return namedUpdates.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createBean() {
|
||||
|
||||
@@ -2,9 +2,6 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Model;
|
||||
import com.avaje.ebean.RawSql;
|
||||
import com.avaje.ebean.RawSqlBuilder;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
@@ -15,20 +12,20 @@ import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbHistorySupport;
|
||||
import com.avaje.ebean.config.dbplatform.DbIdentity;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogFilter;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogListener;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogPrepare;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogRegister;
|
||||
import com.avaje.ebean.plugin.BeanType;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.TransactionEventTable;
|
||||
import com.avaje.ebeaninternal.server.core.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.core.InternalConfiguration;
|
||||
import com.avaje.ebeaninternal.server.core.Message;
|
||||
import com.avaje.ebeaninternal.server.core.XmlConfig;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.IdBinderEmbedded;
|
||||
@@ -46,8 +43,6 @@ import com.avaje.ebeaninternal.server.deploy.parse.DeployInherit;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployUtil;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.ReadAnnotations;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.TransientProperties;
|
||||
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
|
||||
import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory;
|
||||
@@ -109,8 +104,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final DeployCreateProperties createProperties;
|
||||
|
||||
private final DeployOrmXml deployOrmXml;
|
||||
|
||||
private final BeanManagerFactory beanManagerFactory;
|
||||
|
||||
private final ServerConfig serverConfig;
|
||||
@@ -163,8 +156,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final IdBinderFactory idBinderFactory;
|
||||
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
private final BeanLifecycleAdapterFactory beanLifecycleAdapterFactory;
|
||||
|
||||
private final boolean eagerFetchLobs;
|
||||
@@ -190,7 +181,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
this.serverName = InternString.intern(serverConfig.getName());
|
||||
this.cacheManager = config.getCacheManager();
|
||||
this.docStoreFactory = config.getDocStoreFactory();
|
||||
this.xmlConfig = config.getXmlConfig();
|
||||
this.dbSequenceBatchSize = serverConfig.getDatabaseSequenceBatchSize();
|
||||
this.backgroundExecutor = config.getBackgroundExecutor();
|
||||
this.dataSource = serverConfig.getDataSource();
|
||||
@@ -207,7 +197,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
this.namingConvention = serverConfig.getNamingConvention();
|
||||
this.dbIdentity = config.getDatabasePlatform().getDbIdentity();
|
||||
this.deplyInherit = config.getDeployInherit();
|
||||
this.deployOrmXml = config.getDeployOrmXml();
|
||||
this.deployUtil = config.getDeployUtil();
|
||||
|
||||
this.beanManagerFactory = new BeanManagerFactory(config.getDatabasePlatform());
|
||||
@@ -316,10 +305,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
readEntityBeanTable();
|
||||
readEntityDeploymentAssociations();
|
||||
readInheritedIdGenerators();
|
||||
|
||||
// creates the BeanDescriptors
|
||||
readEntityRelationships();
|
||||
readRawSqlQueries();
|
||||
|
||||
List<BeanDescriptor<?>> list = new ArrayList<BeanDescriptor<?>>(descMap.values());
|
||||
Collections.sort(list, beanDescComparator);
|
||||
@@ -555,10 +542,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return beanManagerMap.get(beanClassName);
|
||||
}
|
||||
|
||||
public DNativeQuery getNativeQuery(String name) {
|
||||
return deployOrmXml.getNativeQuery(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the BeanControllers, BeanFinders and BeanListeners.
|
||||
*/
|
||||
@@ -679,25 +662,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return new BeanTable(beanTable, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the named Raw Sql queries using BeanDescriptor.
|
||||
*/
|
||||
private void readRawSqlQueries() {
|
||||
|
||||
for (DeployBeanInfo<?> info : deplyInfoMap.values()) {
|
||||
|
||||
DeployBeanDescriptor<?> deployDesc = info.getDescriptor();
|
||||
BeanDescriptor<?> desc = getBeanDescriptor(deployDesc.getBeanType());
|
||||
|
||||
for (DRawSqlMeta rawSqlMeta : deployDesc.getRawSqlMeta()) {
|
||||
if (rawSqlMeta.getQuery() != null) {
|
||||
DeployNamedQuery nq = new DRawSqlSelectBuilder(namingConvention, desc, rawSqlMeta).parse();
|
||||
desc.addNamedQuery(nq);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void readEntityRelationships() {
|
||||
|
||||
@@ -1148,8 +1112,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
readAnnotations.readAssociations(info, this);
|
||||
|
||||
readXml(desc);
|
||||
|
||||
if (EntityType.SQL == desc.getEntityType()) {
|
||||
desc.setBaseTable(null, null, null);
|
||||
}
|
||||
@@ -1271,127 +1233,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
}
|
||||
}
|
||||
|
||||
private void readXml(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
List<Dnode> eXml = xmlConfig.findEntityXml(deployDesc.getFullName());
|
||||
readXmlRawSql(deployDesc, eXml);
|
||||
|
||||
Dnode entityXml = deployOrmXml.findEntityDeploymentXml(deployDesc.getFullName());
|
||||
|
||||
if (entityXml != null) {
|
||||
readXmlNamedQueries(deployDesc, entityXml);
|
||||
readXmlSql(deployDesc, entityXml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read sql-select (FUTURE: additionally sql-insert, sql-update, sql-delete).
|
||||
* If found this entity bean is based on raw sql.
|
||||
*/
|
||||
private void readXmlSql(DeployBeanDescriptor<?> deployDesc, Dnode entityXml) {
|
||||
|
||||
List<Dnode> sqlSelectList = entityXml.findAll("sql-select", entityXml.getLevel() + 1);
|
||||
for (int i = 0; i < sqlSelectList.size(); i++) {
|
||||
Dnode sqlSelect = sqlSelectList.get(i);
|
||||
readSqlSelect(deployDesc, sqlSelect);
|
||||
}
|
||||
}
|
||||
|
||||
private String findContent(Dnode node, String nodeName) {
|
||||
Dnode found = node.find(nodeName);
|
||||
if (found != null) {
|
||||
return found.getNodeContent();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void readSqlSelect(DeployBeanDescriptor<?> deployDesc, Dnode sqlSelect) {
|
||||
|
||||
String name = sqlSelect.getStringAttr("name", "default");
|
||||
String extend = sqlSelect.getStringAttr("extend", null);
|
||||
String queryDebug = sqlSelect.getStringAttr("debug", null);
|
||||
boolean debug = (queryDebug != null && queryDebug.equalsIgnoreCase("true"));
|
||||
|
||||
// the raw sql select
|
||||
String query = findContent(sqlSelect, "query");
|
||||
String where = findContent(sqlSelect, "where");
|
||||
String having = findContent(sqlSelect, "having");
|
||||
String columnMapping = findContent(sqlSelect, "columnMapping");
|
||||
|
||||
DRawSqlMeta m = new DRawSqlMeta(name, extend, query, debug, where, having, columnMapping);
|
||||
|
||||
deployDesc.add(m);
|
||||
|
||||
}
|
||||
|
||||
private void readXmlRawSql(DeployBeanDescriptor<?> deployDesc, List<Dnode> entityXml) {
|
||||
|
||||
List<Dnode> rawSqlQueries = xmlConfig.find(entityXml, "raw-sql");
|
||||
for (int i = 0; i < rawSqlQueries.size(); i++) {
|
||||
Dnode rawSqlDnode = rawSqlQueries.get(i);
|
||||
String name = rawSqlDnode.getAttribute("name");
|
||||
if (isEmpty(name)) {
|
||||
throw new IllegalStateException("raw-sql for " + deployDesc.getFullName() + " missing name attribute");
|
||||
}
|
||||
Dnode queryNode = rawSqlDnode.find("query");
|
||||
if (queryNode == null) {
|
||||
throw new IllegalStateException("raw-sql for " + deployDesc.getFullName() + " missing query element");
|
||||
}
|
||||
String sql = queryNode.getNodeContent();
|
||||
if (isEmpty(sql)) {
|
||||
throw new IllegalStateException("raw-sql for " + deployDesc.getFullName() + " has empty sql in the query element?");
|
||||
}
|
||||
|
||||
List<Dnode> columnMappings = rawSqlDnode.findAll("columnMapping", 1);
|
||||
|
||||
RawSqlBuilder rawSqlBuilder = RawSqlBuilder.parse(sql);
|
||||
for (int j = 0; j < columnMappings.size(); j++) {
|
||||
Dnode cm = columnMappings.get(j);
|
||||
String column = cm.getAttribute("column");
|
||||
String property = cm.getAttribute("property");
|
||||
rawSqlBuilder.columnMapping(column, property);
|
||||
}
|
||||
RawSql rawSql = rawSqlBuilder.create();
|
||||
|
||||
DeployNamedQuery namedQuery = new DeployNamedQuery(name, rawSql);
|
||||
deployDesc.add(namedQuery);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read named queries for this bean type.
|
||||
*/
|
||||
private void readXmlNamedQueries(DeployBeanDescriptor<?> deployDesc, Dnode entityXml) {
|
||||
|
||||
// look for named-query...
|
||||
List<Dnode> namedQueries = entityXml.findAll("named-query", 1);
|
||||
|
||||
for (Dnode namedQueryXml : namedQueries) {
|
||||
|
||||
String name = namedQueryXml.getAttribute("name");
|
||||
Dnode query = namedQueryXml.find("query");
|
||||
if (query == null) {
|
||||
logger.warn("orm.xml " + deployDesc.getFullName() + " named-query missing query element?");
|
||||
|
||||
} else {
|
||||
String oql = query.getNodeContent();
|
||||
// TODO: QueryHints not read from xml yet
|
||||
if (name == null || oql == null) {
|
||||
logger.warn("orm.xml " + deployDesc.getFullName() + " named-query has no query content?");
|
||||
} else {
|
||||
// add the named query
|
||||
DeployNamedQuery q = new DeployNamedQuery(name, oql, null);
|
||||
deployDesc.add(q);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BeanPropertyInfoFactory createReflectionFactory() {
|
||||
|
||||
return new EnhanceBeanPropertyInfoFactory();
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
/**
|
||||
* A native query defined in deployment xml.
|
||||
*/
|
||||
public class DNativeQuery {
|
||||
|
||||
final String query;
|
||||
|
||||
public DNativeQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
public class DRawSqlColumnInfo {
|
||||
|
||||
final String name;
|
||||
|
||||
final String label;
|
||||
|
||||
final String propertyName;
|
||||
|
||||
final boolean scalarProperty;
|
||||
|
||||
public DRawSqlColumnInfo(String name, String label, String propertyName, boolean scalarProperty) {
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
this.propertyName = propertyName;
|
||||
this.scalarProperty = scalarProperty;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
public boolean isScalarProperty() {
|
||||
return scalarProperty;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "name:" + name + " label:" + label + " prop:" + propertyName;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
/**
|
||||
* Meta data for a sql-select object.
|
||||
* <p>
|
||||
* Created from SqlSelect annotation or xml deployment.
|
||||
* </p>
|
||||
*/
|
||||
public class DRawSqlMeta {
|
||||
|
||||
private String name;
|
||||
private String tableAlias;
|
||||
private String extend;
|
||||
private String query;
|
||||
private boolean debug;
|
||||
private String where;
|
||||
private String having;
|
||||
private String columnMapping;
|
||||
|
||||
public DRawSqlMeta(String name, String extend, String query, boolean debug,
|
||||
String where, String having, String columnMapping) {
|
||||
|
||||
this.name = name;
|
||||
this.extend = extend;
|
||||
this.query = query;
|
||||
this.debug = debug;
|
||||
this.having = having;
|
||||
this.where = where;
|
||||
this.columnMapping = columnMapping;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setTableAlias(String tableAlias) {
|
||||
this.tableAlias = tableAlias;
|
||||
}
|
||||
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
}
|
||||
|
||||
public String getExtend() {
|
||||
return extend;
|
||||
}
|
||||
|
||||
public void setExtend(String extend) {
|
||||
this.extend = extend;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
public void setDebug(boolean debug) {
|
||||
this.debug = debug;
|
||||
}
|
||||
|
||||
public String getWhere() {
|
||||
return where;
|
||||
}
|
||||
|
||||
public void setWhere(String where) {
|
||||
this.where = where;
|
||||
}
|
||||
|
||||
public String getHaving() {
|
||||
return having;
|
||||
}
|
||||
|
||||
public void setHaving(String having) {
|
||||
this.having = having;
|
||||
}
|
||||
|
||||
public String getColumnMapping() {
|
||||
return columnMapping;
|
||||
}
|
||||
|
||||
public void setColumnMapping(String columnMapping) {
|
||||
this.columnMapping = columnMapping;
|
||||
}
|
||||
|
||||
public void extend(DRawSqlMeta parentQuery){
|
||||
extendQuery(parentQuery.getQuery());
|
||||
extendColumnMapping(parentQuery.getColumnMapping());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend sql from the parent query that this query 'extends'.
|
||||
*/
|
||||
private void extendQuery(String parentSql) {
|
||||
if (query == null) {
|
||||
query = parentSql;
|
||||
} else {
|
||||
query = parentSql + " " + query;
|
||||
}
|
||||
}
|
||||
|
||||
private void extendColumnMapping(String parentColumnMapping) {
|
||||
if (columnMapping == null){
|
||||
columnMapping = parentColumnMapping;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.query.CQueryPredicates;
|
||||
import com.avaje.ebeaninternal.server.query.SqlTree;
|
||||
import com.avaje.ebeaninternal.server.query.SqlTreeNode;
|
||||
import com.avaje.ebeaninternal.server.query.SqlTreeNodeRoot;
|
||||
import com.avaje.ebeaninternal.server.query.SqlTreeProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents a SqlSelect raw sql query.
|
||||
*/
|
||||
public class DRawSqlSelect {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DRawSqlSelect.class);
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final DRawSqlColumnInfo[] selectColumns;
|
||||
|
||||
private final Map<String,DRawSqlColumnInfo> columnMap;
|
||||
|
||||
private final String preWhereExprSql;
|
||||
|
||||
private final boolean andWhereExpr;
|
||||
|
||||
private final String preHavingExprSql;
|
||||
|
||||
private final boolean andHavingExpr;
|
||||
|
||||
private final String orderBySql;
|
||||
|
||||
private final String whereClause;
|
||||
|
||||
private final String havingClause;
|
||||
|
||||
private final String query;
|
||||
|
||||
private final String columnMapping;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final SqlTree sqlTree;
|
||||
|
||||
private boolean withId;
|
||||
|
||||
private final String tableAlias;
|
||||
|
||||
public DRawSqlSelect(BeanDescriptor<?> desc, List<DRawSqlColumnInfo> selectColumns,
|
||||
String tableAlias, String preWhereExprSql, boolean andWhereExpr, String preHavingExprSql,
|
||||
boolean andHavingExpr, String orderBySql, DRawSqlMeta meta) {
|
||||
|
||||
this.desc = desc;
|
||||
this.tableAlias = tableAlias;
|
||||
this.selectColumns = selectColumns.toArray(new DRawSqlColumnInfo[selectColumns.size()]);
|
||||
this.preHavingExprSql = preHavingExprSql;
|
||||
this.preWhereExprSql = preWhereExprSql;
|
||||
this.andHavingExpr = andHavingExpr;
|
||||
this.andWhereExpr = andWhereExpr;
|
||||
this.orderBySql = orderBySql;
|
||||
this.name = meta.getName();
|
||||
this.whereClause = meta.getWhere();
|
||||
this.havingClause = meta.getHaving();
|
||||
this.query = meta.getQuery();
|
||||
this.columnMapping = meta.getColumnMapping();
|
||||
|
||||
this.sqlTree = initialise(desc);
|
||||
this.columnMap = createColumnMap(this.selectColumns);
|
||||
}
|
||||
|
||||
private Map<String,DRawSqlColumnInfo> createColumnMap(DRawSqlColumnInfo[] selectColumns) {
|
||||
|
||||
HashMap<String,DRawSqlColumnInfo> m = new HashMap<String,DRawSqlColumnInfo>();
|
||||
for (int i = 0; i < selectColumns.length; i++) {
|
||||
m.put(selectColumns[i].getPropertyName(), selectColumns[i]);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find foreign keys for assoc one types and build SqlTree.
|
||||
*/
|
||||
private SqlTree initialise(BeanDescriptor<?> owner){
|
||||
|
||||
try {
|
||||
return buildSqlTree(owner);
|
||||
|
||||
} catch (Exception e){
|
||||
String m = "Bug? initialising query "+name+" on "+owner;
|
||||
throw new RuntimeException(m, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RawSqlColumnInfo given it's logical property name.
|
||||
*/
|
||||
public DRawSqlColumnInfo getRawSqlColumnInfo(String propertyName){
|
||||
return columnMap.get(propertyName);
|
||||
}
|
||||
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the SqlTree for this query.
|
||||
* <p>
|
||||
* Most commonly this is just a simple list of properties - aka flat, but it
|
||||
* could be a real object graph tree for more complex scenarios.
|
||||
* </p>
|
||||
*/
|
||||
private SqlTree buildSqlTree(BeanDescriptor<?> desc){
|
||||
|
||||
SqlTreeProperties selectProps = new SqlTreeProperties();
|
||||
|
||||
for (int i = 0; i < selectColumns.length; i++) {
|
||||
|
||||
DRawSqlColumnInfo columnInfo = selectColumns[i];
|
||||
String propName = columnInfo.getPropertyName();
|
||||
BeanProperty beanProperty = desc.getBeanProperty(propName);
|
||||
if (beanProperty != null) {
|
||||
if (beanProperty.isId()){
|
||||
if (i > 0){
|
||||
String m = "With "+desc+" query:"+name+" the ID is not the first column in the select. It must be...";
|
||||
throw new PersistenceException(m);
|
||||
} else {
|
||||
withId = true;
|
||||
}
|
||||
} else {
|
||||
selectProps.add(beanProperty);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
String m = "Mapping for " + desc.getFullName();
|
||||
m += " query["+name+"] column[" + columnInfo + "] index[" + i;
|
||||
m += "] not matched to bean property?";
|
||||
logger.error(m);
|
||||
}
|
||||
}
|
||||
|
||||
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, withId);
|
||||
|
||||
return new SqlTree(desc.getName(), sqlRoot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the full SQL Select statement for the request.
|
||||
*/
|
||||
public String buildSql(String orderBy, CQueryPredicates predicates, OrmQueryRequest<?> request) {
|
||||
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(preWhereExprSql);
|
||||
sb.append(" ");
|
||||
|
||||
String dynamicWhere = null;
|
||||
if (request.getQuery().getId() != null) {
|
||||
// need to convert this as well. This avoids the
|
||||
// assumption that id has its proper dbColumn assigned
|
||||
// which may change if using multiple raw sql statements
|
||||
// against the same bean.
|
||||
BeanDescriptor<?> descriptor = request.getBeanDescriptor();
|
||||
//FIXME: I think this is broken... needs to be logical
|
||||
// and then parsed for RawSqlSelect...
|
||||
dynamicWhere = descriptor.getIdBinderIdSql();
|
||||
}
|
||||
|
||||
String dbWhere = predicates.getDbWhere();
|
||||
if (dbWhere != null && dbWhere.length() > 0) {
|
||||
if (dynamicWhere == null) {
|
||||
dynamicWhere = dbWhere;
|
||||
} else {
|
||||
dynamicWhere += " and " + dbWhere;
|
||||
}
|
||||
}
|
||||
|
||||
if (dynamicWhere != null) {
|
||||
if (andWhereExpr) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" where ");
|
||||
}
|
||||
sb.append(dynamicWhere);
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
if (preHavingExprSql != null) {
|
||||
sb.append(preHavingExprSql);
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
String dbHaving = predicates.getDbHaving();
|
||||
|
||||
if (dbHaving != null && dbHaving.length() > 0) {
|
||||
if (andHavingExpr) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" having ");
|
||||
}
|
||||
sb.append(dbHaving);
|
||||
sb.append(" ");
|
||||
}
|
||||
|
||||
if (orderBy != null) {
|
||||
sb.append(" order by ").append(orderBy);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getOrderBy(CQueryPredicates predicates) {
|
||||
String orderBy = predicates.getDbOrderBy();
|
||||
if (orderBy != null) {
|
||||
return orderBy;
|
||||
} else {
|
||||
return orderBySql;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public SqlTree getSqlTree() {
|
||||
return sqlTree;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public String getColumnMapping() {
|
||||
return columnMapping;
|
||||
}
|
||||
|
||||
public String getWhereClause() {
|
||||
return whereClause;
|
||||
}
|
||||
|
||||
public String getHavingClause() {
|
||||
return havingClause;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Arrays.toString(selectColumns);
|
||||
}
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public DeployParser createDeployPropertyParser() {
|
||||
return new DeployPropertyParserRawSql(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,339 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebeaninternal.server.querydefn.SimpleTextParser;
|
||||
|
||||
/**
|
||||
* Parses sql-select queries to try and determine the location where WHERE and HAVING
|
||||
* clauses can be added dynamically to the sql.
|
||||
*/
|
||||
public class DRawSqlSelectBuilder {
|
||||
|
||||
public static final String $_AND_HAVING = "${andHaving}";
|
||||
|
||||
public static final String $_HAVING = "${having}";
|
||||
|
||||
public static final String $_AND_WHERE = "${andWhere}";
|
||||
|
||||
public static final String $_WHERE = "${where}";
|
||||
|
||||
private static final String ORDER_BY = "order by";
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
private final DRawSqlMeta meta;
|
||||
|
||||
private final boolean debug;
|
||||
|
||||
private String sql;
|
||||
|
||||
private final SimpleTextParser textParser;
|
||||
|
||||
private int placeHolderWhere;
|
||||
private int placeHolderAndWhere;
|
||||
private int placeHolderHaving;
|
||||
private int placeHolderAndHaving;
|
||||
private final boolean hasPlaceHolders;
|
||||
|
||||
private int selectPos = -1;
|
||||
private int fromPos = -1;
|
||||
private int wherePos = -1;
|
||||
private int groupByPos = -1;
|
||||
private int havingPos = -1;
|
||||
private int orderByPos = -1;
|
||||
|
||||
private boolean whereExprAnd;
|
||||
private int whereExprPos = -1;
|
||||
private boolean havingExprAnd;
|
||||
private int havingExprPos = -1;
|
||||
|
||||
private final String tableAlias;
|
||||
|
||||
public DRawSqlSelectBuilder(NamingConvention namingConvention, BeanDescriptor<?> desc, DRawSqlMeta sqlSelectMeta) {
|
||||
|
||||
this.namingConvention = namingConvention;
|
||||
this.desc = desc;
|
||||
this.tableAlias = sqlSelectMeta.getTableAlias();
|
||||
this.meta = sqlSelectMeta;
|
||||
this.debug = sqlSelectMeta.isDebug();
|
||||
this.sql = sqlSelectMeta.getQuery().trim();
|
||||
this.hasPlaceHolders = findAndRemovePlaceHolders();
|
||||
this.textParser = new SimpleTextParser(this.sql);
|
||||
}
|
||||
|
||||
protected NamingConvention getNamingConvention() {
|
||||
return namingConvention;
|
||||
}
|
||||
|
||||
protected BeanDescriptor<?> getBeanDescriptor() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
protected boolean isDebug() {
|
||||
return debug;
|
||||
}
|
||||
|
||||
protected void debug(String msg) {
|
||||
if (debug) {
|
||||
System.out.println("debug> " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
public DeployNamedQuery parse() {
|
||||
|
||||
if (debug) {
|
||||
debug("");
|
||||
debug("Parsing sql-select in " + getErrName());
|
||||
}
|
||||
|
||||
if (!hasPlaceHolders()) {
|
||||
// parse the sql for the keywords...
|
||||
// select, from, where, having, group by, order by
|
||||
parseSqlFindKeywords(true);
|
||||
}
|
||||
|
||||
List<DRawSqlColumnInfo> selectColumns = findSelectColumns(meta.getColumnMapping());
|
||||
whereExprPos = findWhereExprPosition();
|
||||
havingExprPos = findHavingExprPosition();
|
||||
|
||||
String preWhereExprSql = removeWhitespace(findPreWhereExprSql());
|
||||
String preHavingExprSql = removeWhitespace(findPreHavingExprSql());
|
||||
|
||||
preWhereExprSql = trimSelectKeyword(preWhereExprSql);
|
||||
|
||||
String orderBySql = findOrderBySql();
|
||||
|
||||
DRawSqlSelect rawSqlSelect = new DRawSqlSelect(desc, selectColumns, tableAlias, preWhereExprSql,
|
||||
whereExprAnd, preHavingExprSql, havingExprAnd, orderBySql, meta);
|
||||
|
||||
return new DeployNamedQuery(rawSqlSelect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find and remove the known place holders such as ${where}.
|
||||
*/
|
||||
private boolean findAndRemovePlaceHolders() {
|
||||
placeHolderWhere = removePlaceHolder($_WHERE);
|
||||
placeHolderAndWhere = removePlaceHolder($_AND_WHERE);
|
||||
placeHolderHaving = removePlaceHolder($_HAVING);
|
||||
placeHolderAndHaving = removePlaceHolder($_AND_HAVING);
|
||||
return hasPlaceHolders();
|
||||
}
|
||||
|
||||
private int removePlaceHolder(String placeHolder) {
|
||||
int pos = sql.indexOf(placeHolder);
|
||||
if (pos > -1) {
|
||||
int after = pos + placeHolder.length() + 1;
|
||||
if (after > sql.length()) {
|
||||
sql = sql.substring(0, pos);
|
||||
} else {
|
||||
sql = sql.substring(0, pos) + sql.substring(after);
|
||||
}
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
private boolean hasPlaceHolders() {
|
||||
return placeHolderWhere > -1 || placeHolderAndWhere > -1 || placeHolderHaving > -1 || placeHolderAndHaving > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim off the select keyword (to support row_number() limit function).
|
||||
*/
|
||||
private String trimSelectKeyword(String preWhereExprSql) {
|
||||
|
||||
if (preWhereExprSql.length() < 7){
|
||||
throw new RuntimeException("Expecting at least 7 chars in ["+preWhereExprSql+"]");
|
||||
}
|
||||
|
||||
String select = preWhereExprSql.substring(0, 7);
|
||||
if (!select.equalsIgnoreCase("select ")){
|
||||
throw new RuntimeException("Expecting ["+preWhereExprSql+"] to start with \"select\"");
|
||||
}
|
||||
return preWhereExprSql.substring(7);
|
||||
}
|
||||
|
||||
|
||||
private String findOrderBySql() {
|
||||
if (orderByPos > -1) {
|
||||
int pos = orderByPos + ORDER_BY.length();
|
||||
return sql.substring(pos);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String findPreHavingExprSql() {
|
||||
if (havingExprPos > whereExprPos) {
|
||||
// an order by clause follows...
|
||||
return sql.substring(whereExprPos, havingExprPos - 1);
|
||||
}
|
||||
if (whereExprPos > -1) {
|
||||
// the rest of the sql...
|
||||
return sql.substring(whereExprPos);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String findPreWhereExprSql() {
|
||||
if (whereExprPos > -1) {
|
||||
return sql.substring(0, whereExprPos - 1);
|
||||
} else {
|
||||
return sql;
|
||||
}
|
||||
}
|
||||
|
||||
protected String getErrName() {
|
||||
return "entity[" + desc.getFullName() + "] query[" + meta.getName() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the columns in the select clause including the table alias' and
|
||||
* column alias.
|
||||
*/
|
||||
private List<DRawSqlColumnInfo> findSelectColumns(String selectClause) {
|
||||
|
||||
if (selectClause == null || selectClause.trim().length() == 0) {
|
||||
if (hasPlaceHolders) {
|
||||
if (debug) {
|
||||
debug("... No explicit ColumnMapping, so parse the sql looking for SELECT and FROM keywords.");
|
||||
}
|
||||
parseSqlFindKeywords(false);
|
||||
}
|
||||
if (selectPos == -1 || fromPos == -1) {
|
||||
String msg = "Error in [" + getErrName() + "] parsing sql looking ";
|
||||
msg += "for SELECT and FROM keywords.";
|
||||
msg += " select:" + selectPos + " from:" + fromPos;
|
||||
msg += ". You could use an explicit columnMapping to bypass this error.";
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
selectPos += "select".length();
|
||||
selectClause = sql.substring(selectPos, fromPos);
|
||||
}
|
||||
|
||||
selectClause = selectClause.trim();
|
||||
if (debug) {
|
||||
debug("ColumnMapping ... [" + selectClause + "]");
|
||||
}
|
||||
|
||||
return new DRawSqlSelectColumnsParser(this,selectClause).parse();
|
||||
}
|
||||
|
||||
private void parseSqlFindKeywords(boolean allKeywords) {
|
||||
|
||||
debug("Parsing query looking for SELECT...");
|
||||
selectPos = textParser.findWordLower("select");
|
||||
if (selectPos == -1) {
|
||||
String msg = "Error in "+getErrName()+" parsing sql, can not find SELECT keyword in:";
|
||||
throw new RuntimeException(msg + sql);
|
||||
}
|
||||
debug("Parsing query looking for FROM... SELECT found at " + selectPos);
|
||||
fromPos = textParser.findWordLower("from");
|
||||
if (fromPos == -1) {
|
||||
String msg = "Error in "+getErrName()+" parsing sql, can not find FROM keyword in:";
|
||||
throw new RuntimeException(msg + sql);
|
||||
}
|
||||
|
||||
if (!allKeywords) {
|
||||
return;
|
||||
}
|
||||
|
||||
debug("Parsing query looking for WHERE... FROM found at " + fromPos);
|
||||
wherePos = textParser.findWordLower("where");
|
||||
if (wherePos == -1) {
|
||||
debug("Parsing query looking for GROUP... no WHERE found");
|
||||
groupByPos = textParser.findWordLower("group", fromPos + 5);
|
||||
} else {
|
||||
debug("Parsing query looking for GROUP... WHERE found at " + wherePos);
|
||||
groupByPos = textParser.findWordLower("group");
|
||||
}
|
||||
if (groupByPos > -1) {
|
||||
debug("Parsing query looking for HAVING... GROUP found at " + groupByPos);
|
||||
havingPos = textParser.findWordLower("having");
|
||||
}
|
||||
|
||||
int startOrderBy = havingPos;
|
||||
if (startOrderBy == -1) {
|
||||
startOrderBy = groupByPos;
|
||||
}
|
||||
if (startOrderBy == -1) {
|
||||
startOrderBy = wherePos;
|
||||
}
|
||||
if (startOrderBy == -1) {
|
||||
startOrderBy = fromPos;
|
||||
}
|
||||
|
||||
debug("Parsing query looking for ORDER... starting at " + startOrderBy);
|
||||
orderByPos = textParser.findWordLower("order", startOrderBy);
|
||||
}
|
||||
|
||||
private int findWhereExprPosition() {
|
||||
if (hasPlaceHolders) {
|
||||
if (placeHolderWhere > -1) {
|
||||
return placeHolderWhere;
|
||||
} else {
|
||||
whereExprAnd = true;
|
||||
return placeHolderAndWhere;
|
||||
}
|
||||
}
|
||||
whereExprAnd = wherePos > 0;
|
||||
if (groupByPos > 0) {
|
||||
return groupByPos;
|
||||
}
|
||||
if (havingPos > 0) {
|
||||
return havingPos;
|
||||
}
|
||||
if (orderByPos > 0) {
|
||||
return orderByPos;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int findHavingExprPosition() {
|
||||
if (hasPlaceHolders) {
|
||||
if (placeHolderHaving > -1) {
|
||||
return placeHolderHaving;
|
||||
} else {
|
||||
havingExprAnd = true;
|
||||
return placeHolderAndHaving;
|
||||
}
|
||||
}
|
||||
havingExprAnd = havingPos > 0;
|
||||
if (orderByPos > 0) {
|
||||
return orderByPos;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private String removeWhitespace(String sql) {
|
||||
if (sql == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
boolean removeWhitespace = false;
|
||||
|
||||
int length = sql.length();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = sql.charAt(i);
|
||||
if (removeWhitespace) {
|
||||
if (!Character.isWhitespace(c)) {
|
||||
sb.append(c);
|
||||
removeWhitespace = false;
|
||||
}
|
||||
} else {
|
||||
if (c == '\r' || c == '\n') {
|
||||
sb.append('\n');
|
||||
removeWhitespace = true;
|
||||
} else {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Parses columnMapping (select clause) mapping columns to bean properties.
|
||||
*/
|
||||
public final class DRawSqlSelectColumnsParser {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DRawSqlSelectColumnsParser.class);
|
||||
|
||||
/**
|
||||
* Description of how the match was made.
|
||||
*/
|
||||
private String matchDescription;
|
||||
|
||||
/**
|
||||
* The actual column string used in search for a matching property.
|
||||
* <p>
|
||||
* This has table alias' and quoted identifiers removed.
|
||||
* </p>
|
||||
*/
|
||||
private String searchColumn;
|
||||
|
||||
private int columnIndex;
|
||||
|
||||
private int pos;
|
||||
|
||||
private final int end;
|
||||
|
||||
private final String sqlSelect;
|
||||
|
||||
private final List<DRawSqlColumnInfo> columns = new ArrayList<DRawSqlColumnInfo>();
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final NamingConvention namingConvention;
|
||||
|
||||
private final DRawSqlSelectBuilder parent;
|
||||
|
||||
private final boolean debug;
|
||||
|
||||
public DRawSqlSelectColumnsParser(DRawSqlSelectBuilder parent, String sqlSelect) {
|
||||
this.parent = parent;
|
||||
this.debug = parent.isDebug();
|
||||
this.namingConvention = parent.getNamingConvention();
|
||||
this.desc = parent.getBeanDescriptor();
|
||||
this.sqlSelect = sqlSelect;
|
||||
this.end = sqlSelect.length();
|
||||
}
|
||||
|
||||
public List<DRawSqlColumnInfo> parse() {
|
||||
while (pos <= end) {
|
||||
nextColumnInfo();
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
|
||||
private void nextColumnInfo() {
|
||||
int start = pos;
|
||||
nextComma();
|
||||
String colInfo = sqlSelect.substring(start, pos);
|
||||
pos++;
|
||||
colInfo = colInfo.trim();
|
||||
int secLastSpace = -1;
|
||||
int lastSpace = colInfo.lastIndexOf(' ');
|
||||
if (lastSpace > -1) {
|
||||
secLastSpace = colInfo.lastIndexOf(' ', lastSpace - 1);
|
||||
}
|
||||
String colName;
|
||||
String colLabel;
|
||||
if (lastSpace == -1) {
|
||||
// no column alias
|
||||
colName = colInfo;
|
||||
colLabel = colName;
|
||||
} else if (secLastSpace == -1) {
|
||||
// no 'as' keyword
|
||||
colName = colInfo.substring(0, lastSpace);
|
||||
colLabel = colInfo.substring(lastSpace + 1);
|
||||
if (colName.equals("")) {
|
||||
colName = colLabel;
|
||||
}
|
||||
} else {
|
||||
// check for as keyword
|
||||
String expectedAs = colInfo.substring(secLastSpace + 1, lastSpace);
|
||||
if (expectedAs.toLowerCase().equals("as")) {
|
||||
colName = colInfo.substring(0, secLastSpace);
|
||||
colLabel = colInfo.substring(lastSpace + 1);
|
||||
} else {
|
||||
String msg = "Error in " + parent.getErrName() + ". ";
|
||||
msg += "Expected \"AS\" keyword but got [" + expectedAs + "] in select clause ["
|
||||
+ colInfo + "]";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BeanProperty prop = findProperty(colLabel);
|
||||
if (prop == null) {
|
||||
if (debug) {
|
||||
String msg = "ColumnMapping ... idx[" + columnIndex
|
||||
+ "] ERROR, no property found to match... column[" + colName + "] label[" + colLabel
|
||||
+ "] search[" + searchColumn + "]";
|
||||
parent.debug(msg);
|
||||
}
|
||||
String msg = "Error in " + parent.getErrName() + ". ";
|
||||
msg += "No matching bean property for column[" + colName + "] columnLabel[" + colLabel
|
||||
+ "] idx[" + columnIndex + "] using search[" + searchColumn + "] found?";
|
||||
logger.error(msg);
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
String msg = null;
|
||||
if (debug || logger.isDebugEnabled()) {
|
||||
msg = "ColumnMapping ... idx[" + columnIndex + "] match column[" + colName
|
||||
+ "] label[" + colLabel + "] to property[" + prop + "]"
|
||||
+ matchDescription;
|
||||
}
|
||||
if (debug) {
|
||||
parent.debug(msg);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(msg);
|
||||
}
|
||||
|
||||
DRawSqlColumnInfo info = new DRawSqlColumnInfo(colName, colLabel, prop.getName(), prop.isScalar());
|
||||
columns.add(info);
|
||||
columnIndex++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private String removeQuotedIdentifierChars(String columnLabel) {
|
||||
|
||||
char c = columnLabel.charAt(0);
|
||||
if (Character.isJavaIdentifierStart(c)) {
|
||||
return columnLabel;
|
||||
}
|
||||
|
||||
// trim off first and last character
|
||||
String result = columnLabel.substring(1, columnLabel.length() - 1);
|
||||
|
||||
String msg = "sql-select trimming quoted identifier from["
|
||||
+ columnLabel + "] to[" + result+ "]";
|
||||
logger.debug(msg);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the property to match against the given resultSet column.
|
||||
*/
|
||||
private BeanProperty findProperty(String column) {
|
||||
|
||||
searchColumn = column;
|
||||
int dotPos = searchColumn.indexOf(".");
|
||||
if (dotPos > -1) {
|
||||
searchColumn = searchColumn.substring(dotPos + 1);
|
||||
}
|
||||
|
||||
searchColumn = removeQuotedIdentifierChars(searchColumn);
|
||||
|
||||
BeanProperty matchingProp = desc.getBeanProperty(searchColumn);
|
||||
if (matchingProp != null) {
|
||||
matchDescription = "";
|
||||
return matchingProp;
|
||||
}
|
||||
|
||||
// convert columnName using the namingConvention
|
||||
String propertyName = namingConvention.getPropertyFromColumn(desc.getBeanType(), searchColumn);
|
||||
matchingProp = desc.getBeanProperty(propertyName);
|
||||
if (matchingProp != null) {
|
||||
matchDescription = " ... using naming convention";
|
||||
return matchingProp;
|
||||
}
|
||||
|
||||
matchDescription = " ... by linear search";
|
||||
|
||||
// search all properties matching against the property db column
|
||||
BeanProperty[] propertiesBase = desc.propertiesBaseScalar();
|
||||
for (int i = 0; i < propertiesBase.length; i++) {
|
||||
BeanProperty prop = propertiesBase[i];
|
||||
if (isMatch(prop, searchColumn)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
BeanProperty idProp = desc.getIdProperty();
|
||||
if (idProp != null) {
|
||||
if (isMatch(idProp, searchColumn)) {
|
||||
return idProp;
|
||||
}
|
||||
}
|
||||
|
||||
BeanPropertyAssocOne<?>[] propertiesAssocOne = desc.propertiesOne();
|
||||
for (int i = 0; i < propertiesAssocOne.length; i++) {
|
||||
BeanProperty prop = propertiesAssocOne[i];
|
||||
if (isMatch(prop, searchColumn)) {
|
||||
return prop;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isMatch(BeanProperty prop, String columnLabel) {
|
||||
return columnLabel.equalsIgnoreCase(prop.getDbColumn()) || columnLabel.equalsIgnoreCase(prop.getName());
|
||||
}
|
||||
|
||||
private void nextComma() {
|
||||
boolean inQuote = false;
|
||||
while (pos < end) {
|
||||
char c = sqlSelect.charAt(pos);
|
||||
if (c == '\'') {
|
||||
inQuote = !inQuote;
|
||||
} else if (!inQuote && c == ',') {
|
||||
return;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
|
||||
import com.avaje.ebean.RawSql;
|
||||
|
||||
public class DeployNamedQuery {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String query;
|
||||
|
||||
private final QueryHint[] hints;
|
||||
|
||||
private final DRawSqlSelect sqlSelect;
|
||||
|
||||
private final RawSql rawSql;
|
||||
|
||||
public DeployNamedQuery(NamedQuery namedQuery) {
|
||||
this.name = namedQuery.name();
|
||||
this.query = namedQuery.query();
|
||||
this.hints = namedQuery.hints();
|
||||
this.sqlSelect = null;
|
||||
this.rawSql = null;
|
||||
}
|
||||
|
||||
public DeployNamedQuery(String name, String query, QueryHint[] hints) {
|
||||
this.name = name;
|
||||
this.query = query;
|
||||
this.hints = hints;
|
||||
this.sqlSelect = null;
|
||||
this.rawSql = null;
|
||||
}
|
||||
|
||||
public DeployNamedQuery(String name, RawSql rawSql) {
|
||||
this.name = name;
|
||||
this.query = null;
|
||||
this.hints = null;
|
||||
this.sqlSelect = null;
|
||||
this.rawSql = rawSql;
|
||||
}
|
||||
|
||||
public DeployNamedQuery(DRawSqlSelect sqlSelect) {
|
||||
this.name = sqlSelect.getName();
|
||||
this.query = null;
|
||||
this.hints = null;
|
||||
this.sqlSelect = sqlSelect;
|
||||
this.rawSql = null;
|
||||
}
|
||||
|
||||
public boolean isRawSql() {
|
||||
return rawSql != null;
|
||||
}
|
||||
|
||||
public boolean isSqlSelect() {
|
||||
return sqlSelect != null;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public QueryHint[] getHints() {
|
||||
return hints;
|
||||
}
|
||||
|
||||
public RawSql getRawSql() {
|
||||
return rawSql;
|
||||
}
|
||||
|
||||
public DRawSqlSelect getSqlSelect() {
|
||||
return sqlSelect;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
|
||||
/**
|
||||
* Deployment information for a named update.
|
||||
*/
|
||||
public class DeployNamedUpdate {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String updateStatement;
|
||||
|
||||
private final boolean notifyCache;
|
||||
|
||||
private String sqlUpdateStatement;
|
||||
|
||||
public DeployNamedUpdate(NamedUpdate update) {
|
||||
this.name = update.name();
|
||||
this.updateStatement = update.update();
|
||||
this.notifyCache = update.notifyCache();
|
||||
}
|
||||
|
||||
public void initialise(DeployUpdateParser parser) {
|
||||
sqlUpdateStatement = parser.parse(updateStatement);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSqlUpdateStatement() {
|
||||
return sqlUpdateStatement;
|
||||
}
|
||||
|
||||
public boolean isNotifyCache() {
|
||||
return notifyCache;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
import com.avaje.ebeaninternal.server.lib.util.DnodeReader;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Controls the creation and caching of BeanManager's, BeanDescriptors,
|
||||
* BeanTable etc for both beans and tables(MapBeans).
|
||||
* <p>
|
||||
* Also supports some other deployment features such as type conversion.
|
||||
* </p>
|
||||
*/
|
||||
public class DeployOrmXml {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DeployOrmXml.class);
|
||||
|
||||
private final HashMap<String, DNativeQuery> nativeQueryCache;
|
||||
|
||||
private final ArrayList<Dnode> ormXmlList;
|
||||
|
||||
public DeployOrmXml() {
|
||||
this.nativeQueryCache = new HashMap<String, DNativeQuery>();
|
||||
this.ormXmlList = findAllOrmXml();
|
||||
|
||||
initialiseNativeQueries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all the native queries in ALL orm xml deployment.
|
||||
*/
|
||||
private void initialiseNativeQueries() {
|
||||
for (Dnode ormXml : ormXmlList) {
|
||||
initialiseNativeQueries(ormXml);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the native queries in this particular orm xml deployment.
|
||||
*/
|
||||
private void initialiseNativeQueries(Dnode ormXml) {
|
||||
|
||||
Dnode entityMappings = ormXml.find("entity-mappings");
|
||||
if (entityMappings != null) {
|
||||
List<Dnode> nq = entityMappings.findAll("named-native-query", 1);
|
||||
for (int i = 0; i < nq.size(); i++) {
|
||||
Dnode nqNode = nq.get(i);
|
||||
Dnode nqQueryNode = nqNode.find("query");
|
||||
if (nqQueryNode != null) {
|
||||
String queryContent = nqQueryNode.getNodeContent();
|
||||
String queryName = nqNode.getAttribute("name");
|
||||
|
||||
if (queryName != null && queryContent != null) {
|
||||
DNativeQuery query = new DNativeQuery(queryContent);
|
||||
nativeQueryCache.put(queryName, query);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a native named query.
|
||||
* <p>
|
||||
* These are loaded from the orm.xml deployment file.
|
||||
* </p>
|
||||
*/
|
||||
public DNativeQuery getNativeQuery(String name) {
|
||||
return nativeQueryCache.get(name);
|
||||
}
|
||||
|
||||
private ArrayList<Dnode> findAllOrmXml() {
|
||||
|
||||
ArrayList<Dnode> ormXmlList = new ArrayList<Dnode>();
|
||||
|
||||
|
||||
String defaultFile = "orm.xml";
|
||||
readOrmXml(defaultFile, ormXmlList);
|
||||
|
||||
if (!ormXmlList.isEmpty()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Dnode ox : ormXmlList) {
|
||||
sb.append(", ").append(ox.getAttribute("ebean.filename"));
|
||||
}
|
||||
String loadedFiles = sb.toString().substring(2);
|
||||
logger.info("Deployment xml [" + loadedFiles + "] loaded.");
|
||||
}
|
||||
|
||||
return ormXmlList;
|
||||
}
|
||||
|
||||
private void readOrmXml(String ormXmlName, ArrayList<Dnode> ormXmlList) {
|
||||
|
||||
try {
|
||||
Dnode ormXml = readOrmXmlFromClasspath(ormXmlName);
|
||||
if (ormXml != null) {
|
||||
ormXml.setAttribute("ebean.filename", ormXmlName);
|
||||
ormXmlList.add(ormXml);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
logger.error("error reading orm xml deployment " + ormXmlName, e);
|
||||
}
|
||||
}
|
||||
|
||||
private Dnode readOrmXmlFromClasspath(String ormXmlName) throws IOException {
|
||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(ormXmlName);
|
||||
if (is == null) {
|
||||
return null;
|
||||
} else {
|
||||
return readOrmXml(is);
|
||||
}
|
||||
}
|
||||
|
||||
private Dnode readOrmXml(InputStream in) throws IOException {
|
||||
DnodeReader reader = new DnodeReader();
|
||||
Dnode ormXml = reader.parseXml(in);
|
||||
in.close();
|
||||
return ormXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the deployment xml for a given entity. This will return null if no
|
||||
* matching deployment xml is found for this entity.
|
||||
* <p>
|
||||
* This searches all the ormXml files and returns the first match.
|
||||
* </p>
|
||||
*/
|
||||
public Dnode findEntityDeploymentXml(String className) {
|
||||
|
||||
for (Dnode ormXml : ormXmlList) {
|
||||
Dnode entityMappings = ormXml.find("entity-mappings");
|
||||
|
||||
List<Dnode> entities = entityMappings.findAll("entity", "class", className, 1);
|
||||
if (entities.size() == 1) {
|
||||
return entities.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Converts logical property names to database columns for the raw sql.
|
||||
* <p>
|
||||
* This is used in building the where and having clauses for SqlSelect queries.
|
||||
* </p>
|
||||
*/
|
||||
public final class DeployPropertyParserRawSql extends DeployParser {
|
||||
|
||||
private final DRawSqlSelect rawSqlSelect;
|
||||
|
||||
public DeployPropertyParserRawSql(DRawSqlSelect rawSqlSelect) {
|
||||
this.rawSqlSelect = rawSqlSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null for raw sql queries.
|
||||
*/
|
||||
public Set<String> getIncludes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String convertWord() {
|
||||
String r = getDeployWord(word);
|
||||
return r == null ? word : r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
DRawSqlColumnInfo columnInfo = rawSqlSelect.getRawSqlColumnInfo(expression);
|
||||
if (columnInfo == null) {
|
||||
return null;
|
||||
} else {
|
||||
return columnInfo.getName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<!ELEMENT ebean (table | iudextender | findextender | datasource | primarykeys | property)* >
|
||||
<!ELEMENT table EMPTY >
|
||||
<!ATTLIST table name CDATA #REQUIRED>
|
||||
<!ELEMENT iudextender EMPTY >
|
||||
<!ATTLIST iudextender classname CDATA #REQUIRED>
|
||||
<!ELEMENT findextender EMPTY >
|
||||
<!ATTLIST findextender classname CDATA #REQUIRED>
|
||||
<!ELEMENT datasource EMPTY >
|
||||
<!ATTLIST datasource name CDATA #REQUIRED>
|
||||
<!ELEMENT primarykeys EMPTY >
|
||||
<!ATTLIST primarykeys keys CDATA #REQUIRED>
|
||||
<!ELEMENT property EMPTY >
|
||||
<!ATTLIST property name CDATA #REQUIRED
|
||||
datatype CDATA #REQUIRED
|
||||
deploydatatype CDATA #IMPLIED
|
||||
deployname CDATA #IMPLIED >
|
||||
@@ -1,13 +1,12 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import com.avaje.ebean.annotation.Cache;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebean.annotation.DocStore;
|
||||
import com.avaje.ebean.annotation.DocStoreMode;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
@@ -16,6 +15,7 @@ import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogFilter;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebean.util.CamelCaseHelper;
|
||||
import com.avaje.ebeaninternal.api.ConcurrencyMode;
|
||||
import com.avaje.ebeaninternal.server.core.CacheOptions;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
@@ -24,9 +24,6 @@ import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostLoad;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.DRawSqlMeta;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
|
||||
@@ -40,7 +37,6 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
@@ -72,12 +68,6 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private EntityType entityType;
|
||||
|
||||
private final Map<String, DeployNamedQuery> namedQueries = new LinkedHashMap<String, DeployNamedQuery>();
|
||||
|
||||
private final Map<String, DeployNamedUpdate> namedUpdates = new LinkedHashMap<String, DeployNamedUpdate>();
|
||||
|
||||
private final Map<String, DRawSqlMeta> rawSqlMetas = new LinkedHashMap<String, DRawSqlMeta>();
|
||||
|
||||
private DeployBeanPropertyAssocOne<?> unidirectional;
|
||||
|
||||
/**
|
||||
@@ -309,32 +299,6 @@ public class DeployBeanDescriptor<T> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<DRawSqlMeta> getRawSqlMeta() {
|
||||
if (!processedRawSqlExtend) {
|
||||
rawSqlProcessExtend();
|
||||
processedRawSqlExtend = true;
|
||||
}
|
||||
return rawSqlMetas.values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the "extend" attributes of raw SQL. Aka inherit the query and
|
||||
* column mapping.
|
||||
*/
|
||||
private void rawSqlProcessExtend() {
|
||||
|
||||
for (DRawSqlMeta rawSqlMeta : rawSqlMetas.values()) {
|
||||
String extend = rawSqlMeta.getExtend();
|
||||
if (extend != null) {
|
||||
DRawSqlMeta parentQuery = rawSqlMetas.get(extend);
|
||||
if (parentQuery == null) {
|
||||
throw new RuntimeException("parent query [" + extend + "] not found for sql-select " + rawSqlMeta.getName());
|
||||
}
|
||||
rawSqlMeta.extend(parentQuery);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DeployBeanTable createDeployBeanTable() {
|
||||
|
||||
DeployBeanTable beanTable = new DeployBeanTable(getBeanType());
|
||||
@@ -380,32 +344,6 @@ public class DeployBeanDescriptor<T> {
|
||||
return sequenceAllocationSize;
|
||||
}
|
||||
|
||||
public void add(DRawSqlMeta rawSqlMeta) {
|
||||
rawSqlMetas.put(rawSqlMeta.getName(), rawSqlMeta);
|
||||
if ("default".equals(rawSqlMeta.getName())) {
|
||||
setEntityType(EntityType.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
public void add(DeployNamedUpdate namedUpdate) {
|
||||
namedUpdates.put(namedUpdate.getName(), namedUpdate);
|
||||
}
|
||||
|
||||
public void add(DeployNamedQuery namedQuery) {
|
||||
namedQueries.put(namedQuery.getName(), namedQuery);
|
||||
if ("default".equals(namedQuery.getName())) {
|
||||
setEntityType(EntityType.SQL);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, DeployNamedQuery> getNamedQueries() {
|
||||
return namedQueries;
|
||||
}
|
||||
|
||||
public Map<String, DeployNamedUpdate> getNamedUpdates() {
|
||||
return namedUpdates;
|
||||
}
|
||||
|
||||
public String[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
@@ -7,16 +7,12 @@ import com.avaje.ebean.annotation.Draftable;
|
||||
import com.avaje.ebean.annotation.DraftableElement;
|
||||
import com.avaje.ebean.annotation.History;
|
||||
import com.avaje.ebean.annotation.Index;
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
import com.avaje.ebean.annotation.NamedUpdates;
|
||||
import com.avaje.ebean.annotation.ReadAudit;
|
||||
import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.annotation.View;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -25,8 +21,6 @@ import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
@@ -181,53 +175,10 @@ public class AnnotationClass extends AnnotationParser {
|
||||
descriptor.setUpdateChangesOnly(updateMode.updateChangesOnly());
|
||||
}
|
||||
|
||||
NamedQueries namedQueries = cls.getAnnotation(NamedQueries.class);
|
||||
if (namedQueries != null) {
|
||||
readNamedQueries(namedQueries);
|
||||
}
|
||||
NamedQuery namedQuery = cls.getAnnotation(NamedQuery.class);
|
||||
if (namedQuery != null) {
|
||||
readNamedQuery(namedQuery);
|
||||
}
|
||||
|
||||
NamedUpdates namedUpdates = cls.getAnnotation(NamedUpdates.class);
|
||||
if (namedUpdates != null) {
|
||||
readNamedUpdates(namedUpdates);
|
||||
}
|
||||
|
||||
NamedUpdate namedUpdate = cls.getAnnotation(NamedUpdate.class);
|
||||
if (namedUpdate != null) {
|
||||
readNamedUpdate(namedUpdate);
|
||||
}
|
||||
|
||||
Cache cache = cls.getAnnotation(Cache.class);
|
||||
if (cache != null && !disableL2Cache) {
|
||||
descriptor.setCache(cache);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQueries(NamedQueries namedQueries) {
|
||||
NamedQuery[] queries = namedQueries.value();
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
readNamedQuery(queries[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedQuery(NamedQuery namedQuery) {
|
||||
DeployNamedQuery q = new DeployNamedQuery(namedQuery);
|
||||
descriptor.add(q);
|
||||
}
|
||||
|
||||
private void readNamedUpdates(NamedUpdates updates) {
|
||||
NamedUpdate[] updateArray = updates.value();
|
||||
for (int i = 0; i < updateArray.length; i++) {
|
||||
readNamedUpdate(updateArray[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void readNamedUpdate(NamedUpdate update) {
|
||||
DeployNamedUpdate upd = new DeployNamedUpdate(update);
|
||||
descriptor.add(upd);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,321 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A lightweight tree structure for simple XML handling.
|
||||
* <p>
|
||||
* It removes support for nodes being mixed with content. That is, a node can
|
||||
* only contain content or a list of one or more child nodes. It does not
|
||||
* support mixing bits of content between the child nodes.
|
||||
* </p>
|
||||
* <p>
|
||||
* Although designed to simplify XML in supported cases it can be used as a
|
||||
* general tree structure with attributes of java Objects.
|
||||
* </p>
|
||||
*/
|
||||
public class Dnode {
|
||||
|
||||
int level;
|
||||
|
||||
String nodeName;
|
||||
|
||||
String nodeContent;
|
||||
|
||||
ArrayList<Dnode> children;
|
||||
|
||||
final LinkedHashMap<String, String> attrList = new LinkedHashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Create a node.
|
||||
*/
|
||||
public Dnode() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the raw XML string.
|
||||
*/
|
||||
public static Dnode parse(String s){
|
||||
DnodeReader r = new DnodeReader();
|
||||
return r.parseXml(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node as XML.
|
||||
*/
|
||||
public String toXml() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
generate(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate this node as xml to the buffer.
|
||||
*/
|
||||
public void generate(StringBuilder sb) {
|
||||
if (sb == null) {
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
sb.append("<").append(nodeName);
|
||||
for (String attr : attrList.keySet()) {
|
||||
Object attrValue = getAttribute(attr);
|
||||
sb.append(" ").append(attr).append("=\"");
|
||||
if (attrValue != null) {
|
||||
sb.append(attrValue);
|
||||
}
|
||||
sb.append("\"");
|
||||
}
|
||||
|
||||
if (nodeContent == null && !hasChildren()) {
|
||||
sb.append(" />");
|
||||
|
||||
} else {
|
||||
sb.append(">");
|
||||
if (children != null && children.size() > 0) {
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
Dnode child = children.get(i);
|
||||
child.generate(sb);
|
||||
}
|
||||
}
|
||||
if (nodeContent != null) {
|
||||
sb.append(nodeContent);
|
||||
}
|
||||
sb.append("</").append(nodeName).append(">");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node name.
|
||||
*/
|
||||
public String getNodeName() {
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node name.
|
||||
*/
|
||||
public void setNodeName(String nodeName) {
|
||||
this.nodeName = nodeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node content.
|
||||
*/
|
||||
public String getNodeContent() {
|
||||
return nodeContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the node content.
|
||||
*/
|
||||
public void setNodeContent(String nodeContent) {
|
||||
this.nodeContent = nodeContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this node has children.
|
||||
*/
|
||||
public boolean hasChildren() {
|
||||
return getChildrenCount() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of children this node has.
|
||||
*/
|
||||
public int getChildrenCount() {
|
||||
if (children == null) {
|
||||
return 0;
|
||||
}
|
||||
return children.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a ancestor node.
|
||||
*/
|
||||
public boolean remove(Dnode node) {
|
||||
if (children == null) {
|
||||
return false;
|
||||
}
|
||||
if (children.remove(node)) {
|
||||
return true;
|
||||
}
|
||||
for (Dnode child : children) {
|
||||
if (child.remove(node)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of children nodes.
|
||||
*/
|
||||
public List<Dnode> children() {
|
||||
if (children == null) {
|
||||
return null;
|
||||
}
|
||||
return children;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a child.
|
||||
*/
|
||||
public void addChild(Dnode child) {
|
||||
if (children == null) {
|
||||
children = new ArrayList<Dnode>();
|
||||
}
|
||||
children.add(child);
|
||||
child.setLevel(level + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the level or depth of the node from the root.
|
||||
*/
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the level or depth of this node from the root.
|
||||
*/
|
||||
public void setLevel(int level) {
|
||||
this.level = level;
|
||||
if (children != null) {
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
Dnode child = children.get(i);
|
||||
child.setLevel(level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first matching node using nodeName. This is a depth first tree
|
||||
* search.
|
||||
*/
|
||||
public Dnode find(String nodeName) {
|
||||
return find(nodeName, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first node matching nodeName and attribute value. This is a
|
||||
* depth first tree search.
|
||||
*/
|
||||
public Dnode find(String nodeName, String attrName, Object value) {
|
||||
|
||||
return find(nodeName, attrName, value, -1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for a single node with control over maxLevel. Find the first node
|
||||
* matching nodeName and attribute value. If attrName and value are null
|
||||
* then this will just search using the nodeName. This is a depth first tree
|
||||
* search. Once a matching node is found the search will stop.
|
||||
*/
|
||||
public Dnode find(String nodeName, String attrName, Object value, int maxLevel) {
|
||||
|
||||
ArrayList<Dnode> list = new ArrayList<Dnode>();
|
||||
findByNode(list, nodeName, true, attrName, value, maxLevel);
|
||||
if (list.size() >= 1) {
|
||||
return list.get(0);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the nodes that match the nodeName.
|
||||
*
|
||||
*/
|
||||
public List<Dnode> findAll(String nodeName, int maxLevel) {
|
||||
int level = -1;
|
||||
if (maxLevel > 0) {
|
||||
level = this.level + maxLevel;
|
||||
}
|
||||
return findAll(nodeName, null, null, level);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the nodes that match the nodeName and attribute value.
|
||||
*/
|
||||
public List<Dnode> findAll(String nodeName, String attrName, Object value, int maxLevel) {
|
||||
|
||||
if (nodeName == null && attrName == null) {
|
||||
throw new RuntimeException("You can not have both nodeName and attrName null");
|
||||
}
|
||||
ArrayList<Dnode> list = new ArrayList<Dnode>();
|
||||
findByNode(list, nodeName, false, attrName, value, maxLevel);
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for recursive calling.
|
||||
*/
|
||||
private void findByNode(List<Dnode> list, String node, boolean findOne,String attrName, Object value, int maxLevel) {
|
||||
|
||||
if (findOne && list.size() == 1) {
|
||||
return;
|
||||
}
|
||||
if (node == null || node.equals(nodeName)) {
|
||||
if (attrName == null || value.equals(getAttribute(attrName))) {
|
||||
list.add(this);
|
||||
if (findOne) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (maxLevel > 0 && level >= maxLevel) {
|
||||
// hit max level
|
||||
|
||||
} else if (children != null) {
|
||||
// recursively search the children
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
Dnode child = children.get(i);
|
||||
child.findByNode(list, node, findOne, attrName, value,maxLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute names as strings.
|
||||
*/
|
||||
public Collection<String> attributeNames() {
|
||||
return attrList.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the attribute for a given name.
|
||||
*/
|
||||
public String getAttribute(String name) {
|
||||
return attrList.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Attribute as a String.
|
||||
* <p>
|
||||
* Will throw a ClassCastException if the attribute is not a String.
|
||||
* </p>
|
||||
*/
|
||||
public String getStringAttr(String name, String defaultValue) {
|
||||
Object o = attrList.get(name);
|
||||
if (o == null){
|
||||
return defaultValue;
|
||||
} else {
|
||||
return o.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an attribute.
|
||||
*/
|
||||
public void setAttribute(String name, String value) {
|
||||
attrList.put(name, value);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "[" + getNodeName() + " " + attrList + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* Parse an xml document into a Dnode tree.
|
||||
*/
|
||||
public class DnodeParser extends DefaultHandler {
|
||||
|
||||
/**
|
||||
* The root of the DContent tree.
|
||||
*/
|
||||
Dnode root;
|
||||
|
||||
/**
|
||||
* The current node being parsed.
|
||||
*/
|
||||
Dnode currentNode;
|
||||
|
||||
/**
|
||||
* The nodeContent buffer.
|
||||
*/
|
||||
StringBuilder buffer;
|
||||
|
||||
/**
|
||||
* Used to stack the nodes.
|
||||
*/
|
||||
final Stack<Dnode> stack = new Stack<Dnode>();
|
||||
|
||||
/**
|
||||
* The class used to construct new nodes. Should be Dnode or a subtype of
|
||||
* Dnode.
|
||||
*/
|
||||
Class<?> nodeClass = Dnode.class;
|
||||
|
||||
int depth = 0;
|
||||
|
||||
/**
|
||||
* Trim whitespace from the content.
|
||||
*/
|
||||
boolean trimWhitespace = true;
|
||||
|
||||
/**
|
||||
* The name of the tag that contains html content
|
||||
*/
|
||||
String contentName;
|
||||
|
||||
/**
|
||||
* The depth of the tag that contains the html content
|
||||
*/
|
||||
int contentDepth;
|
||||
|
||||
|
||||
/**
|
||||
* If true then trim the whitespace from the content.
|
||||
*/
|
||||
public boolean isTrimWhitespace() {
|
||||
return trimWhitespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to trim whitespace from the content.
|
||||
*/
|
||||
public void setTrimWhitespace(boolean trimWhitespace) {
|
||||
this.trimWhitespace = trimWhitespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the root node of the DContent tree.
|
||||
*/
|
||||
public Dnode getRoot() {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the type class of node to be created.
|
||||
*/
|
||||
public void setNodeClass(Class<?> nodeClass) {
|
||||
this.nodeClass = nodeClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Dnode using the nodeClass.
|
||||
*/
|
||||
private Dnode createNewNode() {
|
||||
try {
|
||||
return (Dnode) nodeClass.newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* process a startElement.
|
||||
*/
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes)
|
||||
throws SAXException {
|
||||
|
||||
super.startElement(uri, localName, qName, attributes);
|
||||
depth++;
|
||||
|
||||
boolean isContent = (contentName != null);
|
||||
|
||||
if (isContent){
|
||||
// must be html content... add the begin tag as content
|
||||
buffer.append("<").append(localName);
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
String key = attributes.getLocalName(i);
|
||||
String val = attributes.getValue(i);
|
||||
buffer.append(" ").append(key).append("='").append(val).append("'");
|
||||
}
|
||||
buffer.append(">");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
buffer = new StringBuilder();
|
||||
Dnode node = createNewNode();
|
||||
node.setNodeName(localName);
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
String key = attributes.getLocalName(i);
|
||||
String val = attributes.getValue(i);
|
||||
node.setAttribute(key, val);
|
||||
if ("type".equalsIgnoreCase(key) && "content".equalsIgnoreCase(val)) {
|
||||
// this tag contains html content
|
||||
// no more nodes until end tag is found
|
||||
contentName = localName;
|
||||
contentDepth = depth-1;
|
||||
}
|
||||
|
||||
}
|
||||
if (root == null) {
|
||||
root = node;
|
||||
}
|
||||
if (currentNode != null) {
|
||||
currentNode.addChild(node);
|
||||
}
|
||||
stack.push(node);
|
||||
currentNode = node;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* append the node content.
|
||||
*/
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
super.characters(ch, start, length);
|
||||
String s = new String(ch, start, length);
|
||||
int p = s.indexOf('\r');
|
||||
int p2 = s.indexOf('\n');
|
||||
if (p == -1 && p2 > -1) {
|
||||
// This is probably not an issue but tidys up content
|
||||
// in my text editor
|
||||
s = StringHelper.replaceString(s, "\n", "\r\n");
|
||||
}
|
||||
buffer.append(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* process the endElement.
|
||||
*/
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
super.endElement(uri, localName, qName);
|
||||
depth--;
|
||||
|
||||
if (contentName != null){
|
||||
// is this the end of the content?
|
||||
if (contentName.equals(localName) && contentDepth == depth){
|
||||
contentName = null;
|
||||
|
||||
} else {
|
||||
// the html content end tag
|
||||
buffer.append("</").append(localName).append(">");
|
||||
}
|
||||
return;
|
||||
}
|
||||
String content = buffer.toString();
|
||||
buffer.setLength(0);
|
||||
if (content.length() > 0) {
|
||||
if (trimWhitespace) {
|
||||
content = content.trim();
|
||||
}
|
||||
if (content.length() > 0) {
|
||||
currentNode.setNodeContent(content);
|
||||
}
|
||||
}
|
||||
stack.pop();
|
||||
if (!stack.isEmpty()) {
|
||||
// get the new currentNode
|
||||
currentNode = stack.pop();
|
||||
stack.push(currentNode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.lib.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* Parses an XML inputstream returning a Dnode tree.
|
||||
*/
|
||||
public class DnodeReader {
|
||||
|
||||
public Dnode parseXml(String str) {
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream bao = new ByteArrayOutputStream(str.length());
|
||||
OutputStreamWriter osw = new OutputStreamWriter(bao);
|
||||
|
||||
StringReader sr = new StringReader(str);
|
||||
|
||||
int charBufferSize = 1024;
|
||||
char[] buf = new char[charBufferSize];
|
||||
int len;
|
||||
while ((len = sr.read(buf, 0, buf.length)) != -1) {
|
||||
osw.write(buf, 0, len);
|
||||
}
|
||||
sr.close();
|
||||
osw.flush();
|
||||
osw.close();
|
||||
|
||||
bao.flush();
|
||||
bao.close();
|
||||
|
||||
InputStream is = new ByteArrayInputStream(bao.toByteArray());
|
||||
return parseXml(is);
|
||||
|
||||
} catch (IOException ex){
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the XML inputstream returning the Dnode tree.
|
||||
*/
|
||||
public Dnode parseXml(InputStream in) {
|
||||
|
||||
try {
|
||||
InputSource inSource = new InputSource(in);
|
||||
|
||||
DnodeParser parser = new DnodeParser();
|
||||
|
||||
XMLReader myReader = XMLReaderFactory.createXMLReader();
|
||||
myReader.setContentHandler(parser);
|
||||
|
||||
myReader.parse(inSource);
|
||||
|
||||
return parser.getRoot();
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -590,13 +590,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
|
||||
request.getGraphContext().register(path, bc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query name.
|
||||
*/
|
||||
public String getName() {
|
||||
return query.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a raw sql query as opposed to Ebean generated sql.
|
||||
*/
|
||||
|
||||
@@ -38,7 +38,6 @@ public class CQueryBuilder {
|
||||
|
||||
private final SqlLimiter sqlLimiter;
|
||||
|
||||
private final RawSqlSelectClauseBuilder sqlSelectBuilder;
|
||||
private final CQueryBuilderRawSql rawSqlHandler;
|
||||
|
||||
private final Binder binder;
|
||||
@@ -62,7 +61,6 @@ public class CQueryBuilder {
|
||||
this.historySupport = historySupport;
|
||||
this.tableAliasPlaceHolder = dbPlatform.getTableAliasPlaceHolder();
|
||||
this.columnAliasPrefix = dbPlatform.getColumnAliasPrefix();
|
||||
this.sqlSelectBuilder = new RawSqlSelectClauseBuilder(dbPlatform, binder);
|
||||
this.sqlLimiter = dbPlatform.getSqlLimiter();
|
||||
this.rawSqlHandler = new CQueryBuilderRawSql(sqlLimiter, dbPlatform);
|
||||
this.selectCountWithAlias = dbPlatform.isSelectCountWithAlias();
|
||||
@@ -260,10 +258,6 @@ public class CQueryBuilder {
|
||||
*/
|
||||
public <T> CQuery<T> buildQuery(OrmQueryRequest<T> request) {
|
||||
|
||||
if (request.isSqlSelect()) {
|
||||
return sqlSelectBuilder.build(request);
|
||||
}
|
||||
|
||||
CQueryPredicates predicates = new CQueryPredicates(binder, request);
|
||||
|
||||
CQueryPlan queryPlan = request.getQueryPlan();
|
||||
|
||||
@@ -466,7 +466,6 @@ public class CQueryEngine {
|
||||
}
|
||||
msg.append("exeMicros[").append(q.getQueryExecutionTimeMicros());
|
||||
msg.append("] rows[").append(q.getLoadedRowDetail());
|
||||
msg.append("] name[").append(q.getName());
|
||||
msg.append("] predicates[").append(q.getLogWhereSql());
|
||||
msg.append("] bind[").append(q.getBindLog()).append("]");
|
||||
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.SqlLimitResponse;
|
||||
import com.avaje.ebean.config.dbplatform.SqlLimiter;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.DRawSqlSelect;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployParser;
|
||||
import com.avaje.ebeaninternal.server.persist.Binder;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryLimitRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Factory for SqlSelectClause based on raw sql.
|
||||
* <p>
|
||||
* Its job is to execute the sql, read the meta data to determine the columns to
|
||||
* bean property mapping.
|
||||
* </p>
|
||||
*/
|
||||
public class RawSqlSelectClauseBuilder {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RawSqlSelectClauseBuilder.class);
|
||||
|
||||
private final Binder binder;
|
||||
|
||||
private final SqlLimiter dbQueryLimiter;
|
||||
private final DatabasePlatform dbPlatform;
|
||||
|
||||
public RawSqlSelectClauseBuilder(DatabasePlatform dbPlatform, Binder binder) {
|
||||
|
||||
this.binder = binder;
|
||||
this.dbQueryLimiter = dbPlatform.getSqlLimiter();
|
||||
this.dbPlatform = dbPlatform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build based on the includes and using the BeanJoinTree.
|
||||
*/
|
||||
public <T> CQuery<T> build(OrmQueryRequest<T> request) throws PersistenceException {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
BeanDescriptor<T> desc = request.getBeanDescriptor();
|
||||
|
||||
DeployNamedQuery namedQuery = desc.getNamedQuery(query.getName());
|
||||
DRawSqlSelect sqlSelect = namedQuery.getSqlSelect();
|
||||
|
||||
// create a parser for this specific SqlSelect... has to be really
|
||||
// as each SqlSelect could have different table alias etc
|
||||
DeployParser parser = sqlSelect.createDeployPropertyParser();
|
||||
|
||||
CQueryPredicates predicates = new CQueryPredicates(binder, request);
|
||||
// prepare and convert logical property names to dbColumns etc
|
||||
predicates.prepareRawSql(parser);
|
||||
|
||||
SqlTreeAlias alias = new SqlTreeAlias(sqlSelect.getTableAlias());
|
||||
predicates.parseTableAlias(alias);
|
||||
|
||||
String sql = null;
|
||||
try {
|
||||
|
||||
boolean includeRowNumColumn = false;
|
||||
String orderBy = sqlSelect.getOrderBy(predicates);
|
||||
|
||||
// build the actual sql String
|
||||
sql = sqlSelect.buildSql(orderBy, predicates, request);
|
||||
if (query.hasMaxRowsOrFirstRow() && dbQueryLimiter != null) {
|
||||
// wrap with a limit offset or ROW_NUMBER() etc
|
||||
SqlLimitResponse limitSql = dbQueryLimiter.limit(new OrmQueryLimitRequest(sql, orderBy, query, dbPlatform));
|
||||
includeRowNumColumn = limitSql.isIncludesRowNumberColumn();
|
||||
|
||||
sql = limitSql.getSql();
|
||||
} else {
|
||||
// add back select keyword
|
||||
// ... was removed to support dbQueryLimiter
|
||||
sql = "select " + sql;
|
||||
}
|
||||
|
||||
SqlTree sqlTree = sqlSelect.getSqlTree();
|
||||
|
||||
CQueryPlan queryPlan = new CQueryPlan(request, sql, sqlTree, true, includeRowNumColumn, "");
|
||||
return new CQuery<T>(request, predicates, queryPlan);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
String msg = "Error with " + desc.getFullName() + " query:\r" + sql;
|
||||
logger.error(msg);
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,14 +21,11 @@ import com.avaje.ebeaninternal.api.SpiQuerySecondary;
|
||||
import com.avaje.ebeaninternal.server.autotune.ProfilingListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.DRawSqlSelect;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
import com.avaje.ebeaninternal.server.expression.DefaultExpressionList;
|
||||
import com.avaje.ebeaninternal.server.expression.SimpleExpression;
|
||||
import com.avaje.ebeaninternal.server.query.CancelableQuery;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -61,11 +58,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private CancelableQuery cancelableQuery;
|
||||
|
||||
/**
|
||||
* The name of the query.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private Type type;
|
||||
|
||||
private Mode mode = Mode.NORMAL;
|
||||
@@ -194,8 +186,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private PersistenceContextScope persistenceContextScope;
|
||||
|
||||
private boolean sqlSelect;
|
||||
|
||||
/**
|
||||
* Allow for explicit on off or null for default.
|
||||
*/
|
||||
@@ -240,47 +230,12 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private boolean useDocStore;
|
||||
|
||||
public DefaultOrmQuery(BeanDescriptor<T> desc, EbeanServer server, ExpressionFactory expressionFactory, String query) {
|
||||
public DefaultOrmQuery(BeanDescriptor<T> desc, EbeanServer server, ExpressionFactory expressionFactory) {
|
||||
this.beanDescriptor = desc;
|
||||
this.beanType = desc.getBeanType();
|
||||
this.server = server;
|
||||
this.expressionFactory = expressionFactory;
|
||||
this.detail = new OrmQueryDetail();
|
||||
this.name = "";
|
||||
if (query != null) {
|
||||
setQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional supply a query which is parsed.
|
||||
*/
|
||||
public DefaultOrmQuery(BeanDescriptor<T> desc, EbeanServer server, ExpressionFactory expressionFactory,
|
||||
DeployNamedQuery namedQuery) throws PersistenceException {
|
||||
|
||||
this.beanDescriptor = desc;
|
||||
this.beanType = desc.getBeanType();
|
||||
this.server = server;
|
||||
this.expressionFactory = expressionFactory;
|
||||
this.detail = new OrmQueryDetail();
|
||||
if (namedQuery == null) {
|
||||
this.name = "";
|
||||
} else {
|
||||
this.name = namedQuery.getName();
|
||||
this.sqlSelect = namedQuery.isSqlSelect();
|
||||
if (sqlSelect) {
|
||||
// potentially with where and having clause...
|
||||
DRawSqlSelect sqlSelect = namedQuery.getSqlSelect();
|
||||
additionalWhere = sqlSelect.getWhereClause();
|
||||
additionalHaving = sqlSelect.getHavingClause();
|
||||
} else if (namedQuery.isRawSql()) {
|
||||
rawSql = namedQuery.getRawSql();
|
||||
|
||||
} else {
|
||||
// parse the entire query...
|
||||
setQuery(namedQuery.getQuery());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -290,7 +245,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public boolean isAutoTunable() {
|
||||
return beanDescriptor.isAutoTunable() && !isSqlSelect();
|
||||
return beanDescriptor.isAutoTunable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -496,7 +451,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
if (Mode.LAZYLOAD_MANY.equals(getMode())) {
|
||||
return false;
|
||||
} else if (hasMaxRowsOrFirstRow() && !isRawSql() && !isSqlSelect()) {
|
||||
} else if (hasMaxRowsOrFirstRow() && !isRawSql()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -605,8 +560,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
@Override
|
||||
public DefaultOrmQuery<T> copy(EbeanServer server) {
|
||||
|
||||
DefaultOrmQuery<T> copy = new DefaultOrmQuery<T>(beanDescriptor, server, expressionFactory, (String) null);
|
||||
copy.name = name;
|
||||
DefaultOrmQuery<T> copy = new DefaultOrmQuery<T>(beanDescriptor, server, expressionFactory);
|
||||
copy.includeTableJoin = includeTableJoin;
|
||||
copy.profilingListener = profilingListener;
|
||||
|
||||
@@ -623,7 +577,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
copy.excludeBeanCache = excludeBeanCache;
|
||||
copy.useQueryCache = useQueryCache;
|
||||
copy.readOnly = readOnly;
|
||||
copy.sqlSelect = sqlSelect;
|
||||
if (detail != null) {
|
||||
copy.detail = detail.copy();
|
||||
}
|
||||
@@ -744,7 +697,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public Boolean isAutoTune() {
|
||||
return sqlSelect ? Boolean.FALSE : autoTune;
|
||||
return autoTune;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -946,19 +899,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return new HashQuery(queryPlanKey, hc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query name.
|
||||
*/
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSqlSelect() {
|
||||
return sqlSelect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRawSql() {
|
||||
return rawSql != null;
|
||||
@@ -1065,16 +1005,6 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setQuery(String queryString) throws PersistenceException {
|
||||
|
||||
this.query = queryString;
|
||||
|
||||
OrmQueryDetailParser parser = new OrmQueryDetailParser(queryString);
|
||||
parser.parse();
|
||||
parser.assign(this);
|
||||
}
|
||||
|
||||
|
||||
protected void setRawWhereClause(String rawWhereClause) {
|
||||
this.rawWhereClause = rawWhereClause;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import java.io.Serializable;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebeaninternal.api.BindParams;
|
||||
import com.avaje.ebeaninternal.api.SpiUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.DeployNamedUpdate;
|
||||
|
||||
/**
|
||||
* Default implementation of OrmUpdate.
|
||||
@@ -60,20 +59,6 @@ public final class DefaultOrmUpdate<T> implements SpiUpdate<T>, Serializable {
|
||||
this.name = "";
|
||||
this.updateStatement = updateStatement;
|
||||
this.type = deriveType(updateStatement);
|
||||
|
||||
}
|
||||
|
||||
public DefaultOrmUpdate(Class<?> beanType, EbeanServer server, String baseTable, DeployNamedUpdate namedUpdate) {
|
||||
|
||||
this.beanType = beanType;
|
||||
this.server = server;
|
||||
this.baseTable = baseTable;
|
||||
this.name = namedUpdate.getName();
|
||||
this.notifyCache = namedUpdate.isNotifyCache();
|
||||
|
||||
// named updates are always converted to sql as part of the initialisation
|
||||
this.updateStatement = namedUpdate.getSqlUpdateStatement();
|
||||
this.type = deriveType(updateStatement);
|
||||
}
|
||||
|
||||
public DefaultOrmUpdate<T> setTimeout(int secs) {
|
||||
|
||||
Reference in New Issue
Block a user