Skip to content

Commit

Permalink
Merge pull request ebean-orm#3050 from ebean-orm/feature/LoadBeanRequest
Browse files Browse the repository at this point in the history
Fix SqlTreeLoadBean to only register new beans into load context
  • Loading branch information
rbygrave committed May 9, 2023
2 parents ecfd831 + 4c9f0f2 commit 646f8cc
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 75 deletions.
71 changes: 27 additions & 44 deletions ebean-core/src/main/java/io/ebeaninternal/api/LoadBeanRequest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;

import java.util.*;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static java.lang.System.Logger.Level.DEBUG;

Expand All @@ -21,6 +25,9 @@ public final class LoadBeanRequest extends LoadRequest {
private final boolean loadCache;
private final boolean alreadyLoaded;
private String triggerEbi;
private String batchBefore;
private List<Object> queryIds;

/**
* Construct for lazy load request.
*/
Expand Down Expand Up @@ -56,17 +63,19 @@ public String description() {
}

/**
* Return the batch of beans to actually load.
* Return true if the batch is empty.
*/
public Set<EntityBeanIntercept> batch() {
public boolean checkEmpty() {
loadBuffer.loadingStarted();
return batch;
batchBefore = String.valueOf(batch);
queryIds = ids();
return batch.isEmpty();
}

/**
* Return the list of Id values for the beans in the lazy load buffer.
*/
public List<Object> ids() {
private List<Object> ids() {
final List<Object> idList = new ArrayList<>(batch.size());
final BeanDescriptor<?> desc = loadBuffer.descriptor();
for (EntityBeanIntercept ebi : batch) {
Expand All @@ -78,7 +87,7 @@ public List<Object> ids() {
/**
* Configure the query for lazy loading execution.
*/
public void configureQuery(SpiQuery<?> query, List<Object> idList) {
public void configureQuery(SpiQuery<?> query) {
query.setMode(Mode.LAZYLOAD_BEAN);
query.setPersistenceContext(loadBuffer.persistenceContext());
query.setLoadDescription(mode(), description());
Expand All @@ -94,10 +103,10 @@ public void configureQuery(SpiQuery<?> query, List<Object> idList) {
if (loadCache) {
query.setBeanCacheMode(CacheMode.PUT);
}
if (idList.size() == 1) {
query.where().idEq(idList.get(0));
if (queryIds.size() == 1) {
query.where().idEq(queryIds.get(0));
} else {
query.where().idIn(idList);
query.where().idIn(queryIds);
}
}

Expand All @@ -108,7 +117,7 @@ private String mode() {
/**
* Load the beans into the L2 cache if that is requested and check for load failures due to deletes.
*/
public Result postLoad(List<?> list, List<Object> queryIds) {
public void postLoad(List<?> list) {
loadBuffer.loadingStopped();
Set<Object> loadedIds = new HashSet<>();
BeanDescriptor<?> desc = loadBuffer.descriptor();
Expand Down Expand Up @@ -137,42 +146,16 @@ public Result postLoad(List<?> list, List<Object> queryIds) {
}
}
if (!missed.isEmpty()) {
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch triggered by ebi:{0} property:{1}", triggerEbi, lazyLoadProperty);
if (CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch triggered by ebi:{0} property:{1}", triggerEbi, lazyLoadProperty);
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch BEFORE {0}", batchBefore);
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch AFTER {0}", batch);
String msg = MessageFormat.format("Bean added to batch during load for {0} missedIds:{1} queryIds:{2} missed:{3}",
beanType(), missedIds, queryIds, missed);
CoreLog.markedAsDeleted.log(DEBUG, msg, new RuntimeException("LoadBeanRequest - Bean added to batch during load"));
}
}
}
return new Result(loadedIds, missedIds, missed);
}
return EMPTY_RESULT;
}

static final Result EMPTY_RESULT = new Result(Collections.emptySet(),Collections.emptySet(), Collections.emptyList());

public static class Result {

private final Set<Object> loadedIds;
private final Set<Object> missedIds;
private final List<EntityBeanIntercept> missed;

Result(Set<Object> loadedIds, Set<Object> missedIds, List<EntityBeanIntercept> missed) {
this.loadedIds = loadedIds;
this.missedIds = missedIds;
this.missed = missed;
}

public boolean hasMisses() {
return !missedIds.isEmpty();
}

public Set<Object> missedIds() {
return missedIds;
}

public Set<Object> loadedIds() {
return loadedIds;
}

public List<EntityBeanIntercept> missed() {
return missed;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@
import io.ebeaninternal.server.transaction.DefaultPersistenceContext;

import javax.persistence.EntityNotFoundException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Set;

import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;

/**
* Helper to handle lazy loading and refreshing of beans.
Expand Down Expand Up @@ -126,30 +123,12 @@ private void loadManyInternal(EntityBean parentBean, String propertyName, boolea
* Load a batch of beans for +query or +lazy loading.
*/
void loadBean(LoadBeanRequest loadRequest) {
final Set<EntityBeanIntercept> batch = loadRequest.batch();
if (batch.isEmpty()) {
if (loadRequest.checkEmpty()) {
throw new RuntimeException("Nothing in batch?");
}

final String batchBefore = String.valueOf(batch);
final List<Object> ids = loadRequest.ids();
if (ids.isEmpty()) {
// this should never happen given the batch is not empty
CoreLog.internal.log(ERROR, "No Ids when loading Batch buffer");
return;
}

final SpiQuery<?> query = server.createQuery(loadRequest.beanType());
loadRequest.configureQuery(query, ids);
final List<?> list = executeQuery(loadRequest, query);
final LoadBeanRequest.Result result = loadRequest.postLoad(list, ids);
if (result.hasMisses() && CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch BEFORE {0}", batchBefore);
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch AFTER {0}", batch);
String msg = MessageFormat.format("Bean added to batch during load for {0} missedIds:{1} ids:{2} loadedIds:{3} sql:{4} missed:{5}",
loadRequest.beanType(), result.missedIds(), ids, result.loadedIds(), query.getGeneratedSql(), result.missed());
CoreLog.markedAsDeleted.log(DEBUG, msg, new RuntimeException("LoadBeanRequest - Bean added to batch during load"));
}
loadRequest.configureQuery(query);
loadRequest.postLoad(executeQuery(loadRequest, query));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ class Load {
EntityBean contextBean;
SqlBeanLoad sqlBeanLoad;
boolean lazyLoadMany;
boolean usingContextBean;

private Load(DbReadContext ctx, EntityBean parentBean) {
this.ctx = ctx;
Expand Down Expand Up @@ -189,6 +190,7 @@ private void readIdBean() {
contextBean = localBean;
} else {
// bean already exists in persistenceContext
usingContextBean = true;
if (ctx.isLoadContextBean()) {
// if explicitly set loadContextBean to true, then reload
localBean = contextBean;
Expand Down Expand Up @@ -278,13 +280,11 @@ private void postLoad() {
if (!partialObject) {
ebi.setFullyLoadedBean(true);
}
} else if (partialObject) {
if (readId) {
// register for lazy loading
ctx.register(null, ebi);
}
} else {
} else if (!partialObject) {
ebi.setFullyLoadedBean(true);
} else if (readId && !usingContextBean) {
// register for lazy loading if bean is new
ctx.register(null, ebi);
}

if (ctx.isAutoTuneProfiling() && !disableLazyLoad) {
Expand Down Expand Up @@ -370,7 +370,7 @@ final EntityBean perform() throws SQLException {
* context we need to check if it is already contained in the collection.
*/
final boolean isContextBean() {
return localBean == null || queryMode == Mode.LAZYLOAD_BEAN;
return usingContextBean;
}
}

Expand Down

0 comments on commit 646f8cc

Please sign in to comment.