diff --git a/pom.xml b/pom.xml
index 93f230d2b..c929c5cee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -90,13 +90,6 @@
1.1.1test
-
-
- org.avaje.ebeanorm
- avaje-ebeanorm-agent
- 3.2.1
- test
- com.h2database
@@ -149,7 +142,7 @@
org.avaje.ebeanormavaje-ebeanorm-mavenenhancer
- 3.2.1
+ 3.3.1-SNAPSHOTmain
diff --git a/src/main/java/com/avaje/ebean/BeanState.java b/src/main/java/com/avaje/ebean/BeanState.java
index fc4e3c371..3bd17068e 100644
--- a/src/main/java/com/avaje/ebean/BeanState.java
+++ b/src/main/java/com/avaje/ebean/BeanState.java
@@ -90,5 +90,5 @@ public interface BeanState {
* the properties that where loaded or null for a fully loaded entity
* bean.
*/
- public void setLoaded(Set loadedProperties);
+ public void setLoaded();
}
\ No newline at end of file
diff --git a/src/main/java/com/avaje/ebean/annotation/ConcurrencyMode.java b/src/main/java/com/avaje/ebean/annotation/ConcurrencyMode.java
index 59730225c..06d5cd7c5 100644
--- a/src/main/java/com/avaje/ebean/annotation/ConcurrencyMode.java
+++ b/src/main/java/com/avaje/ebean/annotation/ConcurrencyMode.java
@@ -13,10 +13,5 @@ public enum ConcurrencyMode {
/**
* Use a version column.
*/
- VERSION,
-
- /**
- * Use all the columns (except Lobs).
- */
- ALL
+ VERSION
}
diff --git a/src/main/java/com/avaje/ebean/bean/BeanCollection.java b/src/main/java/com/avaje/ebean/bean/BeanCollection.java
index a8955b341..61d2e1443 100644
--- a/src/main/java/com/avaje/ebean/bean/BeanCollection.java
+++ b/src/main/java/com/avaje/ebean/bean/BeanCollection.java
@@ -37,7 +37,7 @@ public interface BeanCollection extends Serializable {
/**
* Return the bean that owns this collection.
*/
- public Object getOwnerBean();
+ public EntityBean getOwnerBean();
/**
* Return the bean property name this collection represents.
diff --git a/src/main/java/com/avaje/ebean/bean/BeanCollectionAdd.java b/src/main/java/com/avaje/ebean/bean/BeanCollectionAdd.java
index 8bc754166..1df602fc8 100644
--- a/src/main/java/com/avaje/ebean/bean/BeanCollectionAdd.java
+++ b/src/main/java/com/avaje/ebean/bean/BeanCollectionAdd.java
@@ -12,5 +12,5 @@ public interface BeanCollectionAdd {
/**
* Add a loaded bean to the collection.
*/
- public void addBean(Object bean);
+ public void addBean(EntityBean bean);
}
diff --git a/src/main/java/com/avaje/ebean/bean/EntityBean.java b/src/main/java/com/avaje/ebean/bean/EntityBean.java
index fef36e90e..ea39333c8 100644
--- a/src/main/java/com/avaje/ebean/bean/EntityBean.java
+++ b/src/main/java/com/avaje/ebean/bean/EntityBean.java
@@ -83,31 +83,19 @@ public interface EntityBean extends Serializable {
*/
public Object _ebean_createCopy();
- /**
- * Return the fields in their index order.
- */
- public String[] _ebean_getFieldNames();
-
/**
* Set the value of a field of an entity bean of this type.
*
* Note that using this method bypasses any interception that otherwise occurs
* on entity beans. That means lazy loading and oldValues creation.
*
- *
- * @param fieldIndex
- * the index of the field
- * @param entityBean
- * the entityBean of this type to modify
- * @param value
- * the value to set
*/
- public void _ebean_setField(int fieldIndex, Object entityBean, Object value);
+ public void _ebean_setField(int fieldIndex, Object value);
/**
* Set the field value with interception.
*/
- public void _ebean_setFieldIntercept(int fieldIndex, Object entityBean, Object value);
+ public void _ebean_setFieldIntercept(int fieldIndex, Object value);
/**
* Return the value of a field from an entity bean of this type.
@@ -115,17 +103,12 @@ public interface EntityBean extends Serializable {
* Note that using this method bypasses any interception that otherwise occurs
* on entity beans. That means lazy loading.
*
- *
- * @param fieldIndex
- * the index of the field
- * @param entityBean
- * the entityBean to get the value from
*/
- public Object _ebean_getField(int fieldIndex, Object entityBean);
+ public Object _ebean_getField(int fieldIndex);
/**
* Return the field value with interception.
*/
- public Object _ebean_getFieldIntercept(int fieldIndex, Object entityBean);
+ public Object _ebean_getFieldIntercept(int fieldIndex);
}
diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
index 626091ae2..fccc5fbce 100644
--- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
+++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
@@ -6,6 +6,7 @@ import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URL;
+import java.util.LinkedHashSet;
import java.util.Set;
import javax.persistence.EntityNotFoundException;
@@ -24,6 +25,10 @@ public final class EntityBeanIntercept implements Serializable {
private static final long serialVersionUID = -3664031775464862649L;
+ private static final int STATE_NEW = 0;
+ private static final int STATE_REFERENCE = 1;
+ private static final int STATE_LOADED = 2;
+
private transient NodeUsageCollector nodeUsageCollector;
private transient PropertyChangeSupport pcs;
@@ -31,7 +36,7 @@ public final class EntityBeanIntercept implements Serializable {
private transient PersistenceContext persistenceContext;
private transient BeanLoader beanLoader;
-
+
private int beanLoaderIndex;
private String ebeanServerName;
@@ -44,54 +49,43 @@ public final class EntityBeanIntercept implements Serializable {
/**
* The parent bean by relationship (1-1 or 1-M).
*/
- private Object parentBean;
+ private EntityBean embeddedOwner;
+ private int embeddedOwnerIndex;
/**
- * true if the bean properties have been loaded. false if it is a reference
- * bean (will lazy load etc).
+ * One of NEW, REF, UPD.
*/
- private volatile boolean loaded;
-
+ private int state;
+
+ private boolean readOnly;
+
+ private boolean dirty;
+
/**
- * Flag set to disable lazy loading - typically for SQL "report" type entity
- * beans.
+ * Flag set to disable lazy loading - typically for SQL "report" type entity beans.
*/
private boolean disableLazyLoad;
/**
- * Flag set when lazy loading failed due to the underlying bean being deleted
- * in the DB.
+ * Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
*/
private boolean lazyLoadFailure;
- /**
- * Set true when loaded or reference. Used to bypass interception when created
- * by user code.
- */
- private boolean intercepting;
-
- /**
- * The state of the Bean (DEFAULT,UDPATE,READONLY,SHARED).
- */
- private boolean readOnly;
-
- /**
- * The bean as it was before it was modified. Null if no non-transient setters
- * have been called.
- */
- private Object oldValues;
-
/**
* Used when a bean is partially filled.
*/
- private volatile boolean[] loadedProps;
+ private boolean[] loadedProps;
+
+ private boolean fullyLoadedBean;
/**
* Set of changed properties.
*/
private boolean[] changedProps;
- private int lazyLoadProperty;
+ private Object[] origValues;
+
+ private int lazyLoadProperty = -1;
/**
* Create a intercept with a given entity.
@@ -99,20 +93,9 @@ public final class EntityBeanIntercept implements Serializable {
* Refer to agent ProxyConstructor.
*
*/
- public EntityBeanIntercept(Object owner) {
- this.owner = (EntityBean) owner;
- }
-
- /**
- * Copy the internal state of the intercept to another intercept.
- */
- public void copyStateTo(EntityBeanIntercept dest) {
- dest.loadedProps = loadedProps;
- dest.ebeanServerName = ebeanServerName;
-
- if (loaded) {
- dest.setLoaded();
- }
+ public EntityBeanIntercept(Object ownerBean) {
+ this.owner = (EntityBean) ownerBean;
+ this.loadedProps = new boolean[owner._ebean_getPropertyNames().length];
}
/**
@@ -122,13 +105,6 @@ public final class EntityBeanIntercept implements Serializable {
return owner;
}
- public String toString() {
- if (!loaded) {
- return "Reference...";
- }
- return "OldValues: " + oldValues;
- }
-
/**
* Return the persistenceContext.
*/
@@ -193,16 +169,17 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Return the parent bean (by relationship).
*/
- public Object getParentBean() {
- return parentBean;
+ public Object getEmbeddedOwner() {
+ return embeddedOwner;
}
/**
* Special case for a OneToOne, Set the parent bean (by relationship). This is
* the owner of a 1-1.
*/
- public void setParentBean(Object parentBean) {
- this.parentBean = parentBean;
+ public void setEmbeddedOwner(EntityBean parentBean, int embeddedOwnerIndex) {
+ this.embeddedOwner = parentBean;
+ this.embeddedOwnerIndex = embeddedOwnerIndex;
}
/**
@@ -233,24 +210,37 @@ public final class EntityBeanIntercept implements Serializable {
this.persistenceContext = ctx;
this.ebeanServerName = beanLoader.getName();
}
+
+ public boolean isFullyLoadedBean() {
+ return fullyLoadedBean;
+ }
+
+ public void setFullyLoadedBean(boolean fullyLoadedBean) {
+ this.fullyLoadedBean = fullyLoadedBean;
+ }
/**
* Return true if this bean has been directly modified (it has oldValues) or
* if any embedded beans are either new or dirty (and hence need saving).
*/
public boolean isDirty() {
- if (oldValues != null) {
- return true;
- }
- // need to check all the embedded beans
- return owner._ebean_isEmbeddedNewOrDirty();
+ return dirty;
+ }
+
+ public void setEmbeddedDirty(int embeddedProperty) {
+ this.dirty = true;
+ setChangedProperty(embeddedProperty);
+ }
+
+ public void setDirty(boolean dirty) {
+ this.dirty = dirty;
}
/**
* Return true if this entity bean is new and not yet saved.
*/
public boolean isNew() {
- return !intercepting && !loaded;
+ return state == STATE_NEW;
}
/**
@@ -264,22 +254,14 @@ public final class EntityBeanIntercept implements Serializable {
* Return true if the entity is a reference.
*/
public boolean isReference() {
- return intercepting && !loaded;
+ return state == STATE_REFERENCE;
}
/**
* Set this as a reference object.
*/
public void setReference() {
- this.loaded = false;
- this.intercepting = true;
- }
-
- /**
- * Return the old values used for ConcurrencyMode.ALL.
- */
- public Object getOldValues() {
- return oldValues;
+ state = STATE_REFERENCE;
}
/**
@@ -298,33 +280,11 @@ public final class EntityBeanIntercept implements Serializable {
this.readOnly = readOnly;
}
- /**
- * Return true if the bean currently has interception on.
- *
- * With interception on the bean will invoke lazy loading and dirty checking.
- *
- */
- public boolean isIntercepting() {
- return intercepting;
- }
-
- /**
- * Turn interception off or on.
- *
- * This is to support custom serialisation mechanisms that just read all the
- * properties on the bean.
- *
- *
- */
- public void setIntercepting(boolean intercepting) {
- this.intercepting = intercepting;
- }
-
/**
* Return true if the entity has been loaded.
*/
public boolean isLoaded() {
- return loaded;
+ return state == STATE_LOADED;
}
/**
@@ -339,12 +299,12 @@ public final class EntityBeanIntercept implements Serializable {
*
*/
public void setLoaded() {
- this.loaded = true;
- this.oldValues = null;
- this.intercepting = true;
+ this.state = STATE_LOADED;
this.owner._ebean_setEmbeddedLoaded();
this.lazyLoadProperty = -1;
+ this.origValues = null;
this.changedProps = null;
+ this.dirty = false;
}
/**
@@ -352,8 +312,7 @@ public final class EntityBeanIntercept implements Serializable {
* bean.
*/
public void setLoadedLazy() {
- this.loaded = true;
- this.intercepting = true;
+ this.state = STATE_LOADED;
this.lazyLoadProperty = -1;
}
@@ -423,27 +382,104 @@ public final class EntityBeanIntercept implements Serializable {
}
}
- /**
- * Set the property names for a partially loaded bean.
- *
- * @param loadedPropertyNames
- * the names of the loaded properties
- */
-// public void setLoadedProps(boolean[] loadedPropertyNames) {
-// this.loadedProps = loadedPropertyNames;
-// }
+ public String getProperty(int propertyIndex) {
+ if (propertyIndex == -1) {
+ return null;
+ }
+ return owner._ebean_getPropertyName(propertyIndex);
+ }
- public void setLoadedProps(Set loadedPropertyNames) {
+ public int getPropertyLength() {
+ return owner._ebean_getPropertyNames().length;
+ }
+
+ public void setLoadedProperty(int propertyIndex) {
+ loadedProps[propertyIndex] = true;
+ }
+
+ public boolean isLoadedProperty(int propertyIndex) {
+ return loadedProps[propertyIndex];
+ }
+
+ public boolean isChangedProperty(int propertyIndex) {
+ return (changedProps != null && changedProps[propertyIndex]);
+ }
+
+ /**
+ * Explicitly mark a property as having been changed.
+ */
+ public void markPropertyAsChanged(int propertyIndex) {
+ setChangedProperty(propertyIndex);
+ setDirty(true);
+ }
+
+ private void setChangedProperty(int propertyIndex) {
+ if (changedProps == null) {
+ changedProps = new boolean[owner._ebean_getPropertyNames().length];
+ }
+ changedProps[propertyIndex] = true;
+ }
+
+ private void setOriginalValue(int propertyIndex, Object value) {
+ if (origValues == null) {
+ origValues = new Object[owner._ebean_getPropertyNames().length];
+ }
+ if (origValues[propertyIndex] == null) {
+ origValues[propertyIndex] = value;
+ }
+ }
+
+ /**
+ * For forced update on a 'New' bean move set all the changedProperties to loaded properties.
+ */
+ public void setNewBeanForUpdate() {
+
+ for (int i=0; i< loadedProps.length; i++) {
+ if (loadedProps[i]) {
+ setChangedProperty(i);
+ }
+ }
+ setDirty(true);
}
/**
* Return the set of property names for a partially loaded bean.
*/
-// public boolean[] getLoadedProps() {
-// return loadedProps;
-// }
- public Set getLoadedProps() {
- return null;
+ public Set getLoadedPropertyNames() {
+ if (fullyLoadedBean) {
+ return null;
+ }
+ Set props = new LinkedHashSet();
+ for (int i=0; i getChangedPropertyNames() {
+ Set props = new LinkedHashSet();
+ if (changedProps != null) {
+ for (int i=0; i getChangedProps() {
- return null;
+
+ public boolean[] getLoaded() {
+ return loadedProps;
}
/**
* Return the property read or write that triggered the lazy load.
*/
-// public int getLazyLoadProperty() {
-// return lazyLoadProperty;
-// }
- public String getLazyLoadProperty() {
- return null;
+ public int getLazyLoadProperty() {
+ return lazyLoadProperty;
}
/**
@@ -498,16 +531,11 @@ public final class EntityBeanIntercept implements Serializable {
*/
private void loadBeanInternal(int loadProperty, BeanLoader loader) {
- if (loaded && (loadedProps == null || loadedProps[loadProperty])) {
+ if (loadedProps == null || loadedProps[loadProperty]) {
// race condition where multiple threads calling preGetter concurrently
return;
}
- if (disableLazyLoad) {
- loaded = true;
- return;
- }
-
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
throw new EntityNotFoundException("Bean has been deleted - lazy loading failed");
@@ -533,20 +561,6 @@ public final class EntityBeanIntercept implements Serializable {
}
}
- /**
- * Create a copy of the bean as it is now. This is the original or 'old
- * values' prior to any modification. This is used to perform concurrency
- * testing.
- */
- protected void createOldValues() {
-
- oldValues = owner._ebean_createCopy();
-
- if (nodeUsageCollector != null) {
- nodeUsageCollector.setModified();
- }
- }
-
/**
* Helper method to check if two objects are equal.
*/
@@ -571,7 +585,6 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return false;
}
-
}
if (obj1 instanceof URL) {
// use the string format to determine if dirty
@@ -582,22 +595,17 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Method that is called prior to a getter method on the actual entity.
- *
- * This checks if the bean is a reference and should be loaded.
- *
*/
public void preGetter(int propertyIndex) {
- if (!intercepting) {
+ if (state == STATE_NEW || disableLazyLoad) {
return;
}
-
- if (!loaded) {
- loadBean(propertyIndex);
- } else if (loadedProps != null && !loadedProps[propertyIndex]) {
+
+ if (!isLoadedProperty(propertyIndex)) {
loadBean(propertyIndex);
}
- if (nodeUsageCollector != null && loaded) {
+ if (nodeUsageCollector != null) {
nodeUsageCollector.addUsed(getProperty(propertyIndex));
}
}
@@ -631,10 +639,15 @@ public final class EntityBeanIntercept implements Serializable {
* OneToMany and ManyToMany don't have any interception so just check for
* PropertyChangeSupport.
*/
- public PropertyChangeEvent preSetterMany(boolean interceptField, int propertyIndex,
- Object oldValue, Object newValue) {
+ public PropertyChangeEvent preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
- // skip setter interception on many's
+ if (readOnly) {
+ throw new IllegalStateException("This bean is readOnly");
+ }
+
+ setLoadedProperty(propertyIndex);
+
+ // Bean itself not considered dirty when many changed
if (pcs != null) {
return new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
} else {
@@ -642,57 +655,27 @@ public final class EntityBeanIntercept implements Serializable {
}
}
- public String getProperty(int propertyIndex) {
- return owner._ebean_getPropertyName(propertyIndex);
- }
-
- public int getPropertyLength() {
- return owner._ebean_getPropertyNames().length;
- }
+ private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
- private final void changedProperty(int propertyIndex, boolean setDirty) {
-
- if (changedProps == null) {
- changedProps = new boolean[owner._ebean_getPropertyNames().length];
- }
- changedProps[propertyIndex] = true;
-
- if (!setDirty || !intercepting) {
- return;
- }
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
+ setChangedProperty(propertyIndex);
- if (loaded) {
- if (oldValues == null) {
- // first time this bean is being made dirty
- createOldValues();
+ if (setDirtyState) {
+ setOriginalValue(propertyIndex, origValue);
+ if (!dirty) {
+ dirty = true;
+ if (embeddedOwner != null) {
+ // Cascade dirty state from Embedded bean to parent bean
+ embeddedOwner._ebean_getIntercept().setEmbeddedDirty(embeddedOwnerIndex);
+ }
+ if (nodeUsageCollector != null) {
+ nodeUsageCollector.setModified();
+ }
}
}
}
-
- private final void addDirty(int propertyIndex) {
-
- if (!intercepting) {
- return;
- }
- if (readOnly) {
- throw new IllegalStateException("This bean is readOnly");
- }
-
- if (loaded) {
- if (oldValues == null) {
- // first time this bean is being made dirty
- createOldValues();
- }
- if (changedProps == null) {
- changedProps = new boolean[getPropertyLength()];
- }
- changedProps[propertyIndex] = true;
- }
- }
-
/**
* Check to see if the values are not equal. If they are not equal then create
@@ -700,205 +683,167 @@ public final class EntityBeanIntercept implements Serializable {
*/
public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
- // If state 'new' then mark property as changed
- // Else state is 'update', check for change
- if (!areEqual(oldValue, newValue)) {
- changedProperty(propertyIndex, intercept);
- if (pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
- }
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (!areEqual(oldValue, newValue)) {
+ setChangedPropertyValue(propertyIndex, intercept, newValue);
+ } else {
+ return null;
}
-
- return null;
+
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
-
+
+
/**
* Check for primitive boolean.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, boolean oldValue,
- boolean newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Boolean.valueOf(oldValue),
- Boolean.valueOf(newValue));
- }
-
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
}
/**
* Check for primitive int.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, int oldValue,
- int newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Integer.valueOf(oldValue),
- Integer.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Integer.valueOf(oldValue), Integer.valueOf(newValue));
}
/**
* long.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, long oldValue,
- long newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Long.valueOf(oldValue),
- Long.valueOf(newValue));
- }
- return null;
+
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Long.valueOf(oldValue), Long.valueOf(newValue));
}
/**
* double.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, double oldValue,
- double newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Double.valueOf(oldValue),
- Double.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Double.valueOf(oldValue), Double.valueOf(newValue));
}
/**
* float.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, float oldValue,
- float newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Float.valueOf(oldValue),
- Float.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Float.valueOf(oldValue), Float.valueOf(newValue));
}
/**
* short.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, short oldValue,
- short newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Short.valueOf(oldValue),
- Short.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Short.valueOf(oldValue), Short.valueOf(newValue));
}
/**
* char.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, char oldValue,
- char newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Character.valueOf(oldValue),
- Character.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Character.valueOf(oldValue), Character.valueOf(newValue));
}
/**
- * char.
+ * byte.
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, byte oldValue,
- byte newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
- boolean changed = oldValue != newValue;
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (oldValue != newValue) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), Byte.valueOf(oldValue),
- Byte.valueOf(newValue));
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Byte.valueOf(oldValue), Byte.valueOf(newValue));
}
/**
* char[].
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, char[] oldValue,
- char[] newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
- boolean changed = !areEqualChars(oldValue, newValue);
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (!areEqualChars(oldValue, newValue)) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
- }
- return null;
+ return (pcs == null) ? null: new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
* byte[].
*/
- public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, byte[] oldValue,
- byte[] newValue) {
+ public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
- boolean changed = !areEqualBytes(oldValue, newValue);
-
- if (intercept && changed) {
- addDirty(propertyIndex);
+ if (state == STATE_NEW) {
+ setLoadedProperty(propertyIndex);
+ } else if (!areEqualBytes(oldValue, newValue)) {
+ setChangedPropertyValue(propertyIndex, intercept, oldValue);
+ } else {
+ return null;
}
-
- if (changed && pcs != null) {
- return new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
- }
- return null;
+ return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
private static boolean areEqualBytes(byte[] b1, byte[] b2) {
diff --git a/src/main/java/com/avaje/ebean/common/AbstractBeanCollection.java b/src/main/java/com/avaje/ebean/common/AbstractBeanCollection.java
index a9cacd874..265c6541b 100644
--- a/src/main/java/com/avaje/ebean/common/AbstractBeanCollection.java
+++ b/src/main/java/com/avaje/ebean/common/AbstractBeanCollection.java
@@ -12,7 +12,6 @@ import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionLoader;
import com.avaje.ebean.bean.BeanCollectionTouched;
import com.avaje.ebean.bean.EntityBean;
-import com.avaje.ebean.bean.EntityBeanIntercept;
/**
* Base class for List Set and Map implementations of BeanCollection.
@@ -43,7 +42,7 @@ public abstract class AbstractBeanCollection implements BeanCollection {
/**
* The owning bean (used for lazy fetch).
*/
- protected final Object ownerBean;
+ protected final EntityBean ownerBean;
/**
* The name of this property in the owning bean (used for lazy fetch).
@@ -81,19 +80,15 @@ public abstract class AbstractBeanCollection implements BeanCollection {
/**
* Used to create deferred fetch proxy.
*/
- public AbstractBeanCollection(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
+ public AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
this.loader = loader;
this.ebeanServerName = loader.getName();
this.ownerBean = ownerBean;
this.propertyName = propertyName;
-
- if (ownerBean instanceof EntityBean) {
- EntityBeanIntercept ebi = ((EntityBean) ownerBean)._ebean_getIntercept();
- this.readOnly = ebi.isReadOnly();
- }
+ this.readOnly = ownerBean._ebean_getIntercept().isReadOnly();
}
- public Object getOwnerBean() {
+ public EntityBean getOwnerBean() {
return ownerBean;
}
diff --git a/src/main/java/com/avaje/ebean/common/BeanList.java b/src/main/java/com/avaje/ebean/common/BeanList.java
index 8207eff8e..dee944729 100644
--- a/src/main/java/com/avaje/ebean/common/BeanList.java
+++ b/src/main/java/com/avaje/ebean/common/BeanList.java
@@ -10,6 +10,7 @@ import java.util.ListIterator;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.BeanCollectionLoader;
+import com.avaje.ebean.bean.EntityBean;
/**
* List capable of lazy loading.
@@ -40,12 +41,12 @@ public final class BeanList extends AbstractBeanCollection implements List
/**
* Used to create deferred fetch proxy.
*/
- public BeanList(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
+ public BeanList(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
super(loader, ownerBean, propertyName);
}
@SuppressWarnings("unchecked")
- public void addBean(Object bean) {
+ public void addBean(EntityBean bean) {
list.add((E) bean);
}
diff --git a/src/main/java/com/avaje/ebean/common/BeanMap.java b/src/main/java/com/avaje/ebean/common/BeanMap.java
index ff3c3e6f2..bdc273616 100644
--- a/src/main/java/com/avaje/ebean/common/BeanMap.java
+++ b/src/main/java/com/avaje/ebean/common/BeanMap.java
@@ -8,6 +8,7 @@ import java.util.Map;
import java.util.Set;
import com.avaje.ebean.bean.BeanCollectionLoader;
+import com.avaje.ebean.bean.EntityBean;
/**
* Map capable of lazy loading.
@@ -33,7 +34,7 @@ public final class BeanMap extends AbstractBeanCollection implements Ma
this(new LinkedHashMap());
}
- public BeanMap(BeanCollectionLoader ebeanServer, Object ownerBean, String propertyName) {
+ public BeanMap(BeanCollectionLoader ebeanServer, EntityBean ownerBean, String propertyName) {
super(ebeanServer, ownerBean, propertyName);
}
diff --git a/src/main/java/com/avaje/ebean/common/BeanSet.java b/src/main/java/com/avaje/ebean/common/BeanSet.java
index f3a41b4dc..5e1c0de13 100644
--- a/src/main/java/com/avaje/ebean/common/BeanSet.java
+++ b/src/main/java/com/avaje/ebean/common/BeanSet.java
@@ -8,6 +8,7 @@ import java.util.Set;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.BeanCollectionLoader;
+import com.avaje.ebean.bean.EntityBean;
/**
* Set capable of lazy loading.
@@ -34,12 +35,12 @@ public final class BeanSet extends AbstractBeanCollection implements Set());
}
- public BeanSet(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
+ public BeanSet(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
super(loader, ownerBean, propertyName);
}
@SuppressWarnings("unchecked")
- public void addBean(Object bean) {
+ public void addBean(EntityBean bean) {
set.add((E) bean);
}
diff --git a/src/main/java/com/avaje/ebean/event/BeanPersistListener.java b/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
index 1b1e1f23d..f38aee387 100644
--- a/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
+++ b/src/main/java/com/avaje/ebean/event/BeanPersistListener.java
@@ -54,7 +54,7 @@ public interface BeanPersistListener {
* @param updatedProperties
* the properties on the bean that where updated
*/
- public boolean updated(T bean, Set updatedProperties);
+ public boolean updated(T bean);//, Set updatedProperties);
/**
* Notified that a bean has been deleted locally. Return true if you want the
diff --git a/src/main/java/com/avaje/ebean/event/BeanPersistRequest.java b/src/main/java/com/avaje/ebean/event/BeanPersistRequest.java
index 97573bcf6..88053c703 100644
--- a/src/main/java/com/avaje/ebean/event/BeanPersistRequest.java
+++ b/src/main/java/com/avaje/ebean/event/BeanPersistRequest.java
@@ -1,7 +1,5 @@
package com.avaje.ebean.event;
-import java.util.Set;
-
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Transaction;
@@ -24,29 +22,29 @@ public interface BeanPersistRequest {
*/
public Transaction getTransaction();
- /**
- * For an update or delete of a partially populated bean this is the set of
- * loaded properties and otherwise returns null.
- */
- public Set getLoadedProperties();
-
- /**
- * For an update this is the set of properties that where updated.
- */
- public Set getUpdatedProperties();
+// /**
+// * For an update or delete of a partially populated bean this is the set of
+// * loaded properties and otherwise returns null.
+// */
+// public Set getLoadedProperties();
+//
+// /**
+// * For an update this is the set of properties that where updated.
+// */
+// public Set getUpdatedProperties();
/**
* Returns the bean being inserted updated or deleted.
*/
public T getBean();
- /**
- * Returns a bean containing the original values prior to the bean being
- * modified.
- *
- * This is for updates only.
- *
- */
- public T getOldValues();
+// /**
+// * Returns a bean containing the original values prior to the bean being
+// * modified.
+// *
+// * This is for updates only.
+// *
+// */
+// public T getOldValues();
}
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java b/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java
index 89588954f..9ac23a9af 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiUpdatePlan.java
@@ -1,9 +1,9 @@
package com.avaje.ebeaninternal.api;
import java.sql.SQLException;
-import java.util.Set;
import com.avaje.ebean.annotation.ConcurrencyMode;
+import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.persist.dml.DmlHandler;
import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
@@ -21,20 +21,20 @@ import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
*/
public interface SpiUpdatePlan {
- /**
- * Return true if the set clause has no columns.
- *
- * Can occur when the only columns updated have a updatable=false in their
- * deployment.
- *
- */
- public boolean isEmptySetClause();
+ /**
+ * Return true if the set clause has no columns.
+ *
+ * Can occur when the only columns updated have a updatable=false in their
+ * deployment.
+ *
+ */
+ public boolean isEmptySetClause();
/**
* Bind given the request and bean. The bean could be the oldValues bean
* when binding a update or delete where clause with ALL concurrency mode.
*/
- public void bindSet(DmlHandler bind, Object bean) throws SQLException;
+ public void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
/**
* Return the time this plan was created.
@@ -66,10 +66,10 @@ public interface SpiUpdatePlan {
*/
public Bindable getSet();
- /**
- * Return the properties that where changed and should be included in the
- * update statement.
- */
- public Set getProperties();
+// /**
+// * Return the properties that where changed and should be included in the
+// * update statement.
+// */
+// public Set getProperties();
}
\ No newline at end of file
diff --git a/src/main/java/com/avaje/ebeaninternal/server/autofetch/StatisticsNodeUsage.java b/src/main/java/com/avaje/ebeaninternal/server/autofetch/StatisticsNodeUsage.java
index c806f4138..ef463af5a 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/autofetch/StatisticsNodeUsage.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/autofetch/StatisticsNodeUsage.java
@@ -93,9 +93,9 @@ public class StatisticsNodeUsage implements Serializable {
}
if ((modified || queryTuningAddVersion) && desc != null) {
- BeanProperty[] versionProps = desc.propertiesVersion();
- if (versionProps.length > 0) {
- pathProps.addToPath(path, versionProps[0].getName());
+ BeanProperty versionProp = desc.getVersionProperty();
+ if (versionProp != null) {
+ pathProps.addToPath(path, versionProp.getName());
}
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanData.java b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanData.java
index 53ebf05a1..e08e29ffb 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanData.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanData.java
@@ -1,50 +1,51 @@
package com.avaje.ebeaninternal.server.cache;
-import java.util.Set;
-
public class CachedBeanData {
- private final Object sharableBean;
- private final Set loadedProperties;
- private final Object[] data;
- private final int naturalKeyUpdate;
-
- public CachedBeanData(Object sharableBean, Set loadedProperties, Object[] data, int naturalKeyUpdate) {
- this.sharableBean = sharableBean;
- this.loadedProperties= loadedProperties;
- this.data = data;
- this.naturalKeyUpdate = naturalKeyUpdate;
- }
-
- public Object getSharableBean() {
- return sharableBean;
- }
+ private final Object sharableBean;
+ private final boolean[] loaded;
+ private final Object[] data;
+ private final int naturalKeyUpdate;
- public boolean isNaturalKeyUpdate() {
- return naturalKeyUpdate > -1;
- }
-
- public Object getNaturalKey() {
- return data[naturalKeyUpdate];
- }
+ public CachedBeanData(Object sharableBean, boolean[] loaded, Object[] data, int naturalKeyUpdate) {
+ this.sharableBean = sharableBean;
+ this.loaded = loaded;
+ this.data = data;
+ this.naturalKeyUpdate = naturalKeyUpdate;
+ }
+
+ public Object getSharableBean() {
+ return sharableBean;
+ }
+
+ public boolean isNaturalKeyUpdate() {
+ return naturalKeyUpdate > -1;
+ }
+
+ public Object getNaturalKey() {
+ return data[naturalKeyUpdate];
+ }
+
+ public boolean containsProperty(int propIndex) {
+ return loaded[propIndex];
+ }
+
+ public boolean[] getLoaded() {
+ return loaded;
+ }
+
+ public Object getData(int i) {
+ return data[i];
+ }
+
+ public Object[] copyData() {
+ Object[] dest = new Object[data.length];
+ System.arraycopy(data, 0, dest, 0, data.length);
+ return dest;
+ }
+
+ public boolean isLoaded(int i) {
+ return loaded[i];
+ }
- public boolean containsProperty(String propName) {
- return loadedProperties == null || loadedProperties.contains(propName);
- }
-
- public Object getData(int i){
- return data[i];
- }
-
- public Set getLoadedProperties() {
- return loadedProperties;
- }
-
- public Object[] copyData() {
- Object[] dest = new Object[data.length];
- System.arraycopy(data, 0, dest, 0, data.length);
- return dest;
- }
-
}
-
diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java
index c2f5025c2..370d79c33 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java
@@ -1,8 +1,5 @@
package com.avaje.ebeaninternal.server.cache;
-import java.util.HashSet;
-import java.util.Set;
-
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
@@ -10,94 +7,73 @@ import com.avaje.ebeaninternal.server.deploy.BeanProperty;
public class CachedBeanDataFromBean {
- private final BeanDescriptor> desc;
- private final Object bean;
- private final EntityBeanIntercept ebi;
-
- private final Set loadedProps;
- private final Set extractProps;
+ private final BeanDescriptor> desc;
+ private final EntityBean bean;
+ private final EntityBeanIntercept ebi;
- public static CachedBeanData extract(BeanDescriptor> desc, Object bean){
- if (bean instanceof EntityBean){
- return new CachedBeanDataFromBean(desc, bean, ((EntityBean)bean)._ebean_getIntercept()).extract();
-
- } else {
- return new CachedBeanDataFromBean(desc, bean, null).extract();
- }
- }
-
- public static CachedBeanData extract(BeanDescriptor> desc, Object bean, EntityBeanIntercept ebi){
- return new CachedBeanDataFromBean(desc, bean, ebi).extract();
- }
-
- private CachedBeanDataFromBean(BeanDescriptor> desc, Object bean, EntityBeanIntercept ebi) {
- this.desc = desc;
- this.bean = bean;
- this.ebi = ebi;
- if (ebi != null){
- this.loadedProps = ebi.getLoadedProps();
- this.extractProps = (loadedProps == null) ? null : new HashSet();
- } else {
- this.extractProps = new HashSet();
- this.loadedProps = null;
- }
- }
-
- private CachedBeanData extract(){
+ public static CachedBeanData extract(BeanDescriptor> desc, EntityBean bean) {
+ return new CachedBeanDataFromBean(desc, bean, bean._ebean_getIntercept()).extract();
+ }
- BeanProperty[] props = desc.propertiesNonMany();
+ private CachedBeanDataFromBean(BeanDescriptor> desc, EntityBean bean, EntityBeanIntercept ebi) {
+ this.desc = desc;
+ this.bean = bean;
+ this.ebi = ebi;
+ }
- Object[] data = new Object[props.length];
-
- int naturalKeyUpdate = -1;
- for (int i = 0; i < props.length; i++) {
- BeanProperty prop = props[i];
- if (includeNonManyProperty(prop.getName())){
-
- data[i] = prop.getCacheDataValue(bean);
- if (prop.isNaturalKey()) {
- naturalKeyUpdate = i;
- }
- if (ebi != null){
- if (extractProps != null){
- extractProps.add(prop.getName());
- }
- } else if (data[i] != null){
- if (extractProps != null){
- extractProps.add(prop.getName());
- }
- }
- }
- }
-
- Object sharableBean = null;
- if (desc.isCacheSharableBeans() && ebi != null && loadedProps == null){
- if (ebi.isReadOnly()){
- sharableBean = bean;
- } else {
- // create a readOnly sharable instance by copying the data
- sharableBean = desc.createBean();
- BeanProperty[] propertiesId = desc.propertiesId();
- for (int i = 0; i < propertiesId.length; i++) {
- Object v = propertiesId[i].getValue(bean);
- propertiesId[i].setValue(sharableBean, v);
- }
- BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
- for (int i = 0; i < propertiesNonTransient.length; i++) {
- Object v = propertiesNonTransient[i].getValue(bean);
- propertiesNonTransient[i].setValue(sharableBean, v);
- }
- EntityBeanIntercept ebi = ((EntityBean)sharableBean)._ebean_intercept();
- ebi.setReadOnly(true);
- ebi.setLoaded();
- }
- }
-
- return new CachedBeanData(sharableBean, extractProps, data, naturalKeyUpdate);
- }
+ private CachedBeanData extract() {
+
+ Object[] data = new Object[desc.getPropertyCount()];
+ boolean[] loaded = new boolean[desc.getPropertyCount()];
- private boolean includeNonManyProperty(String name) {
- return loadedProps == null || loadedProps.contains(name);
+ BeanProperty[] props = desc.propertiesNonMany();
+
+ int naturalKeyUpdate = -1;
+ for (int i = 0; i < props.length; i++) {
+ BeanProperty prop = props[i];
+ if (isLoaded(prop)) {
+ int propertyIndex = prop.getPropertyIndex();
+ data[propertyIndex] = prop.getCacheDataValue(bean);
+ loaded[propertyIndex] = true;
+ if (prop.isNaturalKey()) {
+ naturalKeyUpdate = propertyIndex;
+ }
+ }
}
+
+ EntityBean sharableBean = createSharableBean();
+
+ return new CachedBeanData(sharableBean, loaded, data, naturalKeyUpdate);
+ }
+
+ private EntityBean createSharableBean() {
+ if (!desc.isCacheSharableBeans() || !ebi.isFullyLoadedBean()) {
+ return null;
+ }
+ if (ebi.isReadOnly()) {
+ return bean;
+ }
+ // create a readOnly sharable instance by copying the data
+ EntityBean sharableBean = desc.createBean();
+ BeanProperty[] propertiesId = desc.propertiesId();
+ for (int i = 0; i < propertiesId.length; i++) {
+ Object v = propertiesId[i].getValue(bean);
+ propertiesId[i].setValue(sharableBean, v);
+ }
+ BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
+ for (int i = 0; i < propertiesNonTransient.length; i++) {
+ Object v = propertiesNonTransient[i].getValue(bean);
+ propertiesNonTransient[i].setValue(sharableBean, v);
+ }
+ EntityBeanIntercept ebi = ((EntityBean) sharableBean)._ebean_intercept();
+ ebi.setReadOnly(true);
+ ebi.setLoaded();
+ return sharableBean;
+ }
+
+ private boolean isLoaded(BeanProperty prop) {
+ return ebi.isLoadedProperty(prop.getPropertyIndex());
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataToBean.java b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataToBean.java
index 5199d8375..db3082753 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataToBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataToBean.java
@@ -1,8 +1,5 @@
package com.avaje.ebeaninternal.server.cache;
-import java.util.HashSet;
-import java.util.Set;
-
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.bean.EntityBeanIntercept;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
@@ -11,107 +8,55 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
public class CachedBeanDataToBean {
- private final BeanDescriptor> desc;
- private final Object bean;
- private final EntityBeanIntercept ebi;
- private final CachedBeanData cacheBeandata;
- private final Set cacheLoadedProperties;
- private final Set loadedProps;
-
- private final Set excludeProps;
- private final Object oldValuesBean;
- private final boolean readOnly;
+ private final BeanDescriptor> desc;
+ private final EntityBean bean;
+ private final EntityBeanIntercept ebi;
+ private final CachedBeanData cacheBeanData;
+ //private final boolean readOnly;
- public static void load(BeanDescriptor> desc, Object bean, CachedBeanData cacheBeandata) {
- if (bean instanceof EntityBean){
- load(desc, bean, ((EntityBean)bean)._ebean_getIntercept(), cacheBeandata);
- } else {
- load(desc, bean, null, cacheBeandata);
- }
- }
+ public static boolean load(BeanDescriptor> desc, EntityBean bean, CachedBeanData cacheBeandata) {
+ return new CachedBeanDataToBean(desc, bean, ((EntityBean) bean)._ebean_getIntercept(), cacheBeandata).load();
+ }
- public static void load(BeanDescriptor> desc, Object bean, EntityBeanIntercept ebi, CachedBeanData cacheBeandata) {
- new CachedBeanDataToBean(desc, bean, ebi, cacheBeandata).load();
- }
-
- private CachedBeanDataToBean(BeanDescriptor> desc, Object bean, EntityBeanIntercept ebi, CachedBeanData cacheBeandata) {
- this.desc = desc;
- this.bean = bean;
- this.ebi = ebi;
- this.cacheBeandata = cacheBeandata;
- this.cacheLoadedProperties = cacheBeandata.getLoadedProperties();
- this.loadedProps = (cacheLoadedProperties == null) ? null : new HashSet();
-
- if (ebi != null){
- this.excludeProps = ebi.getLoadedProps();
- this.oldValuesBean = ebi.getOldValues();
- this.readOnly = ebi.isReadOnly();
+ private CachedBeanDataToBean(BeanDescriptor> desc, EntityBean bean, EntityBeanIntercept ebi, CachedBeanData cacheBeandata) {
+ this.desc = desc;
+ this.bean = bean;
+ this.ebi = ebi;
+ this.cacheBeanData = cacheBeandata;
+ //this.readOnly = ebi.isReadOnly();
+ }
+
+ private boolean load() {
+
+ BeanProperty[] props = desc.propertiesNonMany();
+ for (int i = 0; i < props.length; i++) {
+
+ BeanProperty prop = props[i];
+ int propertyIndex = prop.getPropertyIndex();
+ if (cacheBeanData.isLoaded(propertyIndex)) {
+ if (ebi.isLoadedProperty(propertyIndex)) {
+ // already loaded (lazy load on partially loaded bean)
} else {
- this.excludeProps = null;
- this.oldValuesBean = null;
- this.readOnly = false;
+ Object data = cacheBeanData.getData(propertyIndex);
+ prop.setCacheDataValue(bean, data);
}
+ }
}
-
- private boolean load(){
-
- BeanProperty[] propertiesNonTransient = desc.propertiesNonMany();
- for (int i = 0; i < propertiesNonTransient.length; i++) {
- BeanProperty prop = propertiesNonTransient[i];
- if (includeNonManyProperty(prop.getName())){
- Object data = cacheBeandata.getData(i);
- prop.setCacheDataValue(bean, data, oldValuesBean, readOnly);
- }
- }
- BeanPropertyAssocMany>[] manys = desc.propertiesMany();
- for (int i = 0; i < manys.length; i++) {
- BeanPropertyAssocMany> prop = manys[i];
- if (includeManyProperty(prop.getName())){
- // set a lazy loading proxy
- prop.createReference(bean);
- }
- }
-
- if (ebi != null){
- if (loadedProps == null){
- ebi.setLoadedProps(null);
- } else {
- HashSet mergeProps = new HashSet();
- if (excludeProps != null) {
- mergeProps.addAll(excludeProps);
- }
- mergeProps.addAll(loadedProps);
- ebi.setLoadedProps(mergeProps);
- }
- ebi.setLoadedLazy();
- }
- return true;
+ BeanPropertyAssocMany>[] manys = desc.propertiesMany();
+ for (int i = 0; i < manys.length; i++) {
+ BeanPropertyAssocMany> prop = manys[i];
+ if (ebi.isLoadedProperty(prop.getPropertyIndex())) {
+ // already loaded property
+ } else {
+ // set a lazy loading proxy
+ prop.createReference(bean);
+ }
}
-
- private boolean includeManyProperty(String name) {
- if (excludeProps != null && excludeProps.contains(name)){
- // ignore this property (partial bean lazy loading)
- return false;
- }
- if (loadedProps != null){
- loadedProps.add(name);
- }
- return true;
- }
-
- private boolean includeNonManyProperty(String name) {
- if (excludeProps != null && excludeProps.contains(name)){
- // ignore this property (partial bean lazy loading)
- return false;
- }
- if (cacheLoadedProperties != null && !cacheLoadedProperties.contains(name)){
- return false;
- }
- if (loadedProps != null){
- loadedProps.add(name);
- }
- return true;
- }
-
+
+ ebi.setLoadedLazy();
+
+ return true;
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataUpdate.java b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataUpdate.java
index 93c883213..dbe0a8d94 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataUpdate.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataUpdate.java
@@ -11,37 +11,38 @@ public class CachedBeanDataUpdate {
public static CachedBeanData update(BeanDescriptor> desc, CachedBeanData data, PersistRequestBean> updateRequest){
-
- Set loadedProperties = data.getLoadedProperties();
- Object[] copyOfData = data.copyData();
-
- Object updateBean = updateRequest.getBean();
- Set updatedProperties = updateRequest.getUpdatedProperties();
-
- int naturalKeyUpdate = -1;
- boolean mergeProperties = false;
- BeanProperty[] props = desc.propertiesNonMany();
- for (int i = 0; i < props.length; i++) {
- if (updatedProperties.contains(props[i].getName())){
- if (props[i].isNaturalKey()){
- naturalKeyUpdate = i;
- }
- copyOfData[i] = props[i].getCacheDataValue(updateBean);
- if (loadedProperties != null && !mergeProperties && !loadedProperties.contains(props[i].getName())){
- mergeProperties = true;
- }
- }
- }
-
- if (mergeProperties){
- HashSet mergeProps = new HashSet();
- mergeProps.addAll(loadedProperties);
- mergeProps.addAll(updatedProperties);
- loadedProperties = mergeProps;
- }
-
- return new CachedBeanData(null, loadedProperties, copyOfData, naturalKeyUpdate);
+//
+// Set loadedProperties = data.getLoadedProperties();
+// Object[] copyOfData = data.copyData();
+//
+// Object updateBean = updateRequest.getBean();
+// Set updatedProperties = updateRequest.getUpdatedProperties();
+//
+// int naturalKeyUpdate = -1;
+// boolean mergeProperties = false;
+// BeanProperty[] props = desc.propertiesNonMany();
+// for (int i = 0; i < props.length; i++) {
+// if (updatedProperties.contains(props[i].getName())){
+// if (props[i].isNaturalKey()){
+// naturalKeyUpdate = i;
+// }
+// copyOfData[i] = props[i].getCacheDataValue(updateBean);
+// if (loadedProperties != null && !mergeProperties && !loadedProperties.contains(props[i].getName())){
+// mergeProperties = true;
+// }
+// }
+// }
+//
+// if (mergeProperties){
+// HashSet mergeProps = new HashSet();
+// mergeProps.addAll(loadedProperties);
+// mergeProps.addAll(updatedProperties);
+// loadedProperties = mergeProps;
+// }
+//
+// return new CachedBeanData(null, loadedProperties, copyOfData, naturalKeyUpdate);
+ return null;
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/BootupClasses.java b/src/main/java/com/avaje/ebeaninternal/server/core/BootupClasses.java
index c90022ab7..6bb53693f 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/BootupClasses.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/BootupClasses.java
@@ -325,10 +325,6 @@ public class BootupClasses implements ClassPathSearchMatcher {
} else if (isEntity(cls)) {
entityList.add(cls);
-
- } else if (isXmlBean(cls)){
- entityList.add(cls);
- //xmlBeanList.add(cls);
} else if (isInterestingInterface(cls)) {
return true;
@@ -420,17 +416,4 @@ public class BootupClasses implements ClassPathSearchMatcher {
return false;
}
- private boolean isXmlBean(Class> cls) {
-
- Annotation ann = cls.getAnnotation(XmlRootElement.class);
- if (ann != null) {
- return true;
- }
- ann = cls.getAnnotation(XmlType.class);
- if (ann != null) {
- // Only looking for Beans and not Enums
- return !cls.isEnum();
- }
- return false;
- }
}
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 0bd05ca18..67409388c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
@@ -78,7 +78,7 @@ public class DefaultBeanLoader {
return requestedBatchSize;
}
- public void refreshMany(Object parentBean, String propertyName) {
+ public void refreshMany(EntityBean parentBean, String propertyName) {
refreshMany(parentBean, propertyName, null);
}
@@ -97,7 +97,7 @@ public class DefaultBeanLoader {
for (int i = 0; i < batch.size(); i++) {
BeanCollection> bc = batch.get(i);
- Object ownerBean = bc.getOwnerBean();
+ EntityBean ownerBean = bc.getOwnerBean();
Object id = many.getParentId(ownerBean);
idList.add(id);
}
@@ -156,7 +156,7 @@ public class DefaultBeanLoader {
public void loadMany(BeanCollection> bc, LoadManyContext ctx, boolean onlyIds) {
- Object parentBean = bc.getOwnerBean();
+ EntityBean parentBean = bc.getOwnerBean();
String propertyName = bc.getPropertyName();
ObjectGraphNode node = ctx == null ? null : ctx.getObjectGraphNode();
@@ -164,11 +164,11 @@ public class DefaultBeanLoader {
loadManyInternal(parentBean, propertyName, null, false, node, onlyIds);
}
- public void refreshMany(Object parentBean, String propertyName, Transaction t) {
+ public void refreshMany(EntityBean parentBean, String propertyName, Transaction t) {
loadManyInternal(parentBean, propertyName, t, true, null, false);
}
- private void loadManyInternal(Object 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 = null;
PersistenceContext pc = null;
@@ -282,7 +282,7 @@ public class DefaultBeanLoader {
for (int i = 0; i < batch.size(); i++) {
EntityBeanIntercept ebi = batch.get(i);
- Object bean = ebi.getOwner();
+ EntityBean bean = ebi.getOwner();
Object id = desc.getId(bean);
idList.add(id);
}
@@ -305,17 +305,6 @@ public class DefaultBeanLoader {
PersistenceContext persistenceContext = ctx.getPersistenceContext();
- // query the database
- for (int i = 0; i < ebis.length; i++) {
- Object parentBean = ebis[i].getParentBean();
- if (parentBean != null) {
- // Special case for OneToOne
- BeanDescriptor> parentDesc = server.getBeanDescriptor(parentBean.getClass());
- Object parentId = parentDesc.getId(parentBean);
- persistenceContext.put(parentId, parentBean);
- }
- }
-
SpiQuery> query = (SpiQuery>) server.createQuery(beanType);
query.setMode(Mode.LAZYLOAD_BEAN);
@@ -338,7 +327,7 @@ public class DefaultBeanLoader {
if (loadRequest.isLoadCache()) {
for (int i = 0; i < list.size(); i++) {
- desc.cachePutBeanData(list.get(i));
+ desc.cachePutBeanData((EntityBean)list.get(i));
}
}
@@ -352,7 +341,7 @@ public class DefaultBeanLoader {
}
- public void refresh(Object bean) {
+ public void refresh(EntityBean bean) {
refreshBeanInternal(bean, SpiQuery.Mode.REFRESH_BEAN);
}
@@ -360,7 +349,7 @@ public class DefaultBeanLoader {
refreshBeanInternal(ebi.getOwner(), SpiQuery.Mode.LAZYLOAD_BEAN);
}
- private void refreshBeanInternal(Object bean, SpiQuery.Mode mode) {
+ private void refreshBeanInternal(EntityBean bean, SpiQuery.Mode mode) {
EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();;
@@ -381,7 +370,7 @@ public class DefaultBeanLoader {
if (ebi != null) {
if (SpiQuery.Mode.LAZYLOAD_BEAN.equals(mode) && desc.isBeanCaching()) {
// lazy loading and the bean cache is active
- if (desc.loadFromCache(bean, ebi, id)) {
+ if (desc.loadFromCache((EntityBean)bean, ebi, id)) {
return;
}
}
@@ -392,15 +381,8 @@ public class DefaultBeanLoader {
SpiQuery> query = (SpiQuery>) server.createQuery(desc.getBeanType());
if (ebi != null) {
- Object parentBean = ebi.getParentBean();
- if (parentBean != null) {
- // Special case for OneToOne
- BeanDescriptor> parentDesc = server.getBeanDescriptor(parentBean.getClass());
- Object parentId = parentDesc.getId(parentBean);
- pc.putIfAbsent(parentId, parentBean);
- }
-
- query.setLazyLoadProperty(ebi.getLazyLoadProperty());
+ int propIndex = ebi.getLazyLoadProperty();
+ query.setLazyLoadProperty(ebi.getProperty(propIndex));
}
// don't collect autoFetch usage profiling information
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java
index b0980925d..cfea34803 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java
@@ -1,7 +1,6 @@
package com.avaje.ebeaninternal.server.core;
import java.beans.PropertyChangeListener;
-import java.util.Collections;
import java.util.Set;
import com.avaje.ebean.BeanState;
@@ -39,14 +38,12 @@ public class DefaultBeanState implements BeanState {
}
public Set getLoadedProps() {
- Set props = intercept.getLoadedProps();
- return props == null ? null : Collections.unmodifiableSet(props);
+ return intercept.getLoadedPropertyNames();
}
public Set getChangedProps() {
- Set props = intercept.getChangedProps();
- return props == null ? null : Collections.unmodifiableSet(props);
- }
+ return intercept.getChangedPropertyNames();
+ }
public boolean isReadOnly() {
return intercept.isReadOnly();
@@ -64,9 +61,8 @@ public class DefaultBeanState implements BeanState {
entityBean.removePropertyChangeListener(listener);
}
- public void setLoaded(Set loadedProperties) {
- intercept.setLoadedProps(loadedProperties);
- intercept.setLoaded();
+ public void setLoaded() {
+ intercept.setLoaded();
}
public void setReference() {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
index 5c85680ae..e1b1696a2 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
@@ -115,6 +115,10 @@ public final class DefaultServer implements SpiEbeanServer {
private static final Logger logger = LoggerFactory.getLogger(DefaultServer.class);
+ private static final int IGNORE_LEADING_ELEMENTS = 5;
+
+ private static final String AVAJE_EBEAN = Ebean.class.getName().substring(0, 15);
+
private final String serverName;
private final DatabasePlatform databasePlatform;
@@ -486,12 +490,12 @@ public final class DefaultServer implements SpiEbeanServer {
public void refreshMany(Object parentBean, String propertyName, Transaction t) {
- beanLoader.refreshMany(parentBean, propertyName, t);
+ beanLoader.refreshMany(checkEntityBean(parentBean), propertyName, t);
}
public void refreshMany(Object parentBean, String propertyName) {
- beanLoader.refreshMany(parentBean, propertyName);
+ beanLoader.refreshMany(checkEntityBean(parentBean), propertyName);
}
public void loadMany(LoadManyRequest loadRequest) {
@@ -506,7 +510,7 @@ public final class DefaultServer implements SpiEbeanServer {
public void refresh(Object bean) {
- beanLoader.refresh(bean);
+ beanLoader.refresh(checkEntityBean(bean));
}
public void loadBean(LoadBeanRequest loadRequest) {
@@ -638,7 +642,7 @@ public final class DefaultServer implements SpiEbeanServer {
} else {
// use the default reference options
- ref = desc.createReference(null, id, null);
+ ref = desc.createReference(null, id);
}
if (ctx != null && (ref instanceof EntityBean)) {
@@ -1565,10 +1569,8 @@ public final class DefaultServer implements SpiEbeanServer {
* Save the bean with an explicit transaction.
*/
public void save(Object bean, Transaction t) {
- if (bean == null) {
- throw new NullPointerException(Message.msg("bean.isnull"));
- }
- persister.save(bean, t);
+
+ persister.save(checkEntityBean(bean), t);
}
/**
@@ -1606,10 +1608,8 @@ public final class DefaultServer implements SpiEbeanServer {
* include in the update.
*/
public void update(Object bean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties) {
- if (bean == null) {
- throw new NullPointerException(Message.msg("bean.isnull"));
- }
- persister.forceUpdate(bean, updateProps, t, deleteMissingChildren, updateNullProperties);
+
+ persister.forceUpdate(checkEntityBean(bean), updateProps, t, deleteMissingChildren, updateNullProperties);
}
/**
@@ -1635,12 +1635,19 @@ public final class DefaultServer implements SpiEbeanServer {
*
*/
public void insert(Object bean, Transaction t) {
+ persister.forceInsert(checkEntityBean(bean), t);
+ }
+
+ private EntityBean checkEntityBean(Object bean) {
if (bean == null) {
throw new NullPointerException(Message.msg("bean.isnull"));
}
- persister.forceInsert(bean, t);
+ if (bean instanceof EntityBean == false) {
+ throw new IllegalArgumentException("Was expecting an EntityBean but got a "+bean.getClass());
+ }
+ return (EntityBean)bean;
}
-
+
/**
* Delete the associations (from the intersection table) of a ManyToMany given
* the owner bean and the propertyName of the ManyToMany collection.
@@ -1661,10 +1668,11 @@ public final class DefaultServer implements SpiEbeanServer {
*/
public int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t) {
+ EntityBean owner = checkEntityBean(ownerBean);
TransWrapper wrap = initTransIfRequired(t);
try {
SpiTransaction trans = wrap.transaction;
- int rc = persister.deleteManyToManyAssociations(ownerBean, propertyName, trans);
+ int rc = persister.deleteManyToManyAssociations(owner, propertyName, trans);
wrap.commitIfCreated();
return rc;
@@ -1688,11 +1696,12 @@ public final class DefaultServer implements SpiEbeanServer {
*/
public void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t) {
+ EntityBean owner = checkEntityBean(ownerBean);
TransWrapper wrap = initTransIfRequired(t);
try {
SpiTransaction trans = wrap.transaction;
- persister.saveManyToManyAssociations(ownerBean, propertyName, trans);
+ persister.saveManyToManyAssociations(owner, propertyName, trans);
wrap.commitIfCreated();
@@ -1708,21 +1717,12 @@ public final class DefaultServer implements SpiEbeanServer {
public void saveAssociation(Object ownerBean, String propertyName, Transaction t) {
- if (ownerBean instanceof EntityBean) {
- Set loadedProps = ((EntityBean) ownerBean)._ebean_getIntercept().getLoadedProps();
- if (loadedProps != null && !loadedProps.contains(propertyName)) {
- // skip as property is not actually loaded in this partially
- // loaded bean
- logger.debug("Skip saveAssociation as property " + propertyName + " is not loaded");
- return;
- }
- }
-
+ EntityBean owner = checkEntityBean(ownerBean);
+
TransWrapper wrap = initTransIfRequired(t);
try {
SpiTransaction trans = wrap.transaction;
-
- persister.saveAssociation(ownerBean, propertyName, trans);
+ persister.saveAssociation(owner, propertyName, trans);
wrap.commitIfCreated();
@@ -1758,7 +1758,7 @@ public final class DefaultServer implements SpiEbeanServer {
SpiTransaction trans = wrap.transaction;
int saveCount = 0;
while (it.hasNext()) {
- Object bean = it.next();
+ EntityBean bean = checkEntityBean(it.next());
persister.save(bean, trans);
saveCount++;
}
@@ -1822,10 +1822,8 @@ public final class DefaultServer implements SpiEbeanServer {
* Delete the bean with the explicit transaction.
*/
public void delete(Object bean, Transaction t) {
- if (bean == null) {
- throw new NullPointerException(Message.msg("bean.isnull"));
- }
- persister.delete(bean, t);
+
+ persister.delete(checkEntityBean(bean), t);
}
/**
@@ -1853,7 +1851,7 @@ public final class DefaultServer implements SpiEbeanServer {
SpiTransaction trans = wrap.transaction;
int deleteCount = 0;
while (it.hasNext()) {
- Object bean = it.next();
+ EntityBean bean = checkEntityBean(it.next());
persister.delete(bean, trans);
deleteCount++;
}
@@ -1949,13 +1947,14 @@ public final class DefaultServer implements SpiEbeanServer {
}
public Object getBeanId(Object bean) {
+ EntityBean eb = checkEntityBean(bean);
BeanDescriptor> desc = getBeanDescriptor(bean.getClass());
if (desc == null) {
String m = bean.getClass().getName() + " is NOT an Entity Bean registered with this server?";
throw new PersistenceException(m);
}
- return desc.getId(bean);
+ return desc.getId(eb);
}
/**
@@ -2021,8 +2020,6 @@ public final class DefaultServer implements SpiEbeanServer {
return transactionManager.createQueryTransaction();
}
- private static final int IGNORE_LEADING_ELEMENTS = 5;
- private static final String AVAJE_EBEAN = Ebean.class.getName().substring(0, 15);
/**
* Create a CallStack object.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DiffHelp.java b/src/main/java/com/avaje/ebeaninternal/server/core/DiffHelp.java
index 90d586a05..7dbb1721f 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DiffHelp.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DiffHelp.java
@@ -37,30 +37,30 @@ public class DiffHelp {
// get the old values from a
if (a instanceof EntityBean) {
EntityBean eb = (EntityBean) a;
- b = eb._ebean_getIntercept().getOldValues();
+ b = null;//FIXME eb._ebean_getIntercept().getOldValues();
oldValues = true;
}
}
Map map = new LinkedHashMap();
- if (b == null) {
- return map;
- }
-
- // check the simple properties
- BeanProperty[] base = desc.propertiesBaseScalar();
- for (int i = 0; i < base.length; i++) {
-
- Object aval = base[i].getValue(a);
- Object bval = base[i].getValue(b);
- if (!ValueUtil.areEqual(aval, bval)) {
- map.put(base[i].getName(), new ValuePair(aval, bval));
- }
- }
-
- diffAssocOne(a, b, desc, map);
- diffEmbedded(a, b, desc, map, oldValues);
+// if (b == null) {
+// return map;
+// }
+//
+// // check the simple properties
+// BeanProperty[] base = desc.propertiesBaseScalar();
+// for (int i = 0; i < base.length; i++) {
+//
+// Object aval = base[i].getValue(a);
+// Object bval = base[i].getValue(b);
+// if (!ValueUtil.areEqual(aval, bval)) {
+// map.put(base[i].getName(), new ValuePair(aval, bval));
+// }
+// }
+//
+// diffAssocOne(a, b, desc, map);
+// diffEmbedded(a, b, desc, map, oldValues);
return map;
}
@@ -75,40 +75,40 @@ public class DiffHelp {
private void diffEmbedded(Object a, Object b, BeanDescriptor> desc, Map map,
boolean oldValues) {
- BeanPropertyAssocOne>[] emb = desc.propertiesEmbedded();
-
- for (int i = 0; i < emb.length; i++) {
- Object aval = emb[i].getValue(a);
- Object bval = emb[i].getValue(b);
- if (oldValues) {
- bval = ((EntityBean) bval)._ebean_getIntercept().getOldValues();
- if (bval == null) {
- continue;
- }
- }
-
- if (!isBothNull(aval, bval)) {
- if (isDiffNull(aval, bval)) {
- // one of the embedded beans is null
- map.put(emb[i].getName(), new ValuePair(aval, bval));
-
- } else {
- // if ANY of the properties in an Embedded bean is
- // different, treat the whole bean as being different
- BeanProperty[] props = emb[i].getProperties();
- for (int j = 0; j < props.length; j++) {
- Object aEmbPropVal = props[j].getValue(aval);
- Object bEmbPropVal = props[j].getValue(bval);
- if (!ValueUtil.areEqual(aEmbPropVal, bEmbPropVal)) {
-
- // if one prop is different put the
- // embedded bean in the map
- map.put(emb[i].getName(), new ValuePair(aval, bval));
- }
- }
- }
- }
- }
+// BeanPropertyAssocOne>[] emb = desc.propertiesEmbedded();
+//
+// for (int i = 0; i < emb.length; i++) {
+// Object aval = emb[i].getValue(a);
+// Object bval = emb[i].getValue(b);
+// if (oldValues) {
+// bval = null;//FIXME ((EntityBean) bval)._ebean_getIntercept().getOldValues();
+// if (bval == null) {
+// continue;
+// }
+// }
+//
+// if (!isBothNull(aval, bval)) {
+// if (isDiffNull(aval, bval)) {
+// // one of the embedded beans is null
+// map.put(emb[i].getName(), new ValuePair(aval, bval));
+//
+// } else {
+// // if ANY of the properties in an Embedded bean is
+// // different, treat the whole bean as being different
+// BeanProperty[] props = emb[i].getProperties();
+// for (int j = 0; j < props.length; j++) {
+// Object aEmbPropVal = props[j].getValue(aval);
+// Object bEmbPropVal = props[j].getValue(bval);
+// if (!ValueUtil.areEqual(aEmbPropVal, bEmbPropVal)) {
+//
+// // if one prop is different put the
+// // embedded bean in the map
+// map.put(emb[i].getName(), new ValuePair(aval, bval));
+// }
+// }
+// }
+// }
+// }
}
/**
@@ -119,29 +119,29 @@ public class DiffHelp {
BeanPropertyAssocOne>[] ones = desc.propertiesOne();
- for (int i = 0; i < ones.length; i++) {
- Object aval = ones[i].getValue(a);
- Object bval = ones[i].getValue(b);
-
- if (!isBothNull(aval, bval)) {
- if (isDiffNull(aval, bval)) {
- // one of them is/was null
- map.put(ones[i].getName(), new ValuePair(aval, bval));
-
- } else {
- // check to see if the Id properties
- // are different
- BeanDescriptor> oneDesc = ones[i].getTargetDescriptor();
- Object aOneId = oneDesc.getId(aval);
- Object bOneId = oneDesc.getId(bval);
-
- if (!ValueUtil.areEqual(aOneId, bOneId)) {
- // the ids are different
- map.put(ones[i].getName(), new ValuePair(aval, bval));
- }
- }
- }
- }
+// for (int i = 0; i < ones.length; i++) {
+// Object aval = ones[i].getValue(a);
+// Object bval = ones[i].getValue(b);
+//
+// if (!isBothNull(aval, bval)) {
+// if (isDiffNull(aval, bval)) {
+// // one of them is/was null
+// map.put(ones[i].getName(), new ValuePair(aval, bval));
+//
+// } else {
+// // check to see if the Id properties
+// // are different
+// BeanDescriptor> oneDesc = ones[i].getTargetDescriptor();
+// Object aOneId = oneDesc.getId(aval);
+// Object bOneId = oneDesc.getId(bval);
+//
+// if (!ValueUtil.areEqual(aOneId, bOneId)) {
+// // the ids are different
+// map.put(ones[i].getName(), new ValuePair(aval, bval));
+// }
+// }
+// }
+// }
}
private boolean isBothNull(Object aval, Object bval) {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
index b50c3610d..1cf2a0fdd 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
@@ -365,8 +365,7 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe
cacheKey = Integer.valueOf(31 * query.queryHash() + query.getType().hashCode());
}
- // TODO: Sort out returning BeanCollection from L2 cache
- return null;
+ return beanDescriptor.queryCacheGet(cacheKey);
}
public void putToQueryCache(BeanCollection queryResult) {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java
index 51f20722f..31a7983fd 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java
@@ -32,6 +32,10 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
this.persistExecute = persistExecute;
}
+ public void setNotNullAsLoaded() {
+ // Do nothing by default
+ }
+
/**
* Execute a the request or queue/batch it for later execution.
*/
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
index 50101b5c6..f79ea9e3c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.core;
import java.sql.SQLException;
import java.util.List;
-import java.util.Set;
import javax.persistence.OptimisticLockException;
@@ -41,6 +40,13 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*/
protected final BeanPersistController controller;
+ /**
+ * The bean being persisted.
+ */
+ protected final T bean;
+
+ protected final EntityBean entityBean;
+
/**
* The associated intercept.
*/
@@ -53,23 +59,8 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
protected final boolean isDirty;
- /**
- * The bean being persisted.
- */
- protected final T bean;
-
- /**
- * Old values used for concurrency checking.
- */
- protected T oldValues;
-
- /**
- * The concurrency mode used for update or delete.
- */
protected ConcurrencyMode concurrencyMode;
- protected final Set loadedProps;
-
/**
* The unique id used for logging summary.
*/
@@ -80,48 +71,18 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*/
protected Integer beanHash;
protected Integer beanIdentityHash;
-
- protected final Set changedProps;
-
protected boolean notifyCache;
private boolean statelessUpdate;
private boolean deleteMissingChildren;
private boolean updateNullProperties;
- /**
- * Used for forced update of a bean.
- */
- public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager mgr, SpiTransaction t,
- PersistExecute persistExecute, Set updateProps, ConcurrencyMode concurrencyMode) {
-
- super(server, t, persistExecute);
- this.beanManager = mgr;
- this.beanDescriptor = mgr.getBeanDescriptor();
- this.beanPersistListener = beanDescriptor.getPersistListener();
- this.bean = bean;
- this.parentBean = parentBean;
-
- this.controller = beanDescriptor.getPersistController();
- this.concurrencyMode = beanDescriptor.getConcurrencyMode();
-
- this.concurrencyMode = concurrencyMode;
- this.loadedProps = updateProps;
- this.changedProps = updateProps;
- this.isDirty = true;
- this.oldValues = bean;
- if (bean instanceof EntityBean) {
- this.intercept = ((EntityBean) bean)._ebean_getIntercept();
- } else {
- this.intercept = null;
- }
- }
-
- @SuppressWarnings("unchecked")
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager mgr,
SpiTransaction t, PersistExecute persistExecute) {
super(server, t, persistExecute);
+ this.entityBean = (EntityBean)bean;
+ this.intercept = entityBean._ebean_getIntercept();
this.beanManager = mgr;
this.beanDescriptor = mgr.getBeanDescriptor();
this.beanPersistListener = beanDescriptor.getPersistListener();
@@ -130,38 +91,24 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
this.controller = beanDescriptor.getPersistController();
this.concurrencyMode = beanDescriptor.getConcurrencyMode();
- this.intercept = ((EntityBean) bean)._ebean_getIntercept();
if (intercept.isReference()) {
- // allowed to delete reference objects
- // with no concurrency checking
+ // delete reference objects with no concurrency checking
this.concurrencyMode = ConcurrencyMode.NONE;
}
// this is ok to not use isNewOrDirty() as used for updates only
this.isDirty = intercept.isDirty();
- if (!isDirty) {
- this.changedProps = intercept.getChangedProps();
- } else {
- // merge changed properties on the bean with changed embedded beans
- Set beanChangedProps = intercept.getChangedProps();
- Set dirtyEmbedded = beanDescriptor.getDirtyEmbeddedProperties(bean);
- this.changedProps = mergeChangedProperties(beanChangedProps, dirtyEmbedded);
- }
- this.loadedProps = intercept.getLoadedProps();
- this.oldValues = (T) intercept.getOldValues();
}
-
- /**
- * Merge the changed properties for the bean and embedded beans.
- */
- private Set mergeChangedProperties(Set beanChangedProps, Set embChanged) {
- if (embChanged == null) {
- return beanChangedProps;
- } else if (beanChangedProps == null) {
- return embChanged;
- } else {
- beanChangedProps.addAll(embChanged);
- return beanChangedProps;
- }
+
+ public void setNotNullAsLoaded() {
+ BeanProperty[] props = beanDescriptor.propertiesNonMany();
+ for (int i=0; i< props.length; i++) {
+ BeanProperty prop = props[i];
+ if (!intercept.isLoadedProperty(prop.getPropertyIndex())) {
+ if (prop.getValue(entityBean) != null) {
+ intercept.setLoadedProperty(prop.getPropertyIndex());
+ }
+ }
+ }
}
public boolean isNotify(TransactionEvent txnEvent) {
@@ -176,26 +123,25 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return beanPersistListener != null;
}
- public void notifyCache() {
- if (notifyCache) {
- switch (type) {
- case INSERT:
- beanDescriptor.cacheInsert(idValue, this);
- break;
- case UPDATE:
- beanDescriptor.cacheUpdate(idValue, this);
- break;
- case DELETE:
- beanDescriptor.cacheDelete(idValue, this);
- break;
- default:
- throw new IllegalStateException("Invalid type "+type);
- }
- }
- }
+ public void notifyCache() {
+ if (notifyCache) {
+ switch (type) {
+ case INSERT:
+ beanDescriptor.cacheInsert(idValue, this);
+ break;
+ case UPDATE:
+ beanDescriptor.cacheUpdate(idValue, this);
+ break;
+ case DELETE:
+ beanDescriptor.cacheDelete(idValue, this);
+ break;
+ default:
+ throw new IllegalStateException("Invalid type " + type);
+ }
+ }
+ }
public void addToPersistMap(BeanPersistIdMap beanPersistMap) {
-
beanPersistMap.add(beanDescriptor, type, idValue);
}
@@ -209,7 +155,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return beanPersistListener.inserted(bean);
case UPDATE:
- return beanPersistListener.updated(bean, getUpdatedProperties());
+ return beanPersistListener.updated(bean);//, getUpdatedProperties());
case DELETE:
return beanPersistListener.deleted(bean);
@@ -226,7 +172,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
/**
* Return true if this bean has been already been persisted
- * (inserted/updated or deleted) in this transaction.
+ * (inserted or updated) in this transaction.
*/
public boolean isRegisteredBean() {
return transaction.isRegisteredBean(bean);
@@ -244,7 +190,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*/
private Integer getBeanHash() {
if (beanHash == null) {
- Object id = beanDescriptor.getId(bean);
+ Object id = beanDescriptor.getId(entityBean);
int hc = 31 * bean.getClass().getName().hashCode();
if (id != null) {
hc += id.hashCode();
@@ -281,11 +227,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
public void setType(Type type) {
this.type = type;
notifyCache = beanDescriptor.isCacheNotify();
- if (type == Type.DELETE || type == Type.UPDATE) {
- if (oldValues == null) {
- oldValues = bean;
- }
- }
}
public BeanManager getBeanManager() {
@@ -351,20 +292,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return concurrencyMode;
}
- /**
- * Set loaded properties when generated values has added properties such as
- * created and updated timestamps.
- */
- public void setLoadedProps(Set additionalProps) {
- if (intercept != null) {
- intercept.setLoadedProps(additionalProps);
- }
- }
-
- public Set getLoadedProperties() {
- return loadedProps;
- }
-
/**
* Returns a description of the request. This is typically the bean class
* name or the base table for MapBeans.
@@ -384,25 +311,22 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return bean;
}
- /**
+
+ public EntityBean getEntityBean() {
+ return entityBean;
+ }
+
+ /**
* Return the Id value for the bean.
*/
public Object getBeanId() {
- return beanDescriptor.getId(bean);
+ return beanDescriptor.getId(entityBean);
}
public BeanDelta createDeltaBean() {
return new BeanDelta(beanDescriptor, getBeanId());
}
- /**
- * Get the old values bean. This is used to perform optimistic concurrency
- * checking on updates and deletes.
- */
- public T getOldValues() {
- return oldValues;
- }
-
/**
* Return the parent bean for cascading save with unidirectional
* relationship.
@@ -431,11 +355,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
* bean).
*/
public boolean isLoadedProperty(BeanProperty prop) {
- if (loadedProps == null) {
- return true;
- } else {
- return loadedProps.contains(prop.getName());
- }
+ return intercept.isLoadedProperty(prop.getPropertyIndex());
}
@Override
@@ -482,13 +402,8 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*/
public void setGeneratedKey(Object idValue) {
if (idValue != null) {
-
- // set back to the bean so that we can use the same bean later
- // for update [refer ebeanIntercept.setLoaded(true)].
- idValue = beanDescriptor.convertSetId(idValue, bean);
-
// remember it for logging summary
- this.idValue = idValue;
+ this.idValue = beanDescriptor.convertSetId(idValue, entityBean);
}
}
@@ -586,18 +501,18 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*
*/
public ConcurrencyMode determineConcurrencyMode() {
- if (loadedProps != null) {
- // 'partial bean' update/delete...
- if (concurrencyMode.equals(ConcurrencyMode.VERSION)) {
- // check the version property was loaded
- BeanProperty prop = beanDescriptor.firstVersionProperty();
- if (prop != null && loadedProps.contains(prop.getName())) {
- // OK to use version property
- } else {
- concurrencyMode = ConcurrencyMode.ALL;
- }
+
+ // 'partial bean' update/delete...
+ if (concurrencyMode.equals(ConcurrencyMode.VERSION)) {
+ // check the version property was loaded
+ BeanProperty prop = beanDescriptor.getVersionProperty();
+ if (prop != null && intercept.isLoadedProperty(prop.getPropertyIndex())) {
+ // OK to use version property
+ } else {
+ concurrencyMode = ConcurrencyMode.NONE;//ALL;
}
}
+
return concurrencyMode;
}
@@ -608,7 +523,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*
*/
public boolean isDynamicUpdateSql() {
- return beanDescriptor.isUpdateChangesOnly() || (loadedProps != null);
+ return beanDescriptor.isUpdateChangesOnly() || !intercept.isFullyLoadedBean();//(loadedProps != null);
}
/**
@@ -619,37 +534,28 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*
*/
public GenerateDmlRequest createGenerateDmlRequest(boolean emptyStringAsNull) {
- if (beanDescriptor.isUpdateChangesOnly()) {
- return new GenerateDmlRequest(emptyStringAsNull, changedProps, loadedProps, oldValues);
- } else {
- return new GenerateDmlRequest(emptyStringAsNull, loadedProps, loadedProps, oldValues);
- }
- }
-
- /**
- * Return the updated properties. If this returns null then all the
- * properties on the bean where updated.
- */
- public Set getUpdatedProperties() {
- if (changedProps != null) {
- return changedProps;
- }
- return loadedProps;
+ return new GenerateDmlRequest(emptyStringAsNull, intercept, beanDescriptor.isUpdateChangesOnly());
}
/**
* Test if the property value has changed and if so include it in the
* update.
*/
- public boolean hasChanged(BeanProperty prop) {
- if (changedProps == null) {
- return false;
- }
- return changedProps.contains(prop.getName());
+ public boolean isAddToUpdate(BeanProperty prop) {
+ return intercept.isChangedProperty(prop.getPropertyIndex());
}
- public List getDerivedRelationships() {
- return transaction.getDerivedRelationship(bean);
+ public List getDerivedRelationships() {
+ return transaction.getDerivedRelationship(bean);
+ }
+
+ public void postInsert() {
+ // mark all properties as loaded after an insert
+ // to support immediate update
+ int len = intercept.getPropertyLength();
+ for (int i = 0; i < len; i++) {
+ intercept.setLoadedProperty(i);
}
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java b/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java
index 319a5fd73..268ddf8ec 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java
@@ -7,6 +7,7 @@ import com.avaje.ebean.CallableSql;
import com.avaje.ebean.SqlUpdate;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.Update;
+import com.avaje.ebean.bean.EntityBean;
/**
@@ -17,23 +18,23 @@ public interface Persister {
/**
* Force an Update using the given bean.
*/
- public void forceUpdate(Object entityBean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties);
+ public void forceUpdate(EntityBean entityBean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties);
/**
* Force an Insert using the given bean.
*/
- public void forceInsert(Object entityBean, Transaction t);
+ public void forceInsert(EntityBean entityBean, Transaction t);
/**
* Insert or update the bean depending on its state.
*/
- public void save(Object entityBean, Transaction t);
+ public void save(EntityBean entityBean, Transaction t);
/**
* Save the associations of a ManyToMany given the owner bean and the
* propertyName of the ManyToMany collection.
*/
- public void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
+ public void saveManyToManyAssociations(EntityBean ownerBean, String propertyName, Transaction t);
/**
* Save an association (OneToMany, ManyToOne, OneToOne or ManyToMany).
@@ -45,12 +46,12 @@ public interface Persister {
* @param t
* the transaction to use.
*/
- public void saveAssociation(Object parentBean, String propertyName, Transaction t);
+ public void saveAssociation(EntityBean parentBean, String propertyName, Transaction t);
/**
* Delete the associations of a ManyToMany given the owner bean and the property name of the ManyToMany.
*/
- public int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
+ public int deleteManyToManyAssociations(EntityBean ownerBean, String propertyName, Transaction t);
/**
* Delete a bean given it's type and id value.
@@ -63,7 +64,7 @@ public interface Persister {
/**
* Delete the bean.
*/
- public void delete(Object entityBean, Transaction t);
+ public void delete(EntityBean entityBean, Transaction t);
/**
* Delete multiple beans given a collection of Id values.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanCollectionHelp.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanCollectionHelp.java
index 061624e23..711d1496c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanCollectionHelp.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanCollectionHelp.java
@@ -8,6 +8,7 @@ import com.avaje.ebean.Transaction;
import com.avaje.ebean.bean.BeanCollection;
import com.avaje.ebean.bean.BeanCollectionAdd;
import com.avaje.ebean.bean.BeanCollectionLoader;
+import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
/**
@@ -41,22 +42,22 @@ public interface BeanCollectionHelp {
/**
* Add a bean to the List Set or Map.
*/
- public void add(BeanCollection> collection, Object bean);
+ public void add(BeanCollection> collection, EntityBean bean);
/**
* Create a lazy loading proxy for a List Set or Map.
*/
- public BeanCollection createReference(Object parentBean, String propertyName);
+ public BeanCollection createReference(EntityBean parentBean, String propertyName);
/**
* Refresh the List Set or Map.
*/
- public void refresh(EbeanServer server, Query> query, Transaction t, Object parentBean);
+ public void refresh(EbeanServer server, Query> query, Transaction t, EntityBean parentBean);
/**
* Apply the new refreshed BeanCollection to the appropriate property of the parent bean.
*/
- public void refresh(BeanCollection> bc, Object parentBean);
+ public void refresh(BeanCollection> bc, EntityBean parentBean);
/**
* Write the collection out as json.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
index f3e1b3feb..352922fe9 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
@@ -92,7 +92,7 @@ public class BeanDescriptor {
private final ConcurrentHashMap fkeyMap = new ConcurrentHashMap();
public enum EntityType {
- ORM, EMBEDDED, SQL, META, XMLELEMENT
+ ORM, EMBEDDED, SQL, META
}
/**
@@ -175,14 +175,11 @@ public class BeanDescriptor {
* This is not sent to a remote client.
*/
private final BeanDescriptorMap owner;
-
- /**
- * The EntityBean type used to create new EntityBeans.
- */
- private final Class> factoryType;
-
- private final boolean enhancedBean;
-
+
+ private final String[] properties;
+
+ private final int propertyCount;
+
/**
* Intercept pre post on insert,update,delete and postLoad(). Server side
* only.
@@ -219,7 +216,7 @@ public class BeanDescriptor {
/**
* Derived list of properties that are used for version concurrency checking.
*/
- private final BeanProperty[] propertiesVersion;
+ private final BeanProperty versionProperty;
private final BeanProperty propertiesNaturalKey;
/**
@@ -280,12 +277,6 @@ public class BeanDescriptor {
*/
final BeanProperty[] propertiesNonTransient;
- /**
- * Set to true if the bean has version properties or an embedded bean has
- * version properties.
- */
- private final BeanProperty propertyFirstVersion;
-
/**
* Set when the Id property is a single non-embedded property. Can make life
* simpler for this case.
@@ -362,6 +353,8 @@ public class BeanDescriptor {
this.cacheManager = owner.getCacheManager();
this.serverName = owner.getServerName();
this.entityType = deploy.getEntityType();
+ this.properties = deploy.getProperties();
+ this.propertyCount = this.properties.length;
this.name = InternString.intern(deploy.getName());
this.baseTableAlias = "t0";
this.fullName = InternString.intern(deploy.getFullName());
@@ -370,8 +363,6 @@ public class BeanDescriptor {
this.useIndex = deploy.getUseIndex();
this.typeManager = typeManager;
this.beanType = deploy.getBeanType();
- this.factoryType = deploy.getFactoryType();
- this.enhancedBean = beanType.equals(factoryType);
this.namedQueries = deploy.getNamedQueries();
this.namedUpdates = deploy.getNamedUpdates();
@@ -417,7 +408,7 @@ public class BeanDescriptor {
this.propertiesBaseCompound = listHelper.getBaseCompound();
this.propertiesId = listHelper.getId();
this.propertiesNaturalKey = listHelper.getNaturalKey();
- this.propertiesVersion = listHelper.getVersion();
+ this.versionProperty = listHelper.getVersionProperty();
this.propertiesEmbedded = listHelper.getEmbedded();
this.propertiesLocal = listHelper.getLocal();
this.unidirectional = listHelper.getUnidirectional();
@@ -441,7 +432,6 @@ public class BeanDescriptor {
this.namesOfManyPropsHash = namesOfManyProps.hashCode();
this.derivedTableJoins = listHelper.getTableJoin();
- this.propertyFirstVersion = listHelper.getFirstVersion();
if (propertiesId.length == 1) {
this.propertySingleId = propertiesId[0];
@@ -492,19 +482,19 @@ public class BeanDescriptor {
* Determine the concurrency mode based on the existence of a non-null version
* property value.
*/
- public ConcurrencyMode determineConcurrencyMode(Object bean) {
+ public ConcurrencyMode determineConcurrencyMode(EntityBean bean) {
- if (propertyFirstVersion == null) {
+ if (versionProperty == null) {
return ConcurrencyMode.NONE;
}
- Object v = propertyFirstVersion.getValue(bean);
+ Object v = versionProperty.getValue(bean);
return (v == null) ? ConcurrencyMode.NONE : ConcurrencyMode.VERSION;
}
/**
* Return the Set of embedded beans that have changed.
*/
- public Set getDirtyEmbeddedProperties(Object bean) {
+ public Set getDirtyEmbeddedProperties(EntityBean bean) {
HashSet dirtyProperties = null;
@@ -533,7 +523,7 @@ public class BeanDescriptor {
/**
* Determine the non-null properties of the bean.
*/
- public Set determineLoadedProperties(Object bean) {
+ public Set determineLoadedProperties(EntityBean bean) {
HashSet nonNullProps = new HashSet();
@@ -564,6 +554,14 @@ public class BeanDescriptor {
return entityType;
}
+ public int getPropertyCount() {
+ return propertyCount;
+ }
+
+ public String[] getProperties() {
+ return properties;
+ }
+
/**
* Return the default strategy for using a lucene index (if an index is
* defined on this bean type).
@@ -672,10 +670,6 @@ public class BeanDescriptor {
return inheritInfo != null;
}
- protected boolean isDynamicSubclass() {
- return !beanType.equals(factoryType);
- }
-
public SqlUpdate deleteById(Object id, List