mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge pull request #2626 from ebean-orm/wip/EntityBeanIntercept-interface
Support EntityBeanIntercept as an interface with InterceptReadWrite and InterceptReadOnly options
This commit is contained in:
@@ -34,6 +34,13 @@ public interface EntityBean extends Serializable, ToStringAware {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new entity bean instance optimised for read only no interception use.
|
||||
*/
|
||||
default Object _ebean_newInstanceReadOnly() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generated method that sets the loaded state on all the embedded beans on
|
||||
* this entity bean by using EntityBeanIntercept.setEmbeddedLoaded(Object o);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,536 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
private final EntityBean owner;
|
||||
|
||||
public InterceptReadOnly(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPersistenceContext(PersistenceContext persistenceContext) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNodeUsageCollector(NodeUsageCollector usageCollector) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOwnerId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOwnerId(Object ownerId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEmbeddedOwner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmbeddedOwnerIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGetterCallback() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGetterCallback(PreGetterCallback getterCallback) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedOwner(EntityBean parentBean, int embeddedOwnerIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanLoader(BeanLoader beanLoader) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyLoadedBean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedDirty(int embeddedProperty) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirty(boolean dirty) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNew() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNewOrDirty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasIdOnly(int idIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReference() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReference(int idPos) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedFromCache(boolean loadedFromCache) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadedFromCache() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoaded() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNew() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoaded() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedLazy() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLazyLoadFailure(Object ownerId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLazyLoadFailure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisableLazyLoad() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisableLazyLoad(boolean disableLazyLoad) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedLoaded(Object embeddedBean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrigValue(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPropertyLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyUnloaded(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedProperty(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedPropertyAll() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadedProperty(int propertyIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChangedProperty(int propertyIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirtyProperty(int propertyIndex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markPropertyAsChanged(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangedProperty(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangeLoaded(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEmbeddedPropertyDirty(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOriginalValue(int propertyIndex, Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOriginalValueForce(int propertyIndex, Object value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNewBeanForUpdate() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getLoadedPropertyNames() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getDirtyProperties() {
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDirtyPropertyNames() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyNames(Set<String> props, String prefix) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDirtyProperty(Set<String> propertyNames) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ValuePair> getDirtyValues() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getDirtyPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyKey(StringBuilder sb) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getLoadedPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getLoaded() {
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLazyLoadPropertyIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLazyLoadProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBean(int loadProperty) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialisedMany(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preGetterCallback(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preGetId() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preGetter(int propertyIndex) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirtyStatus() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOldValue(int propertyIndex, Object oldValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSortOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSortOrder(int sortOrder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeletedFromCollection(boolean deletedFromCollection) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrphanDelete() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadError(int propertyIndex, Exception t) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Exception> getLoadErrors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChangedProp(int i) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MutableValueInfo mutableInfo(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mutableInfo(int propertyIndex, MutableValueInfo info) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mutableNext(int propertyIndex, MutableValueNext next) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mutableNext(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,9 +29,10 @@ public final class TenantAwareCache implements ServerCache {
|
||||
/**
|
||||
* Return the underlying ServerCache that is being delegated to.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T unwrap(Class<T> cls) {
|
||||
return (T)delegate;
|
||||
return (T) delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoader(BeanCollectionLoader loader) {
|
||||
public final void setLoader(BeanCollectionLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public Collection underlying(Object value) {
|
||||
public final Collection underlying(Object value) {
|
||||
if (value instanceof BeanCollection) {
|
||||
return ((BeanCollection)value).getActualDetails();
|
||||
} else {
|
||||
@@ -51,7 +51,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
void jsonWriteCollection(SpiJsonWriter ctx, String name, Collection<?> list) throws IOException {
|
||||
final void jsonWriteCollection(SpiJsonWriter ctx, String name, Collection<?> list) throws IOException {
|
||||
if (!list.isEmpty() || ctx.isIncludeEmpty()) {
|
||||
ctx.beginAssocMany(name);
|
||||
for (Object bean : list) {
|
||||
|
||||
@@ -47,6 +47,11 @@ public interface BeanCollectionHelp<T> extends CQueryCollectionAdd<T> {
|
||||
*/
|
||||
BeanCollection<T> createEmpty(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Create and return an empty 'vanilla' collection that does not support lazy loading.
|
||||
*/
|
||||
Object createEmptyReference();
|
||||
|
||||
/**
|
||||
* Add a bean to the List Set or Map.
|
||||
*/
|
||||
|
||||
@@ -86,7 +86,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
private final ConcurrentHashMap<String, ElPropertyDeploy> elDeployCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, STreeProperty> dynamicProperty = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Map<String,String>> pathMaps = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Map<String, String>> pathMaps = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<String, SpiRawSql> namedRawSql;
|
||||
private final Map<String, String> namedQuery;
|
||||
@@ -1765,6 +1765,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return createEntityBean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean createEntityBean2(boolean readOnlyNoIntercept) {
|
||||
if (readOnlyNoIntercept) {
|
||||
return (EntityBean) prototypeEntityBean._ebean_newInstanceReadOnly();
|
||||
}
|
||||
return createEntityBean(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an entity bean for JSON marshalling (which differs for the element collection case).
|
||||
*/
|
||||
@@ -2879,7 +2887,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
for (BeanPropertyAssocMany<?> many : propertiesManySave) {
|
||||
if (ebi.isLoadedProperty(many.propertyIndex())) {
|
||||
final Object value = many.getValue(bean);
|
||||
if (value instanceof BeanCollection && ((BeanCollection<?>)value).hasModifications() || value != null) {
|
||||
if (value instanceof BeanCollection && ((BeanCollection<?>) value).hasModifications() || value != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -27,8 +28,7 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
|
||||
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
if (bc instanceof BeanList<?>) {
|
||||
BeanList<?> bl = (BeanList<?>) bc;
|
||||
if (bl.getActualList() == null) {
|
||||
@@ -42,12 +42,17 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmptyNoParent() {
|
||||
public final Object createEmptyReference() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BeanCollection<T> createEmptyNoParent() {
|
||||
return new BeanList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmpty(EntityBean parentBean) {
|
||||
public final BeanCollection<T> createEmpty(EntityBean parentBean) {
|
||||
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
|
||||
if (many != null) {
|
||||
beanList.setModifyListening(many.modifyListenMode());
|
||||
@@ -56,29 +61,23 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
|
||||
public final BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
|
||||
beanList.setModifyListening(many.modifyListenMode());
|
||||
return beanList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
|
||||
public final void refresh(SpiEbeanServer 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) {
|
||||
|
||||
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
BeanList<?> newBeanList = (BeanList<?>) bc;
|
||||
|
||||
List<?> currentList = (List<?>) many.getValue(parentBean);
|
||||
|
||||
newBeanList.setModifyListening(many.modifyListenMode());
|
||||
|
||||
if (currentList == null) {
|
||||
// the currentList is null? Not really expecting this...
|
||||
many.setValue(parentBean, newBeanList);
|
||||
@@ -96,8 +95,7 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
|
||||
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
List<?> list;
|
||||
if (collection instanceof BeanCollection<?>) {
|
||||
BeanList<?> beanList = (BeanList<?>) collection;
|
||||
@@ -114,7 +112,6 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
|
||||
} else {
|
||||
list = (List<?>) collection;
|
||||
}
|
||||
|
||||
jsonWriteCollection(ctx, name, list);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -36,13 +37,11 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
|
||||
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
if (mapKey == null) {
|
||||
mapKey = many.mapKey();
|
||||
}
|
||||
BeanProperty beanProp = targetDescriptor.beanProperty(mapKey);
|
||||
|
||||
if (bc instanceof BeanMap<?, ?>) {
|
||||
BeanMap<Object, Object> bm = (BeanMap<Object, Object>) bc;
|
||||
Map<Object, Object> actualMap = bm.getActualMap();
|
||||
@@ -57,10 +56,9 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
static class Adder implements BeanCollectionAdd {
|
||||
static final class Adder implements BeanCollectionAdd {
|
||||
|
||||
private final BeanProperty beanProperty;
|
||||
|
||||
private final Map<Object, Object> map;
|
||||
|
||||
Adder(BeanProperty beanProperty, Map<Object, Object> map) {
|
||||
@@ -76,13 +74,17 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmptyNoParent() {
|
||||
public final Object createEmptyReference() {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BeanCollection<T> createEmptyNoParent() {
|
||||
return new BeanMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
|
||||
|
||||
public final BeanCollection<T> createEmpty(EntityBean ownerBean) {
|
||||
BeanMap<?, T> beanMap = new BeanMap<>(loader, ownerBean, propertyName);
|
||||
if (many != null) {
|
||||
beanMap.setModifyListening(many.modifyListenMode());
|
||||
@@ -92,7 +94,6 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
|
||||
@Override
|
||||
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
|
||||
|
||||
if (bean == null) {
|
||||
((BeanMap<?, ?>) collection).internalPutNull();
|
||||
} else {
|
||||
@@ -104,8 +105,7 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
|
||||
public final BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
BeanMap beanMap = new BeanMap(loader, parentBean, propertyName);
|
||||
if (many != null) {
|
||||
beanMap.setModifyListening(many.modifyListenMode());
|
||||
@@ -114,14 +114,13 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
|
||||
refresh(newBeanMap, parentBean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
|
||||
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
|
||||
Map<?, ?> current = (Map<?, ?>) many.getValue(parentBean);
|
||||
|
||||
@@ -143,8 +142,7 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
|
||||
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
Map<?, ?> map;
|
||||
if (collection instanceof BeanCollection<?>) {
|
||||
BeanMap<?, ?> bc = (BeanMap<?, ?>) collection;
|
||||
|
||||
@@ -15,7 +15,6 @@ public final class BeanMapHelpElement<T> extends BeanMapHelp<T> {
|
||||
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
|
||||
Object key = bean._ebean_getField(0);
|
||||
Object val = bean._ebean_getField(1);
|
||||
|
||||
BeanMap<?, ?> map = ((BeanMap<?, ?>) collection);
|
||||
if (withCheck) {
|
||||
map.internalPutWithCheck(key, val);
|
||||
|
||||
@@ -601,6 +601,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createEmptyReference(EntityBean localBean) {
|
||||
setValue(localBean, help.createEmptyReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<?> createReference(EntityBean localBean, boolean forceNewReference) {
|
||||
return forceNewReference ? createReference(localBean) : createReferenceIfNull(localBean);
|
||||
|
||||
@@ -10,6 +10,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -33,7 +34,7 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
|
||||
if (bc instanceof BeanSet<?>) {
|
||||
BeanSet<?> beanSet = (BeanSet<?>) bc;
|
||||
if (beanSet.getActualSet() == null) {
|
||||
@@ -46,12 +47,17 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmptyNoParent() {
|
||||
public final Object createEmptyReference() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BeanCollection<T> createEmptyNoParent() {
|
||||
return new BeanSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
|
||||
public final BeanCollection<T> createEmpty(EntityBean ownerBean) {
|
||||
BeanSet<T> beanSet = new BeanSet<>(loader, ownerBean, propertyName);
|
||||
if (many != null) {
|
||||
beanSet.setModifyListening(many.modifyListenMode());
|
||||
@@ -60,20 +66,20 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
public final BeanCollection<T> createReference(EntityBean parentBean) {
|
||||
BeanSet<T> beanSet = new BeanSet<>(loader, parentBean, propertyName);
|
||||
beanSet.setModifyListening(many.modifyListenMode());
|
||||
return beanSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
public final void refresh(SpiEbeanServer 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) {
|
||||
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
BeanSet<?> newBeanSet = (BeanSet<?>) bc;
|
||||
Set<?> current = (Set<?>) many.getValue(parentBean);
|
||||
newBeanSet.setModifyListening(many.modifyListenMode());
|
||||
@@ -94,7 +100,7 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
|
||||
Set<?> set;
|
||||
if (collection instanceof BeanCollection<?>) {
|
||||
BeanSet<?> bc = (BeanSet<?>) collection;
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.InterceptReadWrite;
|
||||
|
||||
final class ElementEntityBean implements EntityBean {
|
||||
|
||||
@@ -13,7 +14,7 @@ final class ElementEntityBean implements EntityBean {
|
||||
|
||||
ElementEntityBean(String[] properties) {
|
||||
this.properties = properties;
|
||||
this.intercept = new EntityBeanIntercept(this);
|
||||
this.intercept = new InterceptReadWrite(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,6 +33,11 @@ public interface STreePropertyAssocMany extends STreePropertyAssoc {
|
||||
*/
|
||||
BeanCollection<?> createReference(EntityBean localBean, boolean forceNewReference);
|
||||
|
||||
/**
|
||||
* Populate the collection for read-only disabled lazy loading (aka Java Collections non mutable empty collection).
|
||||
*/
|
||||
void createEmptyReference(EntityBean localBean);
|
||||
|
||||
/**
|
||||
* Return true if the property has a join table.
|
||||
*/
|
||||
|
||||
@@ -79,6 +79,11 @@ public interface STreeType {
|
||||
*/
|
||||
EntityBean createEntityBean();
|
||||
|
||||
/**
|
||||
* Create a new entity bean instance with option for read only optimisation.
|
||||
*/
|
||||
EntityBean createEntityBean2(boolean readOnlyNoIntercept);
|
||||
|
||||
/**
|
||||
* Put the entity bean into the persistence context.
|
||||
*/
|
||||
|
||||
@@ -50,6 +50,7 @@ public final class SqlTreeBuilder {
|
||||
*/
|
||||
private final boolean rawNoId;
|
||||
private final boolean disableLazyLoad;
|
||||
private final boolean readOnly;
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
private SqlTreeNode rootNode;
|
||||
private boolean sqlDistinct;
|
||||
@@ -63,6 +64,7 @@ public final class SqlTreeBuilder {
|
||||
this.desc = request.descriptor();
|
||||
this.rawNoId = rawNoId;
|
||||
this.disableLazyLoad = request.query().isDisableLazyLoading();
|
||||
this.readOnly = Boolean.TRUE.equals(request.query().isReadOnly());
|
||||
this.query = null;
|
||||
this.subQuery = false;
|
||||
this.distinctOnPlatform = false;
|
||||
@@ -88,6 +90,7 @@ public final class SqlTreeBuilder {
|
||||
this.query = request.query();
|
||||
this.temporalMode = SpiQuery.TemporalMode.of(query);
|
||||
this.disableLazyLoad = query.isDisableLazyLoading();
|
||||
this.readOnly = Boolean.TRUE.equals(query.isReadOnly());
|
||||
this.subQuery = Type.SQ_EXISTS == query.getType()
|
||||
|| Type.SQ_IN == query.getType()
|
||||
|| Type.ID_LIST == query.getType()
|
||||
@@ -309,13 +312,13 @@ public final class SqlTreeBuilder {
|
||||
if (baseTable == null) {
|
||||
baseTable = desc.baseTable(temporalMode);
|
||||
}
|
||||
return new SqlTreeNodeRoot(desc, props, myList, withId, includeJoin, lazyLoadMany, temporalMode, disableLazyLoad, sqlDistinct, baseTable);
|
||||
return new SqlTreeNodeRoot(desc, props, myList, withId, includeJoin, lazyLoadMany, temporalMode, disableLazyLoad, readOnly, sqlDistinct, baseTable);
|
||||
|
||||
} else if (prop instanceof STreePropertyAssocMany) {
|
||||
return new SqlTreeNodeManyRoot(prefix, (STreePropertyAssocMany) prop, props, myList, withId(), temporalMode, disableLazyLoad);
|
||||
return new SqlTreeNodeManyRoot(prefix, (STreePropertyAssocMany) prop, props, myList, withId(), temporalMode, disableLazyLoad, readOnly);
|
||||
|
||||
} else {
|
||||
return new SqlTreeNodeBean(prefix, prop, props, myList, withId(), temporalMode, disableLazyLoad);
|
||||
return new SqlTreeNodeBean(prefix, prop, props, myList, withId(), temporalMode, disableLazyLoad, readOnly);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
final boolean readId;
|
||||
private final boolean readIdNormal;
|
||||
private final boolean disableLazyLoad;
|
||||
private final boolean readOnlyNoIntercept;
|
||||
private final InheritInfo inheritInfo;
|
||||
final String prefix;
|
||||
private final Map<String, String> pathMap;
|
||||
@@ -49,6 +50,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
this.readId = node.readId;
|
||||
this.readIdNormal = readId && !temporalVersions;
|
||||
this.disableLazyLoad = node.disableLazyLoad;
|
||||
this.readOnlyNoIntercept = disableLazyLoad && node.readOnly;
|
||||
this.partialObject = node.partialObject;
|
||||
this.properties = node.properties;
|
||||
this.pathMap = node.pathMap;
|
||||
@@ -145,7 +147,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
|
||||
void initBeanType() throws SQLException {
|
||||
localDesc = desc;
|
||||
localBean = desc.createEntityBean();
|
||||
localBean = desc.createEntityBean2(readOnlyNoIntercept);
|
||||
localIdBinder = idBinder;
|
||||
}
|
||||
|
||||
@@ -282,14 +284,18 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
boolean forceNewReference = queryMode == Mode.REFRESH_BEAN;
|
||||
for (STreePropertyAssocMany many : localDesc.propsMany()) {
|
||||
if (many != fetchedMany) {
|
||||
// create a proxy for the many (deferred fetching)
|
||||
BeanCollection<?> ref = many.createReference(localBean, forceNewReference);
|
||||
if (ref != null) {
|
||||
if (disableLazyLoad) {
|
||||
ref.setDisableLazyLoad(true);
|
||||
}
|
||||
if (!ref.isRegisteredWithLoadContext()) {
|
||||
ctx.register(many.asMany(), ref);
|
||||
if (readOnlyNoIntercept) {
|
||||
many.createEmptyReference(localBean);
|
||||
} else {
|
||||
// create a proxy for the many (deferred fetching)
|
||||
BeanCollection<?> ref = many.createReference(localBean, forceNewReference);
|
||||
if (ref != null) {
|
||||
if (disableLazyLoad) {
|
||||
ref.setDisableLazyLoad(true);
|
||||
}
|
||||
if (!ref.isRegisteredWithLoadContext()) {
|
||||
ctx.register(many.asMany(), ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
final boolean readId;
|
||||
final boolean readIdNormal;
|
||||
final boolean disableLazyLoad;
|
||||
final boolean readOnly;
|
||||
final InheritInfo inheritInfo;
|
||||
final String prefix;
|
||||
final Map<String, String> pathMap;
|
||||
@@ -57,16 +58,16 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
* Construct for leaf node.
|
||||
*/
|
||||
SqlTreeNodeBean(String prefix, STreePropertyAssoc beanProp, SqlTreeProperties props,
|
||||
List<SqlTreeNode> myChildren, boolean withId, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
|
||||
this(prefix, beanProp, beanProp.target(), props, myChildren, withId, null, temporalMode, disableLazyLoad);
|
||||
List<SqlTreeNode> myChildren, boolean withId, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean readOnly) {
|
||||
this(prefix, beanProp, beanProp.target(), props, myChildren, withId, null, temporalMode, disableLazyLoad, readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for root node.
|
||||
*/
|
||||
SqlTreeNodeBean(STreeType desc, SqlTreeProperties props, List<SqlTreeNode> myList, boolean withId,
|
||||
STreePropertyAssocMany many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
|
||||
this(null, null, desc, props, myList, withId, many, temporalMode, disableLazyLoad);
|
||||
STreePropertyAssocMany many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean readOnly) {
|
||||
this(null, null, desc, props, myList, withId, many, temporalMode, disableLazyLoad, readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +75,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
*/
|
||||
private SqlTreeNodeBean(String prefix, STreePropertyAssoc beanProp, STreeType desc, SqlTreeProperties props,
|
||||
List<SqlTreeNode> myChildren, boolean withId, STreePropertyAssocMany lazyLoadParent,
|
||||
SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
|
||||
SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean readOnly) {
|
||||
this.lazyLoadParent = lazyLoadParent;
|
||||
this.lazyLoadParentIdBinder = (lazyLoadParent == null) ? null : lazyLoadParent.idBinder();
|
||||
this.prefix = prefix;
|
||||
@@ -91,6 +92,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
this.readId = !aggregationRoot && withId && desc.hasId();
|
||||
this.readIdNormal = readId && !temporalVersions;
|
||||
this.disableLazyLoad = disableLazyLoad || !readIdNormal || desc.isRawSqlBased();
|
||||
this.readOnly = readOnly;
|
||||
this.partialObject = props.isPartialObject();
|
||||
this.properties = props.getProps();
|
||||
this.children = myChildren == null ? Collections.emptyList() : myChildren;
|
||||
|
||||
@@ -10,8 +10,8 @@ final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
|
||||
final STreePropertyAssocMany manyProp;
|
||||
|
||||
SqlTreeNodeManyRoot(String prefix, STreePropertyAssocMany prop, SqlTreeProperties props, List<SqlTreeNode> myList,
|
||||
boolean withId, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
|
||||
super(prefix, prop, props, myList, withId, temporalMode, disableLazyLoad);
|
||||
boolean withId, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean readOnly) {
|
||||
super(prefix, prop, props, myList, withId, temporalMode, disableLazyLoad, readOnly);
|
||||
this.manyProp = prop;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ final class SqlTreeNodeRoot extends SqlTreeNodeBean {
|
||||
* Specify for SqlSelect to include an Id property or not.
|
||||
*/
|
||||
SqlTreeNodeRoot(STreeType desc, SqlTreeProperties props, List<SqlTreeNode> myList, boolean withId, TableJoin includeJoin,
|
||||
STreePropertyAssocMany many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean sqlDistinct, String baseTable) {
|
||||
STreePropertyAssocMany many, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad, boolean readOnly, boolean sqlDistinct, String baseTable) {
|
||||
|
||||
super(desc, props, myList, withId, many, temporalMode, disableLazyLoad);
|
||||
super(desc, props, myList, withId, many, temporalMode, disableLazyLoad, readOnly);
|
||||
this.includeJoin = includeJoin;
|
||||
this.sqlDistinct = sqlDistinct;
|
||||
this.baseTable = baseTable;
|
||||
|
||||
@@ -1 +1 @@
|
||||
ebean-version: 133
|
||||
ebean-version: 141
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
synthetic: false
|
||||
@@ -0,0 +1 @@
|
||||
ebean-version: 141
|
||||
@@ -0,0 +1 @@
|
||||
synthetic: false
|
||||
@@ -1,15 +1,25 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.InterceptReadOnly;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestQueryOrderById extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void orderById_default_expectNotOrderById() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query = DB.find(Customer.class)
|
||||
.select("id,name")
|
||||
@@ -17,12 +27,20 @@ public class TestQueryOrderById extends BaseTestCase {
|
||||
.setFirstRow(1)
|
||||
.setMaxRows(5);
|
||||
|
||||
query.findList();
|
||||
query.setReadOnly(true).setDisableLazyLoading(true);
|
||||
List<Customer> list = query.findList();
|
||||
if (isSqlServer() || isDb2()) {
|
||||
assertSql(query).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id offset 1 rows fetch next 5 rows only");
|
||||
} else if (!isOracle()) {
|
||||
assertSql(query).isEqualTo("select t0.id, t0.name from o_customer t0 order by t0.id limit 5 offset 1");
|
||||
}
|
||||
|
||||
assertThat(list).isNotEmpty();
|
||||
Customer customer = list.get(0);
|
||||
EntityBeanIntercept intercept = ((EntityBean) customer)._ebean_getIntercept();
|
||||
assertThat(intercept).isInstanceOf(InterceptReadOnly.class);
|
||||
assertThat(customer.getOrders()).isSameAs(Collections.EMPTY_LIST);
|
||||
assertThat(customer.getContacts()).isSameAs(Collections.EMPTY_LIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
ebean-version: 141
|
||||
Reference in New Issue
Block a user