diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
index c67f16616..4f6f9362a 100644
--- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
+++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
@@ -1,5 +1,10 @@
package com.avaje.ebean.bean;
+import com.avaje.ebean.Ebean;
+import com.avaje.ebean.ValuePair;
+
+import javax.persistence.EntityNotFoundException;
+import javax.persistence.PersistenceException;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
@@ -11,12 +16,6 @@ import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
-import javax.persistence.EntityNotFoundException;
-import javax.persistence.PersistenceException;
-
-import com.avaje.ebean.Ebean;
-import com.avaje.ebean.ValuePair;
-
/**
* This is the object added to every entity bean using byte code enhancement.
*
@@ -92,6 +91,8 @@ public final class EntityBeanIntercept implements Serializable {
private int lazyLoadProperty = -1;
+ private Object ownerId;
+
/**
* Create a intercept with a given entity.
*
@@ -349,11 +350,22 @@ public final class EntityBeanIntercept implements Serializable {
* lazy loading and this bean might not be used by the client code at all.
* Instead we will fail as soon as the client code tries to use this bean.
*
+ * @param lazyLoadPropertyIndex the property that is expected to be loaded
*/
- public void checkLazyLoadFailure() {
- if (lazyLoadProperty != -1) {
- this.lazyLoadFailure = true;
+ public boolean isLazyLoadFailure(int lazyLoadPropertyIndex) {
+ if (lazyLoadProperty != -1 || !isLoadedProperty(lazyLoadPropertyIndex)) {
+ lazyLoadFailure = true;
+ return true;
}
+ lazyLoadFailure = false;
+ return false;
+ }
+
+ /**
+ * Set the Id of the owner bean.
+ */
+ public void setOwnerId(Object ownerId) {
+ this.ownerId = ownerId;
}
/**
@@ -748,7 +760,7 @@ public final class EntityBeanIntercept implements Serializable {
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
- throw new EntityNotFoundException("Bean has been deleted - lazy loading failed");
+ throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
}
if (lazyLoadProperty == -1) {
@@ -763,7 +775,7 @@ public final class EntityBeanIntercept implements Serializable {
if (lazyLoadFailure) {
// failed when lazy loading this bean
- throw new EntityNotFoundException("Bean has been deleted - lazy loading failed");
+ throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
}
// bean should be loaded and intercepting now. setLoaded() has
diff --git a/src/main/java/com/avaje/ebeaninternal/api/LoadBeanRequest.java b/src/main/java/com/avaje/ebeaninternal/api/LoadBeanRequest.java
index 712aebbd7..caeb2ccb3 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/LoadBeanRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/LoadBeanRequest.java
@@ -4,6 +4,8 @@ import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
@@ -13,10 +15,14 @@ import java.util.List;
*/
public class LoadBeanRequest extends LoadRequest {
+ private static final Logger logger = LoggerFactory.getLogger(LoadBeanRequest.class);
+
private final List batch;
private final LoadBeanBuffer loadBuffer;
+ private final int lazyLoadPropertyIndex;
+
private final String lazyLoadProperty;
private final boolean loadCache;
@@ -24,21 +30,24 @@ public class LoadBeanRequest extends LoadRequest {
/**
* Construct for lazy load request.
*/
- public LoadBeanRequest(LoadBeanBuffer LoadBuffer, String lazyLoadProperty, boolean loadCache) {
- this(LoadBuffer, null, true, lazyLoadProperty, loadCache);
+ public LoadBeanRequest(LoadBeanBuffer LoadBuffer, int lazyLoadPropertyIndex, String lazyLoadProperty, boolean loadCache) {
+ this(LoadBuffer, null, true, lazyLoadPropertyIndex, lazyLoadProperty, loadCache);
}
/**
* Construct for secondary query.
*/
public LoadBeanRequest(LoadBeanBuffer LoadBuffer, OrmQueryRequest> parentRequest) {
- this(LoadBuffer, parentRequest, false, null, false);
+ this(LoadBuffer, parentRequest, false, -1, null, false);
}
- private LoadBeanRequest(LoadBeanBuffer loadBuffer, OrmQueryRequest> parentRequest, boolean lazy, String lazyLoadProperty, boolean loadCache) {
+ private LoadBeanRequest(LoadBeanBuffer loadBuffer, OrmQueryRequest> parentRequest, boolean lazy,
+ int lazyLoadPropertyIndex, String lazyLoadProperty, boolean loadCache) {
+
super(parentRequest, lazy);
this.loadBuffer = loadBuffer;
this.batch = loadBuffer.getBatch();
+ this.lazyLoadPropertyIndex = lazyLoadPropertyIndex;
this.lazyLoadProperty = lazyLoadProperty;
this.loadCache = loadCache;
}
@@ -143,10 +152,20 @@ public class LoadBeanRequest extends LoadRequest {
}
}
- for (int i = 0; i < batch.size(); i++) {
- // Check if the underlying row in DB was deleted. Mark this bean as 'failed' if
- // necessary but allow processing to continue until it is accessed by client code
- batch.get(i).checkLazyLoadFailure();
+ if (lazyLoadPropertyIndex > -1) {
+ // this is a lazy loading query so check for lazy loading failure (due to deleted rows)
+ for (int i = 0; i < batch.size(); i++) {
+ // check if the underlying row in DB was deleted. Mark the bean as 'failed' if
+ // necessary but allow processing to continue until it is accessed by client code
+ EntityBeanIntercept ebi = batch.get(i);
+ // all beans in the batch should have this property loaded now
+ if (ebi.isLazyLoadFailure(lazyLoadPropertyIndex)) {
+ BeanDescriptor> desc = loadBuffer.getBeanDescriptor();
+ Object beanId = desc.getId(ebi.getOwner());
+ ebi.setOwnerId(beanId);
+ logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + beanId + " - expecting when bean has been deleted");
+ }
+ }
}
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/api/LoadManyRequest.java b/src/main/java/com/avaje/ebeaninternal/api/LoadManyRequest.java
index 25af86df3..e6d918adb 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/LoadManyRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/LoadManyRequest.java
@@ -183,7 +183,7 @@ public class LoadManyRequest extends LoadRequest {
if (logger.isDebugEnabled()) {
EntityBean ownerBean = bc.getOwnerBean();
Object parentId = desc.getId(ownerBean);
- logger.debug("BeanCollection after lazy load was empty. type[" + ownerBean.getClass() + "] id[" + parentId + "] owner[" + ownerBean + "]");
+ logger.debug("BeanCollection after lazy load was empty. type:" + ownerBean.getClass().getName() + " id:" + parentId + " owner:" + ownerBean);
}
} else if (isLoadCache()) {
Object parentId = desc.getId(bc.getOwnerBean());
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
index 9fb43dee4..3d9e82118 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
@@ -85,7 +85,7 @@ public class DefaultBeanLoader {
SpiQuery> query = loadRequest.createQuery(server, batchSize);
- executeLazyLoadQuery(loadRequest, query);
+ executeQuery(loadRequest, query);
loadRequest.postLoad();
@@ -214,7 +214,7 @@ public class DefaultBeanLoader {
query.where().idIn(idList);
}
- List> list = executeLazyLoadQuery(loadRequest, query);
+ List> list = executeQuery(loadRequest, query);
loadRequest.postLoad(list);
@@ -225,7 +225,7 @@ public class DefaultBeanLoader {
/**
* Execute the lazy load query taking into account MySql transaction oddness.
*/
- private List> executeLazyLoadQuery(LoadRequest loadRequest, SpiQuery> query) {
+ private List> executeQuery(LoadRequest loadRequest, SpiQuery> query) {
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createQueryTransaction();
diff --git a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java
index 254fd6d78..fd121d517 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/loadcontext/DLoadBeanContext.java
@@ -190,7 +190,7 @@ public class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContex
}
}
- LoadBeanRequest req = new LoadBeanRequest(this, ebi.getLazyLoadProperty(), context.hitCache);
+ LoadBeanRequest req = new LoadBeanRequest(this, ebi.getLazyLoadPropertyIndex(), ebi.getLazyLoadProperty(), context.hitCache);
context.desc.getEbeanServer().loadBean(req);
}