mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-25 07:57:39 +00:00
#765 - ENH: Add ebean.xml with support for named RawSql, also adds EbeanServer.createNamedQuery()
This commit is contained in:
@@ -945,6 +945,21 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
* </p>
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query for a type of entity bean.
|
||||
* <p>
|
||||
|
||||
@@ -199,6 +199,19 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> UpdateQuery<T> update(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
* </p>
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
<T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
|
||||
|
||||
/**
|
||||
* Create a query for an entity bean and synonym for {@link #find(Class)}.
|
||||
*
|
||||
|
||||
@@ -564,6 +564,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
@@ -887,6 +887,21 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return createQuery(beanType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
BeanDescriptor<T> 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<T> query = createQuery(beanType);
|
||||
query.setRawSql(rawSql);
|
||||
return query;
|
||||
}
|
||||
throw new PersistenceException("No named query called " + namedQuery + " for bean:" + beanType.getName());
|
||||
}
|
||||
|
||||
public <T> DefaultOrmQuery<T> createQuery(Class<T> beanType) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(beanType);
|
||||
if (desc == null) {
|
||||
@@ -945,6 +960,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
private <T> SpiOrmQueryRequest<T> createQueryRequest(SpiQuery<T> query, Transaction t) {
|
||||
|
||||
query.setDefaultRawSqlIfRequired();
|
||||
if (query.isAutoTunable() && !autoTuneService.tuneQuery(query)) {
|
||||
// use deployment FetchType.LAZY/EAGER annotations
|
||||
// to define the 'default' select clause
|
||||
|
||||
@@ -109,6 +109,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<String, ElComparator<T>>();
|
||||
|
||||
private final Map<String, RawSql> namedRawSql;
|
||||
|
||||
public void merge(EntityBean bean, EntityBean existing) {
|
||||
|
||||
EntityBeanIntercept fromEbi = bean._ebean_getIntercept();
|
||||
@@ -412,6 +414,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
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<T> implements MetaBeanInfo, BeanType<T> {
|
||||
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<T> implements MetaBeanInfo, BeanType<T> {
|
||||
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<T> implements MetaBeanInfo, BeanType<T> {
|
||||
* 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<T> implements MetaBeanInfo, BeanType<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* 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).
|
||||
* </p>
|
||||
* Returns true if this bean is based on RawSql.
|
||||
*/
|
||||
public boolean isSqlSelectBased() {
|
||||
return EntityType.SQL.equals(entityType);
|
||||
public boolean isRawSqlBased() {
|
||||
return EntityType.SQL == entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<Class<?>, DeployBeanInfo<?>> deplyInfoMap = new HashMap<Class<?>, DeployBeanInfo<?>>();
|
||||
private Map<Class<?>, DeployBeanInfo<?>> deployInfoMap = new HashMap<Class<?>, DeployBeanInfo<?>>();
|
||||
|
||||
private final Map<Class<?>, BeanTable> beanTableMap = new HashMap<Class<?>, 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<URL> resources = classLoader.getResources("ebean.xml");
|
||||
|
||||
List<XmEbean> mappings = new ArrayList<XmEbean>();
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
InputStream is = url.openStream();
|
||||
mappings.add(XmlMappingReader.read(is));
|
||||
is.close();
|
||||
}
|
||||
|
||||
for (XmEbean mapping : mappings) {
|
||||
List<XmEntity> 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 <T> DeployBeanInfo<T> getDeploy(Class<T> cls) {
|
||||
return (DeployBeanInfo<T>) deplyInfoMap.get(cls);
|
||||
return (DeployBeanInfo<T>) 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);
|
||||
|
||||
@@ -322,7 +322,7 @@ public abstract class BeanPropertyAssoc<T> 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);
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
|
||||
private static final Map<String, RawSql> EMPTY_RAW_MAP = new HashMap<String, RawSql>();
|
||||
|
||||
private static class PropOrder implements Comparator<DeployBeanProperty> {
|
||||
|
||||
public int compare(DeployBeanProperty o1, DeployBeanProperty o2) {
|
||||
@@ -66,6 +71,8 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
private LinkedHashMap<String, DeployBeanProperty> propMap = new LinkedHashMap<String, DeployBeanProperty>();
|
||||
|
||||
private Map<String, RawSql> namedRawSql;
|
||||
|
||||
private EntityType entityType;
|
||||
|
||||
private DeployBeanPropertyAssocOne<?> unidirectional;
|
||||
@@ -1047,4 +1054,21 @@ public class DeployBeanDescriptor<T> {
|
||||
if (docStorePersist != DocStoreMode.DEFAULT) return docStorePersist;
|
||||
return serverConfig.getDocStoreConfig().getPersist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the named RawSql queries.
|
||||
*/
|
||||
public Map<String, RawSql> 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<String, RawSql>();
|
||||
}
|
||||
namedRawSql.put(name, rawSql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<T> {
|
||||
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named RawSql from ebean.xml.
|
||||
*/
|
||||
public void addRawSql(String name, RawSql rawSql) {
|
||||
descriptor.addRawSql(name, rawSql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -38,6 +38,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
public static final String DEFAULT_QUERY_NAME = "default";
|
||||
|
||||
private final Class<T> beanType;
|
||||
|
||||
private final BeanDescriptor<T> beanDescriptor;
|
||||
@@ -699,6 +701,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return forUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultRawSqlIfRequired() {
|
||||
if (beanDescriptor.isRawSqlBased() && rawSql == null) {
|
||||
rawSql = beanDescriptor.getNamedRawSql(DEFAULT_QUERY_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> setAutoTune(boolean autoTune) {
|
||||
this.autoTune = autoTune;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
* <p>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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <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>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <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>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <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>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"entity"
|
||||
})
|
||||
@XmlRootElement(name = "ebean")
|
||||
public class XmEbean {
|
||||
|
||||
@XmlElement(required = true)
|
||||
protected List<XmEntity> entity;
|
||||
|
||||
/**
|
||||
* Gets the value of the entity property.
|
||||
*
|
||||
* <p>
|
||||
* 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 <CODE>set</CODE> method for the entity property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getEntity().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link XmEntity }
|
||||
*
|
||||
*
|
||||
*/
|
||||
public List<XmEntity> getEntity() {
|
||||
if (entity == null) {
|
||||
entity = new ArrayList<XmEntity>();
|
||||
}
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <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>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"rawSql"
|
||||
})
|
||||
@XmlRootElement(name = "entity")
|
||||
public class XmEntity {
|
||||
|
||||
@XmlElement(name = "raw-sql", required = true)
|
||||
protected List<XmRawSql> rawSql;
|
||||
@XmlAttribute(name = "class", required = true)
|
||||
protected String clazz;
|
||||
|
||||
/**
|
||||
* Gets the value of the rawSql property.
|
||||
*
|
||||
* <p>
|
||||
* 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 <CODE>set</CODE> method for the rawSql property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getRawSql().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link XmRawSql }
|
||||
*
|
||||
*
|
||||
*/
|
||||
public List<XmRawSql> getRawSql() {
|
||||
if (rawSql == null) {
|
||||
rawSql = new ArrayList<XmRawSql>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <simpleContent>
|
||||
* <extension base="<http://www.w3.org/2001/XMLSchema>string">
|
||||
* </extension>
|
||||
* </simpleContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <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>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"aliasMapping",
|
||||
"columnMapping",
|
||||
"query"
|
||||
})
|
||||
@XmlRootElement(name = "raw-sql")
|
||||
public class XmRawSql {
|
||||
|
||||
@XmlElement(name = "alias-mapping")
|
||||
protected List<XmAliasMapping> aliasMapping;
|
||||
@XmlElement(name = "column-mapping")
|
||||
protected List<XmColumnMapping> columnMapping;
|
||||
@XmlElement(required = true)
|
||||
protected XmQuery query;
|
||||
@XmlAttribute(name = "name", required = true)
|
||||
protected String name;
|
||||
|
||||
/**
|
||||
* Gets the value of the aliasMapping property.
|
||||
*
|
||||
* <p>
|
||||
* 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 <CODE>set</CODE> method for the aliasMapping property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getAliasMapping().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link XmAliasMapping }
|
||||
*
|
||||
*
|
||||
*/
|
||||
public List<XmAliasMapping> getAliasMapping() {
|
||||
if (aliasMapping == null) {
|
||||
aliasMapping = new ArrayList<XmAliasMapping>();
|
||||
}
|
||||
return this.aliasMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the columnMapping property.
|
||||
*
|
||||
* <p>
|
||||
* 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 <CODE>set</CODE> method for the columnMapping property.
|
||||
*
|
||||
* <p>
|
||||
* For example, to add a new item, do as follows:
|
||||
* <pre>
|
||||
* getColumnMapping().add(newItem);
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* Objects of the following type(s) are allowed in the list
|
||||
* {@link XmColumnMapping }
|
||||
*
|
||||
*
|
||||
*/
|
||||
public List<XmColumnMapping> getColumnMapping() {
|
||||
if (columnMapping == null) {
|
||||
columnMapping = new ArrayList<XmColumnMapping>();
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -0,0 +1,59 @@
|
||||
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns="http://ebean-orm.github.io/xml/ns/ebean"
|
||||
targetNamespace="http://ebean-orm.github.io/xml/ns/ebean" elementFormDefault="qualified">
|
||||
|
||||
<!-- Root level type : extra-ddl -->
|
||||
|
||||
<xsd:element name="ebean">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="entity" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="entity">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="raw-sql" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="class" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="raw-sql">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="alias-mapping" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element ref="column-mapping" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xsd:element ref="query" minOccurs="1" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="alias-mapping">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="property" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="column-mapping">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="column" type="xsd:string" use="required"/>
|
||||
<xsd:attribute name="property" type="xsd:string" use="required"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="query">
|
||||
<xsd:complexType>
|
||||
<xsd:simpleContent>
|
||||
<xsd:extension base="xsd:string">
|
||||
<!--<xsd:attribute name="class" type="xsd:string" use="required"/>-->
|
||||
</xsd:extension>
|
||||
</xsd:simpleContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
@@ -285,6 +285,11 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Query<T> createQuery(Class<T> beanType) {
|
||||
return null;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<OrderAggregate> query = Ebean.find(OrderAggregate.class);
|
||||
List<OrderAggregate> 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<OrderAggregate> query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withMax");
|
||||
List<OrderAggregate> 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<OrderAggregate> query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withMax");
|
||||
List<OrderAggregate> 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<OrderAggregate> query = Ebean.getDefaultServer().createNamedQuery(OrderAggregate.class, "withParam");
|
||||
List<OrderAggregate> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,25 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testNamed() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = Ebean.createNamedQuery(Order.class, "myRawTest");
|
||||
query.setParameter("orderStatus", Order.Status.NEW);
|
||||
query.setMaxRows(10);
|
||||
List<Order> 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() {
|
||||
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity-mappings>
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.OrderAggregate">
|
||||
<raw-sql name="default">
|
||||
<columnMapping column="order_id" property="order.id" />
|
||||
<query>
|
||||
select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
|
||||
<raw-sql name="total.amount">
|
||||
<columnMapping column="order_id" property="order.id" />
|
||||
<query>
|
||||
select order_id, sum(order_qty*unit_price) as totalAmount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
<sql-select name="total.qty">
|
||||
<query>
|
||||
select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</sql-select>
|
||||
<sql-select name="total">
|
||||
<query>
|
||||
select order_id, sum(order_qty*unit_price) as total_amount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</sql-select>
|
||||
</entity>
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.TMapSuperEntity">
|
||||
<raw-sql name="testTransient">
|
||||
<columnMapping column="id" property="id" />
|
||||
<columnMapping column="name" property="name" />
|
||||
<query>
|
||||
select id, name, 12 as myint from t_mapsuper1
|
||||
</query>
|
||||
</raw-sql>
|
||||
</entity>
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.MyAdHoc">
|
||||
<raw-sql name="default">
|
||||
<columnMapping column="order_id" property="order.id" />
|
||||
<query>
|
||||
select order_id, count(*) as detailCount from o_order_detail group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
</entity>
|
||||
|
||||
</entity-mappings>
|
||||
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ebean xmlns="http://ebean-orm.github.io/xml/ns/ebean">
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.OrderAggregate">
|
||||
<raw-sql name="default">
|
||||
<column-mapping column="order_id" property="order.id"/>
|
||||
<column-mapping column="total_items" property="totalItems"/>
|
||||
<column-mapping column="total_amount" property="totalAmount"/>
|
||||
<query>
|
||||
select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
|
||||
<raw-sql name="withMax">
|
||||
<column-mapping column="order_id" property="order.id"/>
|
||||
<query>
|
||||
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
|
||||
</query>
|
||||
</raw-sql>
|
||||
|
||||
<raw-sql name="withParam">
|
||||
<column-mapping column="order_id" property="order.id"/>
|
||||
<query>
|
||||
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
|
||||
</query>
|
||||
</raw-sql>
|
||||
|
||||
</entity>
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.Order">
|
||||
<raw-sql name="myRawTest">
|
||||
<alias-mapping alias="c" property="customer"/>
|
||||
<alias-mapping alias="a" property="customer.billingAddress"/>
|
||||
<query>
|
||||
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
|
||||
</query>
|
||||
</raw-sql>
|
||||
</entity>
|
||||
|
||||
</ebean>
|
||||
@@ -1,40 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd">
|
||||
|
||||
<package>com.avaje.tests.model.basic</package>
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.Order">
|
||||
<named-query name="top.open">
|
||||
<query>
|
||||
find order
|
||||
join customer (name)
|
||||
join customer.billingAddress (*)
|
||||
join details
|
||||
join details.product (sku, name)
|
||||
order by customer.name asc
|
||||
limit 10
|
||||
</query>
|
||||
</named-query>
|
||||
<named-query name="top.open">
|
||||
<query>
|
||||
find order
|
||||
join customer (name)
|
||||
join customer.billingAddress (*)
|
||||
join details
|
||||
join details.product (sku, name)
|
||||
order by customer.name asc
|
||||
limit 10
|
||||
</query>
|
||||
</named-query>
|
||||
</entity>
|
||||
|
||||
<named-native-query name="find.order">
|
||||
<query>
|
||||
select * from o_order where id = :id
|
||||
</query>
|
||||
</named-native-query>
|
||||
|
||||
|
||||
</entity-mappings>
|
||||
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<ebean xmlns="http://ebean-orm.github.io/xml/ns/ebean">
|
||||
|
||||
<entity class="com.avaje.tests.model.basic.OrderAggregate">
|
||||
<raw-sql name="default">
|
||||
<column-mapping column="order_id" property="order.id"/>
|
||||
<query>
|
||||
select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
<raw-sql name="default">
|
||||
<column-mapping column="order_id" property="order.id"/>
|
||||
<query>
|
||||
select order_id, count(*) as totalItems, sum(order_qty*unit_price) as totalAmount
|
||||
from o_order_detail
|
||||
group by order_id
|
||||
</query>
|
||||
</raw-sql>
|
||||
</entity>
|
||||
|
||||
</ebean>
|
||||
Reference in New Issue
Block a user