mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Fix for #209 - refresh() ... does not refresh OneToMany or ManyToMany properties
This commit is contained in:
@@ -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
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user