beanType, String namedQuery) {
+ return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
+ }
+
/**
* Create a query for a type of entity bean.
*
diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java
index ebb69a62a..9e2d4a77a 100644
--- a/src/main/java/com/avaje/ebean/EbeanServer.java
+++ b/src/main/java/com/avaje/ebean/EbeanServer.java
@@ -199,6 +199,19 @@ public interface EbeanServer {
*/
UpdateQuery update(Class beanType);
+ /**
+ * Create a named query.
+ *
+ * For RawSql the named query is expected to be in ebean.xml.
+ *
+ *
+ * @param beanType The type of entity bean
+ * @param namedQuery The name of the query
+ * @param The type of entity bean
+ * @return The query
+ */
+ Query createNamedQuery(Class beanType, String namedQuery);
+
/**
* Create a query for an entity bean and synonym for {@link #find(Class)}.
*
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
index 40218a10c..545101630 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java
@@ -564,6 +564,11 @@ public interface SpiQuery extends Query {
*/
boolean tuneFetchProperties(OrmQueryDetail detail);
+ /**
+ * If this is a RawSql based entity set the default RawSql if not set.
+ */
+ void setDefaultRawSqlIfRequired();
+
/**
* Set to true if this query has been tuned by autoTune.
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
index 8a1934a23..1f97a70cb 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
@@ -887,6 +887,21 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return createQuery(beanType);
}
+ @Override
+ public Query createNamedQuery(Class beanType, String namedQuery) {
+ BeanDescriptor desc = getBeanDescriptor(beanType);
+ if (desc == null) {
+ throw new PersistenceException(beanType.getName() + " is NOT an Entity Bean registered with this server?");
+ }
+ RawSql rawSql = desc.getNamedRawSql(namedQuery);
+ if (rawSql != null) {
+ DefaultOrmQuery query = createQuery(beanType);
+ query.setRawSql(rawSql);
+ return query;
+ }
+ throw new PersistenceException("No named query called " + namedQuery + " for bean:" + beanType.getName());
+ }
+
public DefaultOrmQuery createQuery(Class beanType) {
BeanDescriptor desc = getBeanDescriptor(beanType);
if (desc == null) {
@@ -945,6 +960,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private SpiOrmQueryRequest createQueryRequest(SpiQuery query, Transaction t) {
+ query.setDefaultRawSqlIfRequired();
if (query.isAutoTunable() && !autoTuneService.tuneQuery(query)) {
// use deployment FetchType.LAZY/EAGER annotations
// to define the 'default' select clause
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
index face09faf..506411cea 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
@@ -109,6 +109,8 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
private final ConcurrentHashMap> comparatorCache = new ConcurrentHashMap>();
+ private final Map namedRawSql;
+
public void merge(EntityBean bean, EntityBean existing) {
EntityBeanIntercept fromEbi = bean._ebean_getIntercept();
@@ -412,6 +414,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
this.rootBeanType = PersistenceContextUtil.root(beanType);
this.prototypeEntityBean = createPrototypeEntityBean(beanType);
+ this.namedRawSql = deploy.getNamedRawSql();
this.inheritInfo = deploy.getInheritInfo();
this.beanFinder = deploy.getBeanFinder();
@@ -443,7 +446,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
this.baseTableVersionsBetween = deploy.getBaseTableVersionsBetween();
this.dependentTables = deploy.getDependentTables();
this.dbComment = deploy.getDbComment();
- this.autoTunable = EntityType.ORM.equals(entityType) && (beanFinder == null);
+ this.autoTunable = EntityType.ORM == entityType && (beanFinder == null);
// helper object used to derive lists of properties
DeployBeanPropertyLists listHelper = new DeployBeanPropertyLists(owner, this, deploy);
@@ -985,6 +988,13 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
return this;
}
+ /**
+ * Return the named RawSql query.
+ */
+ public RawSql getNamedRawSql(String named) {
+ return namedRawSql.get(named);
+ }
+
/**
* Return the type of DocStoreMode that should occur for this type of persist request
* given the transactions requested mode.
@@ -2169,7 +2179,7 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
* Return true if this is an embedded bean.
*/
public boolean isEmbedded() {
- return EntityType.EMBEDDED.equals(entityType);
+ return EntityType.EMBEDDED == entityType;
}
/**
@@ -2295,15 +2305,10 @@ public class BeanDescriptor implements MetaBeanInfo, BeanType {
}
/**
- * Returns true if this bean is based on a table (or possibly view) and
- * returns false if this bean is based on a raw sql select statement.
- *
- * When false querying this bean is based on a supplied sql select statement
- * placed in the orm xml file (as opposed to Ebean generated sql).
- *
+ * Returns true if this bean is based on RawSql.
*/
- public boolean isSqlSelectBased() {
- return EntityType.SQL.equals(entityType);
+ public boolean isRawSqlBased() {
+ return EntityType.SQL == entityType;
}
/**
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
index 9a8983a45..4cbaa718d 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.Model;
+import com.avaje.ebean.RawSqlBuilder;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.cache.ServerCacheManager;
@@ -22,10 +23,10 @@ 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.bootup.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.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.id.IdBinderEmbedded;
@@ -47,6 +48,12 @@ import com.avaje.ebeaninternal.server.properties.BeanPropertiesReader;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfo;
import com.avaje.ebeaninternal.server.properties.BeanPropertyInfoFactory;
import com.avaje.ebeaninternal.server.properties.EnhanceBeanPropertyInfoFactory;
+import com.avaje.ebeaninternal.xmlmapping.XmlMappingReader;
+import com.avaje.ebeaninternal.xmlmapping.model.XmAliasMapping;
+import com.avaje.ebeaninternal.xmlmapping.model.XmColumnMapping;
+import com.avaje.ebeaninternal.xmlmapping.model.XmEbean;
+import com.avaje.ebeaninternal.xmlmapping.model.XmEntity;
+import com.avaje.ebeaninternal.xmlmapping.model.XmRawSql;
import com.avaje.ebeanservice.docstore.api.DocStoreBeanAdapter;
import com.avaje.ebeanservice.docstore.api.DocStoreFactory;
import org.slf4j.Logger;
@@ -56,12 +63,16 @@ import javax.persistence.MappedSuperclass;
import javax.persistence.PersistenceException;
import javax.persistence.Transient;
import javax.sql.DataSource;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -124,7 +135,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private final String serverName;
- private Map, DeployBeanInfo>> deplyInfoMap = new HashMap, DeployBeanInfo>>();
+ private Map, DeployBeanInfo>> deployInfoMap = new HashMap, DeployBeanInfo>>();
private final Map, BeanTable> beanTableMap = new HashMap, BeanTable>();
@@ -301,6 +312,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
try {
createListeners();
readEntityDeploymentInitial();
+ readXmlMapping();
readEmbeddedDeployment();
readEntityBeanTable();
readEntityDeploymentAssociations();
@@ -319,8 +331,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
logStatus();
- deplyInfoMap.clear();
- deplyInfoMap = null;
+ deployInfoMap.clear();
+ deployInfoMap = null;
return asOfTableMap;
@@ -330,6 +342,62 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
}
+ private void readXmlMapping() {
+
+ try {
+ ClassLoader classLoader = serverConfig.getClassLoadConfig().getClassLoader();
+
+ Enumeration resources = classLoader.getResources("ebean.xml");
+
+ List mappings = new ArrayList();
+ while (resources.hasMoreElements()) {
+ URL url = resources.nextElement();
+ InputStream is = url.openStream();
+ mappings.add(XmlMappingReader.read(is));
+ is.close();
+ }
+
+ for (XmEbean mapping : mappings) {
+ List entityDeploy = mapping.getEntity();
+ for (XmEntity deploy : entityDeploy) {
+ readEntityMapping(classLoader, deploy);
+ }
+ }
+
+ } catch (IOException e) {
+ throw new RuntimeException("Error reading ebean.xml", e);
+ }
+ }
+
+ private void readEntityMapping(ClassLoader classLoader, XmEntity entityDeploy) {
+
+ String entityClassName = entityDeploy.getClazz();
+ Class> entityClass;
+ try {
+ entityClass = Class.forName(entityClassName, false, classLoader);
+ } catch (Exception e) {
+ logger.error("Could not load entity bean class "+entityClassName+" for ebean.xml entry");
+ return;
+ }
+
+ DeployBeanInfo> info = deployInfoMap.get(entityClass);
+ if (info == null) {
+ logger.error("No entity bean for ebean.xml entry "+entityClassName);
+
+ } else {
+ for (XmRawSql sql : entityDeploy.getRawSql()) {
+ RawSqlBuilder builder = RawSqlBuilder.parse(sql.getQuery().getValue());
+ for (XmColumnMapping columnMapping : sql.getColumnMapping()) {
+ builder.columnMapping(columnMapping.getColumn(), columnMapping.getProperty());
+ }
+ for (XmAliasMapping aliasMapping : sql.getAliasMapping()) {
+ builder.tableAliasMapping(aliasMapping.getAlias(), aliasMapping.getProperty());
+ }
+ info.addRawSql(sql.getName(), builder.create());
+ }
+ }
+ }
+
/**
* Return the Encrypt key given the table and column name.
*/
@@ -569,7 +637,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
* Return the bean deploy info for the given class.
*/
public DeployBeanInfo getDeploy(Class cls) {
- return (DeployBeanInfo) deplyInfoMap.get(cls);
+ return (DeployBeanInfo) deployInfoMap.get(cls);
}
private void registerBeanDescriptor(BeanDescriptor> desc) {
@@ -601,12 +669,12 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (Class> entityClass : bootupClasses.getEntities()) {
DeployBeanInfo> info = createDeployBeanInfo(entityClass);
- deplyInfoMap.put(entityClass, info);
+ deployInfoMap.put(entityClass, info);
}
for (Class> entityClass : bootupClasses.getEmbeddables()) {
DeployBeanInfo> info = createDeployBeanInfo(entityClass);
readDeployAssociations(info);
- deplyInfoMap.put(entityClass, info);
+ deployInfoMap.put(entityClass, info);
}
}
@@ -618,7 +686,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private void readEntityBeanTable() {
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
BeanTable beanTable = createBeanTable(info);
beanTableMap.put(beanTable.getBeanType(), beanTable);
}
@@ -632,18 +700,18 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
*/
private void readEntityDeploymentAssociations() {
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
readDeployAssociations(info);
}
}
private void readInheritedIdGenerators() {
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
DeployBeanDescriptor> descriptor = info.getDescriptor();
InheritInfo inheritInfo = descriptor.getInheritInfo();
if (inheritInfo != null && !inheritInfo.isRoot()) {
- DeployBeanInfo> rootBeanInfo = deplyInfoMap.get(inheritInfo.getRoot().getType());
+ DeployBeanInfo> rootBeanInfo = deployInfoMap.get(inheritInfo.getRoot().getType());
PlatformIdGenerator rootIdGen = rootBeanInfo.getDescriptor().getIdGenerator();
if (rootIdGen != null) {
descriptor.setIdGenerator(rootIdGen);
@@ -668,20 +736,20 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
// We only perform 'circular' checks etc after we have
// all the DeployBeanDescriptors created and in the map.
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
checkMappedBy(info);
}
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
secondaryPropsJoins(info);
}
// Set inheritance info
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
setInheritanceInfo(info);
}
- for (DeployBeanInfo> info : deplyInfoMap.values()) {
+ for (DeployBeanInfo> info : deployInfoMap.values()) {
registerBeanDescriptor(new BeanDescriptor(this, info.getDescriptor()));
}
}
@@ -695,7 +763,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (DeployBeanPropertyAssocOne> oneProp : info.getDescriptor().propertiesAssocOne()) {
if (!oneProp.isTransient()) {
- DeployBeanInfo> assoc = deplyInfoMap.get(oneProp.getTargetType());
+ DeployBeanInfo> assoc = deployInfoMap.get(oneProp.getTargetType());
if (assoc != null) {
oneProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
}
@@ -704,7 +772,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
for (DeployBeanPropertyAssocMany> manyProp : info.getDescriptor().propertiesAssocMany()) {
if (!manyProp.isTransient()) {
- DeployBeanInfo> assoc = deplyInfoMap.get(manyProp.getTargetType());
+ DeployBeanInfo> assoc = deployInfoMap.get(manyProp.getTargetType());
if (assoc != null) {
manyProp.getTableJoin().setInheritInfo(assoc.getDescriptor().getInheritInfo());
}
@@ -763,7 +831,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
private DeployBeanDescriptor> getTargetDescriptor(DeployBeanPropertyAssoc> prop) {
Class> targetType = prop.getTargetType();
- DeployBeanInfo> info = deplyInfoMap.get(targetType);
+ DeployBeanInfo> info = deployInfoMap.get(targetType);
if (info == null) {
String msg = "Can not find descriptor [" + targetType + "] for " + prop.getFullBeanName();
throw new PersistenceException(msg);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
index f087c3cb3..7083e727e 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
@@ -322,7 +322,7 @@ public abstract class BeanPropertyAssoc extends BeanProperty {
BeanProperty idProp = target.getIdProperty();
BeanProperty[] others = target.propertiesBaseScalar();
- if (descriptor.isSqlSelectBased()) {
+ if (descriptor.isRawSqlBased()) {
String dbColumn = owner.getDbColumn();
return new ImportedIdSimple(owner, dbColumn, idProp, 0);
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
index 3fd22f4da..fdcba6adb 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanDescriptor.java
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.deploy.meta;
+import com.avaje.ebean.RawSql;
import com.avaje.ebean.annotation.Cache;
import com.avaje.ebean.annotation.DocStore;
import com.avaje.ebean.annotation.DocStoreMode;
@@ -35,14 +36,18 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
* Describes Beans including their deployment information.
*/
public class DeployBeanDescriptor {
+ private static final Map EMPTY_RAW_MAP = new HashMap();
+
private static class PropOrder implements Comparator {
public int compare(DeployBeanProperty o1, DeployBeanProperty o2) {
@@ -66,6 +71,8 @@ public class DeployBeanDescriptor {
*/
private LinkedHashMap propMap = new LinkedHashMap();
+ private Map namedRawSql;
+
private EntityType entityType;
private DeployBeanPropertyAssocOne> unidirectional;
@@ -1047,4 +1054,21 @@ public class DeployBeanDescriptor {
if (docStorePersist != DocStoreMode.DEFAULT) return docStorePersist;
return serverConfig.getDocStoreConfig().getPersist();
}
+
+ /**
+ * Return the named RawSql queries.
+ */
+ public Map getNamedRawSql() {
+ return (namedRawSql != null) ? namedRawSql : EMPTY_RAW_MAP;
+ }
+
+ /**
+ * Add a named RawSql from ebean.xml file.
+ */
+ public void addRawSql(String name, RawSql rawSql) {
+ if (namedRawSql == null) {
+ namedRawSql = new HashMap();
+ }
+ namedRawSql.put(name, rawSql);
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployBeanInfo.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployBeanInfo.java
index 1b1b58911..532ddde2d 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployBeanInfo.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/parse/DeployBeanInfo.java
@@ -1,12 +1,13 @@
package com.avaje.ebeaninternal.server.deploy.parse;
-import java.util.HashMap;
-
+import com.avaje.ebean.RawSql;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
+import java.util.HashMap;
+
/**
* Wraps information about a bean during deployment parsing.
*/
@@ -75,4 +76,10 @@ public class DeployBeanInfo {
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
}
+ /**
+ * Add named RawSql from ebean.xml.
+ */
+ public void addRawSql(String name, RawSql rawSql) {
+ descriptor.addRawSql(name, rawSql);
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java
index 8829c10cb..acef03d9e 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/query/SqlTreeNodeBean.java
@@ -128,7 +128,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
// the bean has an Id property and we want to use it
this.readId = withId && (desc.getIdProperty() != null);
- this.disableLazyLoad = disableLazyLoad || !readId || desc.isSqlSelectBased() || temporalVersions;
+ this.disableLazyLoad = disableLazyLoad || !readId || desc.isRawSqlBased() || temporalVersions;
this.partialObject = props.isPartialObject();
this.properties = props.getProps();
diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
index 4d74c5043..c2dec2647 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java
@@ -38,6 +38,8 @@ import java.util.Set;
*/
public class DefaultOrmQuery implements SpiQuery {
+ public static final String DEFAULT_QUERY_NAME = "default";
+
private final Class beanType;
private final BeanDescriptor beanDescriptor;
@@ -699,6 +701,13 @@ public class DefaultOrmQuery implements SpiQuery {
return forUpdate;
}
+ @Override
+ public void setDefaultRawSqlIfRequired() {
+ if (beanDescriptor.isRawSqlBased() && rawSql == null) {
+ rawSql = beanDescriptor.getNamedRawSql(DEFAULT_QUERY_NAME);
+ }
+ }
+
@Override
public DefaultOrmQuery setAutoTune(boolean autoTune) {
this.autoTune = autoTune;
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/XmlMappingReader.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/XmlMappingReader.java
new file mode 100644
index 000000000..72c29da08
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/XmlMappingReader.java
@@ -0,0 +1,27 @@
+package com.avaje.ebeaninternal.xmlmapping;
+
+import com.avaje.ebeaninternal.xmlmapping.model.XmEbean;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import java.io.InputStream;
+
+public class XmlMappingReader {
+
+
+ /**
+ * Read and return a Migration from an xml document.
+ */
+ public static XmEbean read(InputStream is) {
+
+ try {
+ JAXBContext jaxbContext = JAXBContext.newInstance(XmEbean.class);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ return (XmEbean) unmarshaller.unmarshal(is);
+
+ } catch (JAXBException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/ObjectFactory.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/ObjectFactory.java
new file mode 100644
index 000000000..38151f817
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/ObjectFactory.java
@@ -0,0 +1,80 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import javax.xml.bind.annotation.XmlRegistry;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the com.avaje.ebeaninternal.xmlmapping.model package.
+ * An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.avaje.ebeaninternal.xmlmapping.model
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link XmRawSql }
+ *
+ */
+ public XmRawSql createRawSql() {
+ return new XmRawSql();
+ }
+
+ /**
+ * Create an instance of {@link XmAliasMapping }
+ *
+ */
+ public XmAliasMapping createAliasMapping() {
+ return new XmAliasMapping();
+ }
+
+ /**
+ * Create an instance of {@link XmColumnMapping }
+ *
+ */
+ public XmColumnMapping createColumnMapping() {
+ return new XmColumnMapping();
+ }
+
+ /**
+ * Create an instance of {@link XmQuery }
+ *
+ */
+ public XmQuery createQuery() {
+ return new XmQuery();
+ }
+
+ /**
+ * Create an instance of {@link XmEbean }
+ *
+ */
+ public XmEbean createEbean() {
+ return new XmEbean();
+ }
+
+ /**
+ * Create an instance of {@link XmEntity }
+ *
+ */
+ public XmEntity createEntity() {
+ return new XmEntity();
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmAliasMapping.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmAliasMapping.java
new file mode 100644
index 000000000..d28e745c8
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmAliasMapping.java
@@ -0,0 +1,87 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ *
Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <attribute name="alias" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="property" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "")
+@XmlRootElement(name = "alias-mapping")
+public class XmAliasMapping {
+
+ @XmlAttribute(name = "alias", required = true)
+ protected String alias;
+ @XmlAttribute(name = "property", required = true)
+ protected String property;
+
+ /**
+ * Gets the value of the alias property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getAlias() {
+ return alias;
+ }
+
+ /**
+ * Sets the value of the alias property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setAlias(String value) {
+ this.alias = value;
+ }
+
+ /**
+ * Gets the value of the property property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ /**
+ * Sets the value of the property property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setProperty(String value) {
+ this.property = value;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmColumnMapping.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmColumnMapping.java
new file mode 100644
index 000000000..f00f8664d
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmColumnMapping.java
@@ -0,0 +1,87 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <attribute name="column" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * <attribute name="property" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "")
+@XmlRootElement(name = "column-mapping")
+public class XmColumnMapping {
+
+ @XmlAttribute(name = "column", required = true)
+ protected String column;
+ @XmlAttribute(name = "property", required = true)
+ protected String property;
+
+ /**
+ * Gets the value of the column property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getColumn() {
+ return column;
+ }
+
+ /**
+ * Sets the value of the column property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setColumn(String value) {
+ this.column = value;
+ }
+
+ /**
+ * Gets the value of the property property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getProperty() {
+ return property;
+ }
+
+ /**
+ * Sets the value of the property property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setProperty(String value) {
+ this.property = value;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEbean.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEbean.java
new file mode 100644
index 000000000..b0fb313b2
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEbean.java
@@ -0,0 +1,71 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://ebean-orm.github.io/xml/ns/ebean}entity" maxOccurs="unbounded"/>
+ * </sequence>
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "entity"
+})
+@XmlRootElement(name = "ebean")
+public class XmEbean {
+
+ @XmlElement(required = true)
+ protected List entity;
+
+ /**
+ * Gets the value of the entity property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set method for the entity property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getEntity().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link XmEntity }
+ *
+ *
+ */
+ public List getEntity() {
+ if (entity == null) {
+ entity = new ArrayList();
+ }
+ return this.entity;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEntity.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEntity.java
new file mode 100644
index 000000000..c7779e48f
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmEntity.java
@@ -0,0 +1,99 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://ebean-orm.github.io/xml/ns/ebean}raw-sql" maxOccurs="unbounded"/>
+ * </sequence>
+ * <attribute name="class" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "rawSql"
+})
+@XmlRootElement(name = "entity")
+public class XmEntity {
+
+ @XmlElement(name = "raw-sql", required = true)
+ protected List rawSql;
+ @XmlAttribute(name = "class", required = true)
+ protected String clazz;
+
+ /**
+ * Gets the value of the rawSql property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set method for the rawSql property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getRawSql().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link XmRawSql }
+ *
+ *
+ */
+ public List getRawSql() {
+ if (rawSql == null) {
+ rawSql = new ArrayList();
+ }
+ return this.rawSql;
+ }
+
+ /**
+ * Gets the value of the clazz property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getClazz() {
+ return clazz;
+ }
+
+ /**
+ * Sets the value of the clazz property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setClazz(String value) {
+ this.clazz = value;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmQuery.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmQuery.java
new file mode 100644
index 000000000..f331726ed
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmQuery.java
@@ -0,0 +1,61 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ * Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <simpleContent>
+ * <extension base="<http://www.w3.org/2001/XMLSchema>string">
+ * </extension>
+ * </simpleContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "value"
+})
+@XmlRootElement(name = "query")
+public class XmQuery {
+
+ @XmlValue
+ protected String value;
+
+ /**
+ * Gets the value of the value property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Sets the value of the value property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmRawSql.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmRawSql.java
new file mode 100644
index 000000000..ec79bdb66
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/XmRawSql.java
@@ -0,0 +1,160 @@
+
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * Java class for anonymous complex type.
+ *
+ *
The following schema fragment specifies the expected content contained within this class.
+ *
+ *
+ * <complexType>
+ * <complexContent>
+ * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * <sequence>
+ * <element ref="{http://ebean-orm.github.io/xml/ns/ebean}alias-mapping" maxOccurs="unbounded" minOccurs="0"/>
+ * <element ref="{http://ebean-orm.github.io/xml/ns/ebean}column-mapping" maxOccurs="unbounded" minOccurs="0"/>
+ * <element ref="{http://ebean-orm.github.io/xml/ns/ebean}query"/>
+ * </sequence>
+ * <attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ * </restriction>
+ * </complexContent>
+ * </complexType>
+ *
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "aliasMapping",
+ "columnMapping",
+ "query"
+})
+@XmlRootElement(name = "raw-sql")
+public class XmRawSql {
+
+ @XmlElement(name = "alias-mapping")
+ protected List aliasMapping;
+ @XmlElement(name = "column-mapping")
+ protected List columnMapping;
+ @XmlElement(required = true)
+ protected XmQuery query;
+ @XmlAttribute(name = "name", required = true)
+ protected String name;
+
+ /**
+ * Gets the value of the aliasMapping property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set method for the aliasMapping property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getAliasMapping().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link XmAliasMapping }
+ *
+ *
+ */
+ public List getAliasMapping() {
+ if (aliasMapping == null) {
+ aliasMapping = new ArrayList();
+ }
+ return this.aliasMapping;
+ }
+
+ /**
+ * Gets the value of the columnMapping property.
+ *
+ *
+ * This accessor method returns a reference to the live list,
+ * not a snapshot. Therefore any modification you make to the
+ * returned list will be present inside the JAXB object.
+ * This is why there is not a set method for the columnMapping property.
+ *
+ *
+ * For example, to add a new item, do as follows:
+ *
+ * getColumnMapping().add(newItem);
+ *
+ *
+ *
+ *
+ * Objects of the following type(s) are allowed in the list
+ * {@link XmColumnMapping }
+ *
+ *
+ */
+ public List getColumnMapping() {
+ if (columnMapping == null) {
+ columnMapping = new ArrayList();
+ }
+ return this.columnMapping;
+ }
+
+ /**
+ * Gets the value of the query property.
+ *
+ * @return
+ * possible object is
+ * {@link XmQuery }
+ *
+ */
+ public XmQuery getQuery() {
+ return query;
+ }
+
+ /**
+ * Sets the value of the query property.
+ *
+ * @param value
+ * allowed object is
+ * {@link XmQuery }
+ *
+ */
+ public void setQuery(XmQuery value) {
+ this.query = value;
+ }
+
+ /**
+ * Gets the value of the name property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the value of the name property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setName(String value) {
+ this.name = value;
+ }
+
+}
diff --git a/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/package-info.java b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/package-info.java
new file mode 100644
index 000000000..88e0fda8f
--- /dev/null
+++ b/src/main/java/com/avaje/ebeaninternal/xmlmapping/model/package-info.java
@@ -0,0 +1,2 @@
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://ebean-orm.github.io/xml/ns/ebean", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package com.avaje.ebeaninternal.xmlmapping.model;
diff --git a/src/main/resources/ebean-1.0.xsd b/src/main/resources/ebean-1.0.xsd
new file mode 100644
index 000000000..970e3c605
--- /dev/null
+++ b/src/main/resources/ebean-1.0.xsd
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java
index 15408af46..1273014ad 100644
--- a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java
+++ b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java
@@ -285,6 +285,11 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
return null;
}
+ @Override
+ public Query createNamedQuery(Class beanType, String namedQuery) {
+ return null;
+ }
+
@Override
public Query createQuery(Class beanType) {
return null;
diff --git a/src/test/java/com/avaje/ebeaninternal/xmlmapping/model/XmlMappingReaderTest.java b/src/test/java/com/avaje/ebeaninternal/xmlmapping/model/XmlMappingReaderTest.java
new file mode 100644
index 000000000..72371a959
--- /dev/null
+++ b/src/test/java/com/avaje/ebeaninternal/xmlmapping/model/XmlMappingReaderTest.java
@@ -0,0 +1,21 @@
+package com.avaje.ebeaninternal.xmlmapping.model;
+
+import com.avaje.ebeaninternal.xmlmapping.XmlMappingReader;
+import org.junit.Test;
+
+import java.io.InputStream;
+
+import static org.junit.Assert.assertNotNull;
+
+public class XmlMappingReaderTest {
+
+ @Test
+ public void read() throws Exception {
+
+ InputStream is = XmlMappingReaderTest.class.getResourceAsStream("/test-ebean.xml");
+ XmEbean testMapping = XmlMappingReader.read(is);
+
+ assertNotNull(testMapping);
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/com/avaje/tests/basic/TestOrderTotalAmountReportBean.java b/src/test/java/com/avaje/tests/basic/TestOrderTotalAmountReportBean.java
index ddcf8cf98..b7860faaf 100644
--- a/src/test/java/com/avaje/tests/basic/TestOrderTotalAmountReportBean.java
+++ b/src/test/java/com/avaje/tests/basic/TestOrderTotalAmountReportBean.java
@@ -14,6 +14,7 @@ import com.avaje.tests.model.basic.OrderAggregate;
import com.avaje.tests.model.basic.ResetBasicData;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
public class TestOrderTotalAmountReportBean extends BaseTestCase {
@@ -73,5 +74,61 @@ public class TestOrderTotalAmountReportBean extends BaseTestCase {
assertThat(query.getGeneratedSql()).contains("count(*) as total_items, sum(order_qty*unit_price) as total_amount");
}
+ @Test
+ public void testDefaultNamedRawSql() {
+ Query query = Ebean.find(OrderAggregate.class);
+ List list = query.findList();
+
+ assertThat(query.getGeneratedSql()).contains("count(*) as total_items, sum(order_qty*unit_price) as total_amount");
+ assertNotNull(list);
+ }
+
+ @Test
+ public void testNamedRawSql() {
+
+ ResetBasicData.reset();
+
+ Query query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withMax");
+ List list = query.findList();
+
+ assertThat(query.getGeneratedSql()).contains("count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount from o_order_detail");
+ assertNotNull(list);
+ }
+
+ @Test
+ public void testNamedRawSql_with_extraPredicates() {
+
+ ResetBasicData.reset();
+
+ Query query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withMax");
+ List list = query
+ .where().gt("order.id", 1)
+ .having().gt("totalItems", 1)
+ .order().desc("totalAmount")
+ .findList();
+
+ assertThat(query.getGeneratedSql()).contains("count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount from o_order_detail");
+ assertThat(query.getGeneratedSql()).contains("from o_order_detail where order_id > ? group by order_id having count(*) > ? order by sum(order_qty*unit_price) desc");
+ assertNotNull(list);
+ }
+
+ @Test
+ public void testNamedRawSql_with_param() {
+
+ ResetBasicData.reset();
+
+ Query query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withParam");
+ List list = query
+ .setParameter("minId", 2)
+ .where().isNotNull("order.id")
+ .having().lt("totalAmount", 100)
+ .order().desc("totalAmount")
+ .setMaxRows(10)
+ .findList();
+
+ assertThat(query.getGeneratedSql()).contains("count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount from o_order_detail");
+ assertThat(query.getGeneratedSql()).contains("from o_order_detail where id > ? and order_id is not null group by order_id having sum(order_qty*unit_price) < ? order by sum(order_qty*unit_price) desc");
+ assertNotNull(list);
+ }
}
diff --git a/src/test/java/com/avaje/tests/model/basic/OrderAggregate.java b/src/test/java/com/avaje/tests/model/basic/OrderAggregate.java
index f22b95d77..b64c6e887 100644
--- a/src/test/java/com/avaje/tests/model/basic/OrderAggregate.java
+++ b/src/test/java/com/avaje/tests/model/basic/OrderAggregate.java
@@ -19,9 +19,11 @@ public class OrderAggregate {
@OneToOne
Order order;
+ Double maxAmount;
+
Double totalAmount;
- Double totalItems;
+ Long totalItems;
public String toString() {
return order.getId() + " totalAmount:" + totalAmount + " totalItems:" + totalItems;
@@ -43,11 +45,19 @@ public class OrderAggregate {
this.totalAmount = totalAmount;
}
- public Double getTotalItems() {
+ public Long getTotalItems() {
return totalItems;
}
- public void setTotalItems(Double totalItems) {
+ public void setTotalItems(Long totalItems) {
this.totalItems = totalItems;
}
+
+ public Double getMaxAmount() {
+ return maxAmount;
+ }
+
+ public void setMaxAmount(Double maxAmount) {
+ this.maxAmount = maxAmount;
+ }
}
diff --git a/src/test/java/com/avaje/tests/rawsql/TestRawSqlOrmQuery.java b/src/test/java/com/avaje/tests/rawsql/TestRawSqlOrmQuery.java
index 9f1b23097..3ae69818f 100644
--- a/src/test/java/com/avaje/tests/rawsql/TestRawSqlOrmQuery.java
+++ b/src/test/java/com/avaje/tests/rawsql/TestRawSqlOrmQuery.java
@@ -22,6 +22,25 @@ import static org.assertj.core.api.Assertions.assertThat;
public class TestRawSqlOrmQuery extends BaseTestCase {
+ @Test
+ public void testNamed() {
+
+ ResetBasicData.reset();
+
+ Query query = Ebean.createNamedQuery(Order.class, "myRawTest");
+ query.setParameter("orderStatus", Order.Status.NEW);
+ query.setMaxRows(10);
+ List list = query.findList();
+ for (Order order : list) {
+ order.getCretime();
+ }
+
+ String sql = query.getGeneratedSql();
+ assertThat(sql).contains("select o.id, o.status, o.ship_date, c.id, c.name, a.id, a.line_1, a.line_2, a.city from o_order o");
+ assertThat(sql).contains("join o_customer c on o.kcustomer_id = c.id ");
+ assertThat(sql).contains("where o.status = ? order by c.name, c.id");
+ }
+
@Test
public void test() {
diff --git a/src/test/resources/META-INF/ebean-orm.xml b/src/test/resources/META-INF/ebean-orm.xml
deleted file mode 100644
index e2c1407ec..000000000
--- a/src/test/resources/META-INF/ebean-orm.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
- select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
- from o_order_detail
- group by order_id
-
-
-
-
-
-
- select order_id, sum(order_qty*unit_price) as totalAmount
- from o_order_detail
- group by order_id
-
-
-
-
- select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
- from o_order_detail
- group by order_id
-
-
-
-
- select order_id, sum(order_qty*unit_price) as total_amount
- from o_order_detail
- group by order_id
-
-
-
-
-
-
-
-
-
- select id, name, 12 as myint from t_mapsuper1
-
-
-
-
-
-
-
-
- select order_id, count(*) as detailCount from o_order_detail group by order_id
-
-
-
-
-
\ No newline at end of file
diff --git a/src/test/resources/ebean.xml b/src/test/resources/ebean.xml
new file mode 100644
index 000000000..8dcbf7c49
--- /dev/null
+++ b/src/test/resources/ebean.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+ select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
+ from o_order_detail
+ group by order_id
+
+
+
+
+
+
+ select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount
+ from o_order_detail
+ group by order_id
+
+
+
+
+
+
+ select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount, max(order_qty*unit_price) as maxAmount
+ from o_order_detail where id > :minId
+ group by order_id
+
+
+
+
+
+
+
+
+
+
+ select o.id, o.status, o.ship_date, c.id, c.name, a.id, a.line_1, a.line_2, a.city
+ from o_order o
+ join o_customer c on o.kcustomer_id = c.id
+ join o_address a on c.billing_address_id = a.id
+ where o.status = :orderStatus
+ order by c.name, c.id
+
+
+
+
+
diff --git a/src/test/resources/orm.xml b/src/test/resources/orm.xml
deleted file mode 100644
index 54bcd91d0..000000000
--- a/src/test/resources/orm.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-com.avaje.tests.model.basic
-
-
-
-
- find order
- join customer (name)
- join customer.billingAddress (*)
- join details
- join details.product (sku, name)
- order by customer.name asc
- limit 10
-
-
-
-
- find order
- join customer (name)
- join customer.billingAddress (*)
- join details
- join details.product (sku, name)
- order by customer.name asc
- limit 10
-
-
-
-
-
-
- select * from o_order where id = :id
-
-
-
-
-
\ No newline at end of file
diff --git a/src/test/resources/test-ebean.xml b/src/test/resources/test-ebean.xml
new file mode 100644
index 000000000..d28c6ab52
--- /dev/null
+++ b/src/test/resources/test-ebean.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
+ from o_order_detail
+ group by order_id
+
+
+
+
+
+ select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
+ from o_order_detail
+ group by order_id
+
+
+
+
+