Fix for #209 - refresh() ... does not refresh OneToMany or ManyToMany properties

This commit is contained in:
rbygrave
2014-11-25 23:40:21 +13:00
parent d5d6ac675b
commit 6a6cff2236
27 changed files with 618 additions and 727 deletions
@@ -31,6 +31,13 @@ public interface BeanCollection<E> extends Serializable {
ALL
}
/**
* Reset the collection back to an empty state ready for reloading.
* <p>
* This is done as part of bean refresh.
*/
public void reset(EntityBean ownerBean, String propertyName);
/**
* Return true if the collection is empty and untouched. Used to detect if a
* collection was 'cleared' deliberately or just un-initialised.
@@ -47,14 +54,6 @@ public interface BeanCollection<E> extends Serializable {
*/
public String getPropertyName();
/**
* Return the index position of this collection in the lazy/query loader.
* <p>
* Used for batch loading of collections.
* </p>
*/
public int getLoaderIndex();
/**
* Check after the lazy load that the underlying collection is not null
* (handle case where join to many not outer).
@@ -108,11 +107,6 @@ public interface BeanCollection<E> extends Serializable {
*/
public void internalAdd(Object bean);
/**
* Returns the underlying List Set or Map object.
*/
public Object getActualCollection();
/**
* Return the number of elements in the List Set or Map.
*/
@@ -38,12 +38,12 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
/**
* The owning bean (used for lazy fetch).
*/
protected final EntityBean ownerBean;
protected EntityBean ownerBean;
/**
* The name of this property in the owning bean (used for lazy fetch).
*/
protected final String propertyName;
protected String propertyName;
protected ModifyHolder<E> modifyHolder;
@@ -62,8 +62,6 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
* Constructor not non-lazy loading collection.
*/
public AbstractBeanCollection() {
this.ownerBean = null;
this.propertyName = null;
}
/**
@@ -85,10 +83,6 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
return propertyName;
}
public int getLoaderIndex() {
return loaderIndex;
}
public ExpressionList<?> getFilterMany() {
return filterMany;
}
@@ -46,6 +46,14 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
super(loader, ownerBean, propertyName);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
this.propertyName = propertyName;
this.list = null;
this.touched = false;
}
@Override
public boolean isEmptyAndUntouched() {
return !touched && (list == null || list.isEmpty());
@@ -130,13 +138,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
return list;
}
/**
* Returns the underlying list.
*/
public Object getActualCollection() {
return list;
}
/**
* Return true if the underlying list is populated.
*/
@@ -39,7 +39,15 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
public BeanMap(BeanCollectionLoader ebeanServer, EntityBean ownerBean, String propertyName) {
super(ebeanServer, ownerBean, propertyName);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
this.propertyName = propertyName;
this.map = null;
this.touched = false;
}
public boolean isEmptyAndUntouched() {
return !touched && (map == null || map.isEmpty());
}
@@ -146,15 +154,8 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
}
/**
* Returns the underlying map.
*/
public Object getActualCollection() {
return map;
}
public String toString() {
StringBuffer sb = new StringBuffer(50);
StringBuilder sb = new StringBuilder(50);
sb.append("BeanMap ");
if (isReadOnly()) {
sb.append("readOnly ");
@@ -40,6 +40,14 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
super(loader, ownerBean, propertyName);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
this.propertyName = propertyName;
this.set = null;
this.touched = false;
}
public boolean isEmptyAndUntouched() {
return !touched && (set == null || set.isEmpty());
}
@@ -40,7 +40,7 @@ public class DefaultBeanLoader {
this.server = server;
}
/**
/**
* Return a batch size that might be less than the requestedBatchSize.
* <p>
* This means we can have large and variable requestedBatchSizes.
@@ -51,7 +51,7 @@ public class DefaultBeanLoader {
* </p>
*/
private int getBatchSize(int batchSize) {
if (batchSize == 1) {
// there is only one bean/collection to load
return 1;
@@ -74,10 +74,10 @@ public class DefaultBeanLoader {
}
return batchSize;
}
public void refreshMany(EntityBean parentBean, String propertyName) {
refreshMany(parentBean, propertyName, null);
}
public void refreshMany(EntityBean parentBean, String propertyName) {
refreshMany(parentBean, propertyName, null);
}
public void loadMany(LoadManyRequest loadRequest) {
@@ -113,7 +113,7 @@ public class DefaultBeanLoader {
if (orderBy != null) {
query.orderBy(orderBy);
}
String extraWhere = many.getExtraWhere();
if (extraWhere != null) {
// replace special ${ta} placeholder with the base table alias
@@ -121,7 +121,7 @@ public class DefaultBeanLoader {
String ew = StringHelper.replaceString(extraWhere, "${ta}", "t0");
query.where().raw(ew);
}
query.setLazyLoadForParents(idList, many);
many.addWhereParentIdIn(query, idList);
@@ -153,7 +153,7 @@ public class DefaultBeanLoader {
desc.cacheManyPropPut(many, bc, parentId);
}
}
// log the query (for testing secondary queries)
loadRequest.logSecondaryQuery(query);
}
@@ -163,18 +163,17 @@ public class DefaultBeanLoader {
EntityBean parentBean = bc.getOwnerBean();
String propertyName = bc.getPropertyName();
//ObjectGraphNode node = ctx == null ? null : ctx.getObjectGraphNode();
loadManyInternal(parentBean, propertyName, null, false, null, onlyIds);
}
public void refreshMany(EntityBean parentBean, String propertyName, Transaction t) {
loadManyInternal(parentBean, propertyName, t, true, null, false);
}
public void refreshMany(EntityBean parentBean, String propertyName, Transaction t) {
loadManyInternal(parentBean, propertyName, t, true, null, false);
}
private void loadManyInternal(EntityBean parentBean, String propertyName, Transaction t, boolean refresh, ObjectGraphNode node, boolean onlyIds) {
private void loadManyInternal(EntityBean parentBean, String propertyName, Transaction t, boolean refresh,
ObjectGraphNode node, boolean onlyIds) {
EntityBeanIntercept ebi = ((EntityBean) parentBean)._ebean_getIntercept();
EntityBeanIntercept ebi = parentBean._ebean_getIntercept();
PersistenceContext pc = ebi.getPersistenceContext();
BeanDescriptor<?> parentDesc = server.getBeanDescriptor(parentBean.getClass());
@@ -182,7 +181,7 @@ public class DefaultBeanLoader {
BeanCollection<?> beanCollection = null;
ExpressionList<?> filterMany = null;
Object currentValue = many.getValue(parentBean);
if (currentValue instanceof BeanCollection<?>) {
beanCollection = (BeanCollection<?>) currentValue;
@@ -211,7 +210,7 @@ public class DefaultBeanLoader {
if (refresh) {
// populate a new collection
Object emptyCollection = many.createEmpty(false);
BeanCollection<?> emptyCollection = many.createEmpty(parentBean);
many.setValue(parentBean, emptyCollection);
query.setLoadDescription("+refresh", null);
} else {
@@ -329,7 +328,7 @@ public class DefaultBeanLoader {
if (loadRequest.isLoadCache()) {
for (int i = 0; i < list.size(); i++) {
desc.cacheBeanPutData((EntityBean)list.get(i));
desc.cacheBeanPutData((EntityBean) list.get(i));
}
}
@@ -338,33 +337,38 @@ public class DefaultBeanLoader {
// necessary but allow processing to continue until it is accessed by client code
ebis[i].checkLazyLoadFailure();
}
// log the query (for testing secondary queries)
loadRequest.logSecondaryQuery(query);
}
public void refresh(EntityBean bean) {
refreshBeanInternal(bean, SpiQuery.Mode.REFRESH_BEAN, -1);
}
public void loadBean(EntityBeanIntercept ebi) {
refreshBeanInternal(ebi.getOwner(), SpiQuery.Mode.LAZYLOAD_BEAN, -1);
}
public void refresh(EntityBean bean) {
refreshBeanInternal(bean, SpiQuery.Mode.REFRESH_BEAN, -1);
}
public void loadBean(EntityBeanIntercept ebi) {
refreshBeanInternal(ebi.getOwner(), SpiQuery.Mode.LAZYLOAD_BEAN, -1);
}
private void refreshBeanInternal(EntityBean bean, SpiQuery.Mode mode, int embeddedOwnerIndex) {
EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();;
EntityBeanIntercept ebi = bean._ebean_getIntercept();
;
PersistenceContext pc = ebi.getPersistenceContext();
if (Mode.REFRESH_BEAN == mode) {
// need a new PersistenceContext for REFRESH
pc = null;
}
BeanDescriptor<?> desc = server.getBeanDescriptor(bean.getClass());
if (EntityType.EMBEDDED == desc.getEntityType()) {
// lazy loading on an embedded bean property
EntityBean embeddedOwner = (EntityBean)ebi.getEmbeddedOwner();
EntityBean embeddedOwner = (EntityBean) ebi.getEmbeddedOwner();
int ownerIndex = ebi.getEmbeddedOwnerIndex();
refreshBeanInternal(embeddedOwner, mode, ownerIndex);
}
Object id = desc.getId(bean);
if (pc == null) {
@@ -379,7 +383,7 @@ public class DefaultBeanLoader {
if (embeddedOwnerIndex == -1) {
if (SpiQuery.Mode.LAZYLOAD_BEAN.equals(mode) && desc.isBeanCaching()) {
// lazy loading and the bean cache is active
if (desc.cacheBeanLoad((EntityBean)bean, ebi, id)) {
if (desc.cacheBeanLoad(bean, ebi, id)) {
return;
}
}
@@ -395,9 +399,9 @@ public class DefaultBeanLoader {
if (embeddedOwnerIndex > -1) {
String embeddedBeanPropertyName = ebi.getProperty(embeddedOwnerIndex);
query.select("id,"+embeddedBeanPropertyName);
query.select("id," + embeddedBeanPropertyName);
}
// don't collect autoFetch usage profiling information
// as we just copy the data out of these fetched beans
// and put the data into the original bean
@@ -415,7 +419,7 @@ public class DefaultBeanLoader {
if (ebi.isReadOnly()) {
query.setReadOnly(true);
}
if (SpiQuery.Mode.REFRESH_BEAN.equals(mode)) {
// explicitly state to load all properties on REFRESH.
// Lobs default to fetch lazy so this forces lobs to be
@@ -429,5 +433,7 @@ public class DefaultBeanLoader {
throw new EntityNotFoundException(msg);
}
desc.resetManyProperties(dbBean);
}
}
@@ -1,8 +1,5 @@
package com.avaje.ebeaninternal.server.deploy;
import java.io.IOException;
import java.util.Iterator;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Query;
import com.avaje.ebean.Transaction;
@@ -12,6 +9,8 @@ import com.avaje.ebean.bean.BeanCollectionLoader;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import java.io.IOException;
/**
* Helper functions for performing tasks on Lists Sets or Maps.
*/
@@ -30,15 +29,15 @@ public interface BeanCollectionHelp<T> {
*/
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey);
/**
* Create an empty collection of the correct type without a parent bean.
*/
public BeanCollection<T> createEmptyNoParent();
/**
* Create an empty collection of the correct type.
*/
public Object createEmpty(boolean vanilla);
/**
* Create an iterator for reading the entries.
*/
public Iterator<?> getIterator(Object collection);
public BeanCollection<T> createEmpty(EntityBean bean);
/**
* Add a bean to the List Set or Map.
@@ -48,7 +47,7 @@ public interface BeanCollectionHelp<T> {
/**
* Create a lazy loading proxy for a List Set or Map.
*/
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName);
public BeanCollection<T> createReference(EntityBean parentBean);
/**
* Refresh the List Set or Map.
@@ -9,6 +9,10 @@ import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
*/
public class BeanCollectionHelpFactory {
static final BeanListHelp LIST_HELP = new BeanListHelp();
static final BeanSetHelp SET_HELP = new BeanSetHelp();
/**
* Create the helper based on the many property.
*/
@@ -33,10 +37,10 @@ public class BeanCollectionHelpFactory {
SpiQuery.Type manyType = request.getQuery().getType();
if (manyType.equals(SpiQuery.Type.LIST)){
return new BeanListHelp<T>();
return LIST_HELP;
} else if (manyType.equals(SpiQuery.Type.SET)) {
return new BeanSetHelp<T>();
return SET_HELP;
} else {
BeanDescriptor<T> target = request.getBeanDescriptor();
@@ -1487,6 +1487,17 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
return prop;
}
/**
* Reset the many properties to empty state ready for reloading.
*/
public void resetManyProperties(Object dbBean) {
EntityBean bean = (EntityBean)dbBean;
for (int i = 0; i < propertiesMany.length; i++) {
propertiesMany[i].resetMany(bean);
}
}
/**
* Return the name of the server this BeanDescriptor belongs to.
*/
@@ -22,29 +22,36 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private final String propertyName;
private BeanCollectionLoader loader;
public BeanListHelp(BeanPropertyAssocMany<T> many) {
this.many = many;
this.targetDescriptor = many.getTargetDescriptor();
this.propertyName = many.getName();
}
public BeanListHelp() {
this.many = null;
this.targetDescriptor = null;
this.propertyName = null;
}
@Override
public void setLoader(BeanCollectionLoader loader) {
this.loader = loader;
}
/**
* Internal add bypassing any modify listening.
*/
@Override
public void add(BeanCollection<?> collection, EntityBean bean) {
collection.internalAdd(bean);
}
@Override
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (bc instanceof BeanList<?>) {
@@ -54,57 +61,42 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
bl.setActualList(new ArrayList<Object>());
}
return bl;
} else if (bc instanceof List<?>) {
return new VanillaAdd((List<?>) bc);
} else {
throw new RuntimeException("Unhandled type " + bc);
}
}
@SuppressWarnings("unchecked")
static class VanillaAdd implements BeanCollectionAdd {
@SuppressWarnings("rawtypes")
private final List list;
private VanillaAdd(List<?> list) {
this.list = list;
}
public void addBean(EntityBean bean) {
list.add(bean);
}
@Override
public BeanCollection<T> createEmptyNoParent() {
return new BeanList<T>();
}
public Iterator<?> getIterator(Object collection) {
return ((List<?>) collection).iterator();
}
public Object createEmpty(boolean vanilla) {
if (vanilla) {
return new ArrayList<T>();
}
BeanList<T> beanList = new BeanList<T>();
@Override
public BeanCollection<T> createEmpty(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<T>(loader, parentBean, propertyName);
if (many != null) {
beanList.setModifyListening(many.getModifyListenMode());
}
return beanList;
}
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
@Override
public BeanCollection<T> createReference(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<T>(loader, parentBean, propertyName);
beanList.setModifyListening(many.getModifyListenMode());
return beanList;
}
@Override
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) server.findList(query, t);
refresh(newBeanList, parentBean);
}
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) bc;
@@ -129,6 +121,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
}
}
@Override
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
List<?> list;
@@ -150,7 +143,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
ctx.writeStartArray(name);
for (int j = 0; j < list.size(); j++) {
targetDescriptor.jsonWrite(ctx, (EntityBean)list.get(j));
targetDescriptor.jsonWrite(ctx, (EntityBean) list.get(j));
}
ctx.writeEndArray();
}
@@ -1,11 +1,5 @@
package com.avaje.ebeaninternal.server.deploy;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Query;
import com.avaje.ebean.Transaction;
@@ -16,174 +10,175 @@ import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.common.BeanMap;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* Helper specifically for dealing with Maps.
*/
public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private final BeanProperty beanProperty;
private BeanCollectionLoader loader;
//private final String mapKey;
/**
* When created for a given query that will return a map.
*/
public BeanMapHelp(BeanDescriptor<T> targetDescriptor, String mapKey) {
this(null, targetDescriptor, mapKey);
}
private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private final String propertyName;
private final BeanProperty beanProperty;
private BeanCollectionLoader loader;
public BeanMapHelp(BeanPropertyAssocMany<T> many){
this(many, many.getTargetDescriptor(), many.getMapKey());
}
/**
* When help is attached to a specific many property.
*/
private BeanMapHelp(BeanPropertyAssocMany<T> many, BeanDescriptor<T> targetDescriptor, String mapKey){
this.many = many;
this.targetDescriptor = targetDescriptor;
//this.mapKey = mapKey;
this.beanProperty = targetDescriptor.getBeanProperty(mapKey);
}
/**
* Return an iterator of the values.
*/
public Iterator<?> getIterator(Object collection) {
return ((Map<?,?>) collection).values().iterator();
/**
* When created for a given query that will return a map.
*/
public BeanMapHelp(BeanDescriptor<T> targetDescriptor, String mapKey) {
this.targetDescriptor = targetDescriptor;
this.beanProperty = targetDescriptor.getBeanProperty(mapKey);
this.many = null;
this.propertyName = null;
}
/**
* When help is attached to a specific many property.
*/ public BeanMapHelp(BeanPropertyAssocMany<T> many) {
this.many = many;
this.targetDescriptor = many.getTargetDescriptor();
this.propertyName = many.getName();
this.beanProperty = targetDescriptor.getBeanProperty(many.getMapKey());
}
@Override
public void setLoader(BeanCollectionLoader loader) {
this.loader = loader;
}
@Override
@SuppressWarnings("unchecked")
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (mapKey == null) {
mapKey = many.getMapKey();
}
public void setLoader(BeanCollectionLoader loader){
this.loader = loader;
}
BeanProperty beanProp = targetDescriptor.getBeanProperty(mapKey);
@SuppressWarnings("unchecked")
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if(mapKey == null){
mapKey = many.getMapKey();
}
BeanProperty beanProp = targetDescriptor.getBeanProperty(mapKey);
if (bc instanceof BeanMap<?,?>){
BeanMap<Object, Object> bm = (BeanMap<Object, Object>)bc;
Map<Object, Object> actualMap = bm.getActualMap();
if (actualMap == null){
actualMap = new LinkedHashMap<Object, Object>();
bm.setActualMap(actualMap);
}
return new Adder(beanProp, actualMap);
} else if (bc instanceof Map<?,?>) {
return new Adder(beanProp, (Map<Object, Object>)bc);
} else {
throw new RuntimeException("Unhandled type "+bc);
}
}
if (bc instanceof BeanMap<?, ?>) {
BeanMap<Object, Object> bm = (BeanMap<Object, Object>) bc;
Map<Object, Object> actualMap = bm.getActualMap();
if (actualMap == null) {
actualMap = new LinkedHashMap<Object, Object>();
bm.setActualMap(actualMap);
}
return new Adder(beanProp, actualMap);
static class Adder implements BeanCollectionAdd {
private final BeanProperty beanProperty;
private final Map<Object, Object> map;
Adder(BeanProperty beanProperty, Map<Object, Object> map) {
this.beanProperty = beanProperty;
this.map = map;
}
public void addBean(EntityBean bean) {
Object keyValue = beanProperty.getValue(bean);
map.put(keyValue, bean);
}
}
} else {
throw new RuntimeException("Unhandled type " + bc);
}
}
@SuppressWarnings("rawtypes")
public Object createEmpty(boolean vanilla) {
if (vanilla) {
return new LinkedHashMap();
}
BeanMap beanMap = new BeanMap();
if (many != null) {
beanMap.setModifyListening(many.getModifyListenMode());
}
return beanMap;
}
public void add(BeanCollection<?> collection, EntityBean bean) {
static class Adder implements BeanCollectionAdd {
Object keyValue = beanProperty.getValueIntercept(bean);
private final BeanProperty beanProperty;
((BeanMap<?,?>) collection).internalPut(keyValue, bean);
}
private final Map<Object, Object> map;
@SuppressWarnings({ "unchecked", "rawtypes" })
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
Adder(BeanProperty beanProperty, Map<Object, Object> map) {
this.beanProperty = beanProperty;
this.map = map;
}
BeanMap beanMap = new BeanMap(loader, parentBean, propertyName);
public void addBean(EntityBean bean) {
Object keyValue = beanProperty.getValue(bean);
map.put(keyValue, bean);
}
}
@Override
public BeanCollection<T> createEmptyNoParent() {
return new BeanMap();
}
@Override
@SuppressWarnings("rawtypes")
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
BeanMap beanMap = new BeanMap(loader, ownerBean, propertyName);
if (many != null) {
beanMap.setModifyListening(many.getModifyListenMode());
}
return beanMap;
}
}
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
refresh(newBeanMap, parentBean);
}
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
@Override
public void add(BeanCollection<?> collection, EntityBean bean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
Map<?, ?> current = (Map<?, ?>) many.getValue(parentBean);
Object keyValue = beanProperty.getValueIntercept(bean);
((BeanMap<?, ?>) collection).internalPut(keyValue, bean);
}
newBeanMap.setModifyListening(many.getModifyListenMode());
if (current == null) {
// the currentMap is null? Not really expecting this...
many.setValue(parentBean, newBeanMap);
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public BeanCollection<T> createReference(EntityBean parentBean) {
} else if (current instanceof BeanMap<?,?>) {
// normally this case, replace just the underlying list
BeanMap<?, ?> currentBeanMap = (BeanMap<?, ?>) current;
currentBeanMap.setActualMap(newBeanMap.getActualMap());
currentBeanMap.setModifyListening(many.getModifyListenMode());
BeanMap beanMap = new BeanMap(loader, parentBean, propertyName);
if (many != null) {
beanMap.setModifyListening(many.getModifyListenMode());
}
return beanMap;
}
} else {
// replace the entire set
many.setValue(parentBean, newBeanMap);
}
}
@Override
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
refresh(newBeanMap, parentBean);
}
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Map<?,?> map;
if (collection instanceof BeanCollection<?>){
BeanMap<?,?> bc = (BeanMap<?,?>)collection;
if (!bc.isPopulated()){
if (explicitInclude){
// invoke lazy loading as collection
// is explicitly included in the output
bc.size();
} else {
return;
}
}
map = bc.getActualMap();
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
Map<?, ?> current = (Map<?, ?>) many.getValue(parentBean);
newBeanMap.setModifyListening(many.getModifyListenMode());
if (current == null) {
// the currentMap is null? Not really expecting this...
many.setValue(parentBean, newBeanMap);
} else if (current instanceof BeanMap<?, ?>) {
// normally this case, replace just the underlying list
BeanMap<?, ?> currentBeanMap = (BeanMap<?, ?>) current;
currentBeanMap.setActualMap(newBeanMap.getActualMap());
currentBeanMap.setModifyListening(many.getModifyListenMode());
} else {
// replace the entire set
many.setValue(parentBean, newBeanMap);
}
}
@Override
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Map<?, ?> map;
if (collection instanceof BeanCollection<?>) {
BeanMap<?, ?> bc = (BeanMap<?, ?>) collection;
if (!bc.isPopulated()) {
if (explicitInclude) {
// invoke lazy loading as collection
// is explicitly included in the output
bc.size();
} else {
map = (Map<?,?>)collection;
return;
}
ctx.writeStartArray(name);
Iterator<?> it = map.entrySet().iterator();
while (it.hasNext()) {
Entry<?, ?> entry = (Entry<?, ?>)it.next();
//FIXME: json write map key ...
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
}
ctx.writeEndArray();
}
map = bc.getActualMap();
} else {
map = (Map<?, ?>) collection;
}
ctx.writeStartArray(name);
for (Entry<?, ?> entry : map.entrySet()) {
//FIXME: json write map key ...
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
}
ctx.writeEndArray();
}
}
@@ -174,7 +174,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
public void addBeanToCollectionWithCreate(EntityBean parentBean, EntityBean detailBean) {
BeanCollection<?> bc = (BeanCollection<?>) super.getValue(parentBean);
if (bc == null) {
bc = (BeanCollection<?>) help.createEmpty(false);
bc = help.createEmpty(parentBean);
setValue(parentBean, bc);
}
help.add(bc, detailBean);
@@ -185,6 +185,22 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
return val == null || (val instanceof BeanCollection<?>) && ((BeanCollection<?>) val).isEmptyAndUntouched();
}
/**
* Reset the many properties to be empty and ready for reloading.
* <p>
* Used in bean refresh.
*/
public void resetMany(EntityBean bean) {
Object value = getValue(bean);
if (value == null) {
// not expecting this - set an empty reference
createReference(bean);
} else {
// reset the collection back to empty
((BeanCollection)value).reset(bean, name);
}
}
@Override
public Object getValue(EntityBean bean) {
return super.getValue(bean);
@@ -526,13 +542,13 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
public BeanCollection<?> createReference(EntityBean parentBean) {
BeanCollection<?> ref = help.createReference(parentBean, name);
BeanCollection<?> ref = help.createReference(parentBean);
setValue(parentBean, ref);
return ref;
}
public Object createEmpty(boolean vanilla) {
return help.createEmpty(vanilla);
public BeanCollection<T> createEmpty(EntityBean parentBean) {
return help.createEmpty(parentBean);
}
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy;
import java.io.IOException;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.EntityBean;
import com.fasterxml.jackson.core.JsonParseException;
@@ -30,7 +31,7 @@ public class BeanPropertyAssocManyJsonHelp {
throw new JsonParseException("Unexpected token " + event + " - expecting start_array ", parser.getCurrentLocation());
}
Object collection = many.createEmpty(false);
BeanCollection<?> collection = many.createEmpty(parentBean);
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
do {
EntityBean detailBean = (EntityBean) many.targetDescriptor.jsonRead(parser, many.name);
@@ -395,13 +395,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
return getTargetDescriptor().createEntityBean();
}
/**
* Return an empty reference object.
*/
public Object createEmptyReference() {
return targetDescriptor.createEntityBean();
}
@Override
public Object elGetReference(EntityBean bean) {
Object value = getValueIntercept(bean);
@@ -465,7 +458,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
}
}
return (ExportedProperty[]) list.toArray(new ExportedProperty[list.size()]);
return list.toArray(new ExportedProperty[list.size()]);
}
/**
@@ -19,141 +19,131 @@ import com.avaje.ebeaninternal.server.text.json.WriteJson;
* Helper specifically for dealing with Sets.
*/
public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private BeanCollectionLoader loader;
/**
* When attached to a specific many property.
*/
public BeanSetHelp(BeanPropertyAssocMany<T> many){
this.many = many;
this.targetDescriptor = many.getTargetDescriptor();
}
/**
* For a query that returns a set.
*/
public BeanSetHelp(){
this.many = null;
this.targetDescriptor = null;
}
public void setLoader(BeanCollectionLoader loader){
this.loader = loader;
}
public Iterator<?> getIterator(Object collection) {
return ((Set<?>) collection).iterator();
}
public BeanCollectionAdd getBeanCollectionAdd(Object bc,String mapKey) {
if (bc instanceof BeanSet<?>){
BeanSet<?> beanSet = (BeanSet<?>)bc;
if (beanSet.getActualSet() == null){
beanSet.setActualSet(new LinkedHashSet<Object>());
}
return beanSet;
} else if (bc instanceof Set<?>) {
return new VanillaAdd((Set<?>)bc);
} else {
throw new RuntimeException("Unhandled type "+bc);
}
}
@SuppressWarnings("unchecked")
static class VanillaAdd implements BeanCollectionAdd {
private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private final String propertyName;
private BeanCollectionLoader loader;
@SuppressWarnings("rawtypes")
private final Set set;
/**
* When attached to a specific many property.
*/
public BeanSetHelp(BeanPropertyAssocMany<T> many) {
this.many = many;
this.targetDescriptor = many.getTargetDescriptor();
this.propertyName = many.getName();
}
private VanillaAdd(Set<?> set) {
this.set = set;
}
/**
* For a query that returns a set.
*/
public BeanSetHelp() {
this.many = null;
this.targetDescriptor = null;
this.propertyName = null;
}
public void addBean(EntityBean bean) {
set.add(bean);
}
}
public void add(BeanCollection<?> collection, EntityBean bean) {
collection.internalAdd(bean);
}
public Object createEmpty(boolean vanilla) {
if (vanilla) {
return new LinkedHashSet<T>();
@Override
public void setLoader(BeanCollectionLoader loader) {
this.loader = loader;
}
@Override
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (bc instanceof BeanSet<?>) {
BeanSet<?> beanSet = (BeanSet<?>) bc;
if (beanSet.getActualSet() == null) {
beanSet.setActualSet(new LinkedHashSet<Object>());
}
BeanSet<T> beanSet = new BeanSet<T>();
if (many != null) {
beanSet.setModifyListening(many.getModifyListenMode());
}
return beanSet;
}
return beanSet;
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
BeanSet<T> beanSet = new BeanSet<T>(loader, parentBean, propertyName);
beanSet.setModifyListening(many.getModifyListenMode());
return beanSet;
}
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>)server.findSet(query, t);
refresh(newBeanSet, parentBean);
}
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>)bc;
Set<?> current = (Set<?>)many.getValue(parentBean);
newBeanSet.setModifyListening(many.getModifyListenMode());
if (current == null){
// the currentList is null? Not really expecting this...
many.setValue(parentBean,newBeanSet);
} else if (current instanceof BeanSet<?>) {
// normally this case, replace just the underlying list
BeanSet<?> currentBeanSet = (BeanSet<?>)current;
currentBeanSet.setActualSet(newBeanSet.getActualSet());
currentBeanSet.setModifyListening(many.getModifyListenMode());
} else {
// replace the entire set
many.setValue(parentBean, newBeanSet);
}
}
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Set<?> set;
if (collection instanceof BeanCollection<?>){
BeanSet<?> bc = (BeanSet<?>)collection;
if (!bc.isPopulated()){
if (explicitInclude){
// invoke lazy loading as collection
// is explicitly included in the output
bc.size();
} else {
return;
}
}
set = bc.getActualSet();
} else {
set = (Set<?>)collection;
}
ctx.writeStartArray(name);
Iterator<?> it = set.iterator();
while (it.hasNext()) {
targetDescriptor.jsonWrite(ctx, (EntityBean)it.next());
}
ctx.writeEndArray();
} else {
throw new RuntimeException("Unhandled type " + bc);
}
}
public void add(BeanCollection<?> collection, EntityBean bean) {
collection.internalAdd(bean);
}
@Override
public BeanCollection<T> createEmptyNoParent() {
return new BeanSet();
}
@Override
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
BeanSet<T> beanSet = new BeanSet<T>(loader, ownerBean, propertyName);
if (many != null) {
beanSet.setModifyListening(many.getModifyListenMode());
}
return beanSet;
}
@Override
public BeanCollection<T> createReference(EntityBean parentBean) {
BeanSet<T> beanSet = new BeanSet<T>(loader, parentBean, propertyName);
beanSet.setModifyListening(many.getModifyListenMode());
return beanSet;
}
@Override
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) server.findSet(query, t);
refresh(newBeanSet, parentBean);
}
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) bc;
Set<?> current = (Set<?>) many.getValue(parentBean);
newBeanSet.setModifyListening(many.getModifyListenMode());
if (current == null) {
// the currentList is null? Not really expecting this...
many.setValue(parentBean, newBeanSet);
} else if (current instanceof BeanSet<?>) {
// normally this case, replace just the underlying list
BeanSet<?> currentBeanSet = (BeanSet<?>) current;
currentBeanSet.setActualSet(newBeanSet.getActualSet());
currentBeanSet.setModifyListening(many.getModifyListenMode());
} else {
// replace the entire set
many.setValue(parentBean, newBeanSet);
}
}
@Override
public void jsonWrite(WriteJson ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Set<?> set;
if (collection instanceof BeanCollection<?>) {
BeanSet<?> bc = (BeanSet<?>) collection;
if (!bc.isPopulated()) {
if (explicitInclude) {
// invoke lazy loading as collection
// is explicitly included in the output
bc.size();
} else {
return;
}
}
set = bc.getActualSet();
} else {
set = (Set<?>) collection;
}
ctx.writeStartArray(name);
Iterator<?> it = set.iterator();
while (it.hasNext()) {
targetDescriptor.jsonWrite(ctx, (EntityBean) it.next());
}
ctx.writeEndArray();
}
}
@@ -122,10 +122,6 @@ public class DRawSqlSelect {
*/
private SqlTree buildSqlTree(BeanDescriptor<?> desc){
SqlTree sqlTree = new SqlTree();
sqlTree.setSummary(desc.getName());
LinkedHashSet<String> includedProps = new LinkedHashSet<String>();
SqlTreeProperties selectProps = new SqlTreeProperties();
@@ -157,9 +153,8 @@ public class DRawSqlSelect {
}
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, null, withId);
sqlTree.setRootNode(sqlRoot);
return sqlTree;
return new SqlTree(desc.getName(), sqlRoot);
}
/**
@@ -1,29 +1,8 @@
package com.avaje.ebeaninternal.server.query;
import java.lang.ref.WeakReference;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.persistence.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.QueryIterator;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebean.bean.NodeUsageCollector;
import com.avaje.ebean.bean.NodeUsageListener;
import com.avaje.ebean.bean.ObjectGraphNode;
import com.avaje.ebean.bean.PersistenceContext;
import com.avaje.ebean.bean.*;
import com.avaje.ebean.config.GlobalProperties;
import com.avaje.ebeaninternal.api.LoadContext;
import com.avaje.ebeaninternal.api.SpiExpressionList;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.api.SpiQuery.Mode;
@@ -32,16 +11,23 @@ import com.avaje.ebeaninternal.server.autofetch.AutoFetchManager;
import com.avaje.ebeaninternal.server.core.Message;
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
import com.avaje.ebeaninternal.server.core.SpiOrmQueryRequest;
import com.avaje.ebeaninternal.server.deploy.BeanCollectionHelp;
import com.avaje.ebeaninternal.server.deploy.BeanCollectionHelpFactory;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.DbReadContext;
import com.avaje.ebeaninternal.server.deploy.*;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.lib.util.StringHelper;
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.DataReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.lang.ref.WeakReference;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* An object that represents a SqlSelect statement.
@@ -82,7 +68,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
/**
* Flag set when 'master' bean changed.
*/
private boolean loadedBeanChanged;
private boolean loadedBeanChanged;
/**
* The 'master' bean just loaded.
@@ -220,6 +206,9 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
private long startNano;
private long executionTimeMicros;
private BeanCollectionAdd currentDetailAdd;
/**
* Create the Sql select based on the request.
*/
@@ -253,7 +242,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
// get filter to put on the collection for reuse with refresh
String manyPropertyName = sqlTree.getManyPropertyName();
OrmQueryProperties chunk = query.getDetail().getChunk(manyPropertyName, false);
this.filterMany = chunk.getFilterMany();
this.filterMany = (chunk == null) ? null : chunk.getFilterMany();
} else {
this.filterMany = null;
}
@@ -266,7 +255,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
this.predicates = predicates;
this.maxRowsLimit = query.getMaxRows() > 0 ? query.getMaxRows() : GLOBAL_ROW_LIMIT;
this.help = createHelp(request);
this.collection = (BeanCollection<T>) (help != null ? help.createEmpty(false) : null);
this.collection = (help != null ? help.createEmptyNoParent() : null);
}
private BeanCollectionHelp<T> createHelp(OrmQueryRequest<T> request) {
@@ -306,10 +295,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
return predicates;
}
public LoadContext getGraphContext() {
return request.getGraphContext();
}
public SpiOrmQueryRequest<?> getQueryRequest() {
return request;
}
@@ -470,12 +455,10 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
public EntityBean getLoadedBean() {
if (manyIncluded) {
if (prevDetailCollection instanceof BeanCollection<?>) {
((BeanCollection<?>) prevDetailCollection).setModifyListening(manyProperty
.getModifyListenMode());
((BeanCollection<?>) prevDetailCollection).setModifyListening(manyProperty.getModifyListenMode());
} else if (currentDetailCollection instanceof BeanCollection<?>) {
((BeanCollection<?>) currentDetailCollection).setModifyListening(manyProperty
.getModifyListenMode());
((BeanCollection<?>) currentDetailCollection).setModifyListening(manyProperty.getModifyListenMode());
}
}
@@ -581,8 +564,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
return false;
}
private BeanCollectionAdd currentDetailAdd;
private void createNewDetailCollection() {
prevDetailCollection = currentDetailCollection;
if (queryMode.equals(Mode.LAZYLOAD_MANY)) {
@@ -590,7 +571,7 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
currentDetailCollection = manyPropertyEl.elGetValue(loadedBean);
} else {
// create a new collection to populate and assign to the bean
currentDetailCollection = manyProperty.createEmpty(false);
currentDetailCollection = manyProperty.createEmpty(loadedBean);
manyPropertyEl.elSetValue(loadedBean, currentDetailCollection, false);
}
@@ -719,14 +700,6 @@ public class CQuery<T> implements DbReadContext, CancelableQuery {
return sqlTree.getSummary();
}
/**
* Return the SqlSelectChain. This is the flattened structure that represents
* this query.
*/
public SqlTree getSqlTree() {
return sqlTree;
}
public String getBindLog() {
return bindLog;
}
@@ -13,40 +13,71 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
*/
public class SqlTree {
private SqlTreeNode rootNode;
private final SqlTreeNode rootNode;
/**
* Property if resultSet contains master and detail rows.
*/
private BeanPropertyAssocMany<?> manyProperty;
private String manyPropertyName;
private ElPropertyValue manyPropEl;
private final BeanPropertyAssocMany<?> manyProperty;
private Set<String> includes;
private final String manyPropertyName;
private final ElPropertyValue manyPropEl;
private final Set<String> includes;
/**
* Summary of the select being generated.
*/
private String summary;
private final String summary;
private String selectSql;
private final String selectSql;
private String fromSql;
private final String fromSql;
/**
* Encrypted Properties require additional binding.
*/
private BeanProperty[] encryptedProps;
private final BeanProperty[] encryptedProps;
/**
* Where clause for inheritance.
*/
private String inheritanceWhereSql;
private final String inheritanceWhereSql;
/**
* Create the SqlSelectClause.
*/
public SqlTree() {
public SqlTree(String summary, SqlTreeNode rootNode, String selectSql, String fromSql, String inheritanceWhereSql,
BeanProperty[] encryptedProps, BeanPropertyAssocMany<?> manyProperty, String manyPropertyName,
ElPropertyValue manyPropEl, Set<String> includes) {
this.summary = summary;
this.rootNode = rootNode;
this.selectSql = selectSql;
this.fromSql = fromSql;
this.inheritanceWhereSql = inheritanceWhereSql;
this.encryptedProps = encryptedProps;
this.manyProperty = manyProperty;
this.manyPropertyName = manyPropertyName;
this.manyPropEl = manyPropEl;
this.includes = includes;
}
/**
* Construct for RawSql.
*/
public SqlTree(String summary, SqlTreeNode rootNode) {
this.summary = summary;
this.rootNode = rootNode;
this.selectSql = null;
this.fromSql = null;
this.inheritanceWhereSql = null;
this.encryptedProps = null;
this.manyProperty = null;
this.manyPropertyName = null;
this.manyPropEl = null;
this.includes = null;
}
public List<String> buildSelectExpressionChain() {
@@ -62,23 +93,6 @@ public class SqlTree {
return includes;
}
/**
* Set the association includes (Ones and Many's).
*/
public void setIncludes(Set<String> includes) {
this.includes = includes;
}
/**
* Set the manyProperty used for this query.
*/
public void setManyProperty(BeanPropertyAssocMany<?> manyProperty, String manyPropertyName,
ElPropertyValue manyPropEl) {
this.manyProperty = manyProperty;
this.manyPropertyName = manyPropertyName;
this.manyPropEl = manyPropEl;
}
/**
* Return the String for the actual SQL.
*/
@@ -86,21 +100,10 @@ public class SqlTree {
return selectSql;
}
/**
* Set the select sql clause.
*/
public void setSelectSql(String selectSql) {
this.selectSql = selectSql;
}
public String getFromSql() {
return fromSql;
}
public void setFromSql(String fromSql) {
this.fromSql = fromSql;
}
/**
* Return the where clause for inheritance.
*/
@@ -108,20 +111,6 @@ public class SqlTree {
return inheritanceWhereSql;
}
/**
* Set where clause(s) for inheritance.
*/
public void setInheritanceWhereSql(String whereSql) {
this.inheritanceWhereSql = whereSql;
}
/**
* Set the summary description of the query.
*/
public void setSummary(String summary) {
this.summary = summary;
}
/**
* Return a summary of the select clause.
*/
@@ -133,10 +122,6 @@ public class SqlTree {
return rootNode;
}
public void setRootNode(SqlTreeNode rootNode) {
this.rootNode = rootNode;
}
/**
* Return the property that is associated with the many. There can only be one
* per SqlSelect. This can be null.
@@ -164,7 +149,4 @@ public class SqlTree {
return encryptedProps;
}
public void setEncryptedProps(BeanProperty[] encryptedProps) {
this.encryptedProps = encryptedProps;
}
}
@@ -66,6 +66,8 @@ public class SqlTreeBuilder {
private final boolean rawSql;
private SqlTreeNode rootNode;
/**
* Construct for RawSql query.
*/
@@ -111,34 +113,33 @@ public class SqlTreeBuilder {
*/
public SqlTree build() {
SqlTree sqlTree = new SqlTree();
summary.append(desc.getName());
// build the appropriate chain of SelectAdapter's
buildRoot(desc, sqlTree);
buildRoot(desc);
// build the actual String
SqlTreeNode rootNode = sqlTree.getRootNode();
String selectSql = null;
String fromSql = null;
String inheritanceWhereSql = null;
BeanProperty[] encryptedProps = null;
if (!rawSql) {
sqlTree.setSelectSql(buildSelectClause(rootNode));
sqlTree.setFromSql(buildFromClause(rootNode));
sqlTree.setInheritanceWhereSql(buildWhereClause(rootNode));
sqlTree.setEncryptedProps(ctx.getEncryptedProps());
selectSql = buildSelectClause();
fromSql = buildFromClause();
inheritanceWhereSql = buildWhereClause();
encryptedProps = ctx.getEncryptedProps();
}
sqlTree.setIncludes(queryDetail.getIncludes());
sqlTree.setSummary(summary.toString());
ElPropertyValue manyPropEl = null;
if (manyPropertyName != null) {
ElPropertyValue manyPropEl = desc.getElGetValue(manyPropertyName);
sqlTree.setManyProperty(manyProperty, manyPropertyName, manyPropEl);
manyPropEl = desc.getElGetValue(manyPropertyName);
}
return sqlTree;
return new SqlTree(summary.toString(), rootNode, selectSql, fromSql, inheritanceWhereSql, encryptedProps,
manyProperty, manyPropertyName, manyPropEl, queryDetail.getIncludes());
}
private String buildSelectClause(SqlTreeNode rootNode) {
private String buildSelectClause() {
if (rawSql) {
return "Not Used";
@@ -155,7 +156,7 @@ public class SqlTreeBuilder {
return selectSql;
}
private String buildWhereClause(SqlTreeNode rootNode) {
private String buildWhereClause() {
if (rawSql) {
return "Not Used";
@@ -164,7 +165,7 @@ public class SqlTreeBuilder {
return ctx.getContent();
}
private String buildFromClause(SqlTreeNode rootNode) {
private String buildFromClause() {
if (rawSql) {
return "Not Used";
@@ -173,10 +174,9 @@ public class SqlTreeBuilder {
return ctx.getContent();
}
private void buildRoot(BeanDescriptor<?> desc, SqlTree sqlTree) {
private void buildRoot(BeanDescriptor<?> desc) {
SqlTreeNode selectRoot = buildSelectChain(null, null, desc, null);
sqlTree.setRootNode(selectRoot);
rootNode = buildSelectChain(null, null, desc, null);
if (!rawSql) {
alias.addJoin(queryDetail.getIncludes(), desc);
@@ -1,57 +0,0 @@
package com.avaje.ebeaninternal.server.text.json;
import java.sql.Date;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
public class DefaultJsonValueAdapter {//implements JsonValueAdapter {
private final SimpleDateFormat dateTimeProto;
public DefaultJsonValueAdapter(String dateTimeFormat) {
this.dateTimeProto = new SimpleDateFormat(dateTimeFormat);
this.dateTimeProto.setTimeZone(TimeZone.getTimeZone("UTC"));
}
public DefaultJsonValueAdapter() {
this("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
}
private SimpleDateFormat dtFormat() {
return (SimpleDateFormat) dateTimeProto.clone();
}
public String jsonFromDate(Date date) {
return "\"" + date.toString() + "\"";
}
public String jsonFromTimestamp(Timestamp date) {
return "\"" + dtFormat().format(date) + "\"";
}
public Date jsonToDate(String jsonDate) {
try {
long utc = Long.parseLong(jsonDate);
return new java.sql.Date(utc);
} catch (NumberFormatException ex) {
return Date.valueOf(jsonDate);
}
}
public Timestamp jsonToTimestamp(String jsonDateTime) {
try {
long utc = Long.parseLong(jsonDateTime);
return new Timestamp(utc);
} catch (NumberFormatException ex) {
try {
java.util.Date d = dtFormat().parse(jsonDateTime);
return new Timestamp(d.getTime());
} catch (Exception e) {
String m = "Error parsing Datetime[" + jsonDateTime + "]";
throw new RuntimeException(m, e);
}
}
}
}