Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Support for lazy add on BeanList #2945

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions ebean-api/src/main/java/io/ebean/bean/BeanCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 164,13 @@ enum ModifyListenMode {
*/
Collection<?> actualEntries();

/**
* Returns entries, that were lazily added at the end of the list. Might be null.
*/
default Collection<E> getLazyAddedEntries(boolean reset) {
return null;
}

/**
* return true if there are real rows held. Return false is this is using
* Deferred fetch to lazy load the rows and the rows have not yet been
Expand Down
26 changes: 13 additions & 13 deletions ebean-api/src/main/java/io/ebean/common/BeanList.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 8,14 @@
/**
* List capable of lazy loading and modification awareness.
*/
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {
public class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {

private static final long serialVersionUID = 1L;

/**
* The underlying List implementation.
*/
private List<E> list;
List<E> list;

/**
* Specify the underlying List implementation.
Expand Down Expand Up @@ -111,30 111,30 @@ public boolean checkEmptyLazyLoad() {
}
}

protected void initList(boolean skipLoad, boolean onlyIds) {
if (skipLoad) {
list = new ArrayList<>();
} else {
lazyLoadCollection(onlyIds);
}
}

private void initClear() {
lock.lock();
try {
if (list == null) {
if (!disableLazyLoad && modifyListening) {
lazyLoadCollection(true);
} else {
list = new ArrayList<>();
}
initList(disableLazyLoad || !modifyListening, true);
}
} finally {
lock.unlock();
}
}

private void init() {
void init() {
lock.lock();
try {
if (list == null) {
if (disableLazyLoad) {
list = new ArrayList<>();
} else {
lazyLoadCollection(false);
}
initList(disableLazyLoad, false);
}
} finally {
lock.unlock();
Expand Down
133 changes: 133 additions & 0 deletions ebean-api/src/main/java/io/ebean/common/BeanListLazyAdd.java
Original file line number Diff line number Diff line change
@@ -0,0 1,133 @@
package io.ebean.common;

import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.EntityBean;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
* This bean list can perform additions without populating the list.
* This might be useful, if you just want to add entries to an existing collection.
* Works only for lists and only if there is no order column
*/
public class BeanListLazyAdd<E> extends BeanList<E> {

public BeanListLazyAdd(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
super(loader, ownerBean, propertyName);
}

private List<E> lazyAddedEntries;

@Override
public boolean add(E bean) {
checkReadOnly();

lock.lock();
try {
if (list == null) {
// list is not yet initialized, so we may add elements to a spare list
if (lazyAddedEntries == null) {
lazyAddedEntries = new ArrayList<>();
}
lazyAddedEntries.add(bean);
} else {
list.add(bean);
}
} finally {
lock.unlock();
}

if (modifyListening) {
modifyAddition(bean);
}
return true;
}

@Override
public boolean addAll(Collection<? extends E> beans) {
checkReadOnly();

lock.lock();
try {
if (list == null) {
// list is not yet initialized, so we may add elements to a spare list
if (lazyAddedEntries == null) {
lazyAddedEntries = new ArrayList<>();
}
lazyAddedEntries.addAll(beans);
} else {
list.addAll(beans);
}
} finally {
lock.unlock();
}

if (modifyListening) {
getModifyHolder().modifyAdditionAll(beans);
}

return true;
}


@Override
public void loadFrom(BeanCollection<?> other) {
super.loadFrom(other);
if (lazyAddedEntries != null) {
list.addAll(lazyAddedEntries);
lazyAddedEntries = null;
}
}

/**
* on init, this happens on all accessor methods except on 'add' and addAll,
* we add the lazy added entries at the end of the list
*/
@Override
protected void initList(boolean skipLoad, boolean onlyIds) {
if (skipLoad) {
if (lazyAddedEntries != null) {
list = lazyAddedEntries;
lazyAddedEntries = null;
} else {
list = new ArrayList<>();
}
} else {
lazyLoadCollection(onlyIds);
if (lazyAddedEntries != null) {
list.addAll(lazyAddedEntries);
lazyAddedEntries = null;
}
}
}

@Override
public List<E> getLazyAddedEntries(boolean reset) {
List<E> ret = lazyAddedEntries;
if (reset) {
lazyAddedEntries = null;
}
return ret;
}

@Override
public boolean isSkipSave() {
return lazyAddedEntries == null && super.isSkipSave();
}

public boolean checkEmptyLazyLoad() {
if (list != null) {
return false;
} else if (lazyAddedEntries == null) {
list = new ArrayList<>();
return true;
} else {
list = lazyAddedEntries;
lazyAddedEntries = null;
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 11,7 @@
abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {

final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
final BeanDescriptor<T> targetDescriptor;
final String propertyName;
BeanCollectionLoader loader;

Expand All @@ -21,12 21,6 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
this.propertyName = many.name();
}

BaseCollectionHelp() {
this.many = null;
this.targetDescriptor = null;
this.propertyName = null;
}

@Override
public final void setLoader(BeanCollectionLoader loader) {
this.loader = loader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 32,7 @@ public static Collection<?> getActualEntries(Object o) {
if (o instanceof BeanCollection<?>) {
BeanCollection<?> bc = (BeanCollection<?>) o;
if (!bc.isPopulated()) {
return null;
return bc.getLazyAddedEntries(true);
}
// For maps this is a collection of Map.Entry, otherwise it
// returns a collection of beans
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 5,7 @@
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanList;
import io.ebean.common.BeanListLazyAdd;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.json.SpiJsonWriter;
Expand All @@ -19,12 20,11 @@
*/
public class BeanListHelp<T> extends BaseCollectionHelp<T> {

private final boolean hasOrderColumn;

BeanListHelp(BeanPropertyAssocMany<T> many) {
super(many);
}

BeanListHelp() {
super();
hasOrderColumn = many.hasOrderColumn();
}

@Override
Expand Down Expand Up @@ -53,7 53,12 @@ public final BeanCollection<T> createEmptyNoParent() {

@Override
public final BeanCollection<T> createEmpty(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
BeanList<T> beanList;
if (hasOrderColumn) {
beanList = new BeanList<>(loader, parentBean, propertyName);
} else {
beanList = new BeanListLazyAdd<>(loader, parentBean, propertyName);
}
if (many != null) {
beanList.setModifyListening(many.modifyListenMode());
}
Expand All @@ -62,7 67,12 @@ public final BeanCollection<T> createEmpty(EntityBean parentBean) {

@Override
public final BeanCollection<T> createReference(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
BeanList<T> beanList;
if (hasOrderColumn) {
beanList = new BeanList<>(loader, parentBean, propertyName);
} else {
beanList = new BeanListLazyAdd<>(loader, parentBean, propertyName);
}
beanList.setModifyListening(many.modifyListenMode());
return beanList;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 20,13 @@
*/
public class BeanMapHelp<T> extends BaseCollectionHelp<T> {

private final BeanPropertyAssocMany<T> many;
private final BeanDescriptor<T> targetDescriptor;
private final String propertyName;
private final BeanProperty beanProperty;

/**
* When help is attached to a specific many property.
*/
BeanMapHelp(BeanPropertyAssocMany<T> many) {
this.many = many;
this.targetDescriptor = many.targetDescriptor();
this.propertyName = many.name();
super(many);
this.beanProperty = targetDescriptor.beanProperty(many.mapKey());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 26,6 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
super(many);
}

/**
* For a query that returns a set.
*/
BeanSetHelp() {
super();
}

@Override
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (bc instanceof BeanSet<?>) {
Expand Down
Loading