- * You can create a new EntityBean (
- * {@link EbeanServer#createEntityBean(Class)}, set its Id property and then
- * call this setReference() method.
- *
- */
- public void setReference();
-
/**
* Advanced - Used to programmatically build a partially or fully loaded
* entity bean. First create an entity bean via
diff --git a/src/main/java/com/avaje/ebean/Ebean.java b/src/main/java/com/avaje/ebean/Ebean.java
index b8f6a86f5..e24f760bf 100644
--- a/src/main/java/com/avaje/ebean/Ebean.java
+++ b/src/main/java/com/avaje/ebean/Ebean.java
@@ -453,6 +453,14 @@ public final class Ebean {
serverMgr.getPrimaryServer().save(bean);
}
+ /**
+ * Insert the bean. This is useful when you set the Id property on a bean and
+ * want to explicitly insert it.
+ */
+ public static void insert(Object bean) {
+ serverMgr.getPrimaryServer().insert(bean);
+ }
+
/**
* Force an update using the bean updating the non-null properties.
*
@@ -496,29 +504,6 @@ public final class Ebean {
serverMgr.getPrimaryServer().update(bean);
}
- /**
- * Force an update using the bean explicitly stating the properties to update.
- *
- * If you don't specify explicit properties to use in the update then the
- * non-null properties are included in the update.
- *
- *
- * For updates against beans that have not been fetched (say built from JSON
- * or XML) this will treat deleteMissingChildren=true and will delete any
- * 'missing children'. Refer to
- * {@link EbeanServer#update(Object, Set, Transaction, boolean, boolean)}.
- *
- *
- * @param bean
- * The bean holding the values to be included in the update.
- * @param updateProps
- * the explicit set of properties to include in the update (can be
- * null).
- */
- public static void update(Object bean, Set updateProps) {
- serverMgr.getPrimaryServer().update(bean, updateProps);
- }
-
/**
* Save all the beans from an Iterator.
*/
diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java
index e6567b8bb..b2fb352f4 100644
--- a/src/main/java/com/avaje/ebean/EbeanServer.java
+++ b/src/main/java/com/avaje/ebean/EbeanServer.java
@@ -856,71 +856,6 @@ public interface EbeanServer {
*/
public void update(Object bean, Transaction t);
- /**
- * Force an update using the bean explicitly stating the properties to update.
- *
- * You can use this method to FORCE an update to occur (even on a bean that
- * has not been fetched but say built from JSON or XML). When
- * {@link EbeanServer#save(Object)} is used Ebean determines whether to use an
- * insert or an update based on the state of the bean. Using this method will
- * force an update to occur.
- *
- *
- * It is expected that this method is most useful in stateless REST services
- * or web applications where you have the values you wish to update but no
- * existing bean.
- *
- *
- * For updates against beans that have not been fetched (say built from JSON
- * or XML) this will treat deleteMissingChildren=true and will delete any
- * 'missing children'. Refer to
- * {@link EbeanServer#update(Object, Set, Transaction, boolean, boolean)}.
- *
- *
- *
- *
- * Customer c = new Customer();
- * c.setId(7);
- * c.setName("ModifiedNameNoOCC");
- *
- * // generally you should set the version property
- * // so that Optimistic Concurrency Checking is used.
- * // If a version property is not set then no Optimistic
- * // Concurrency Checking occurs for the update
- * // c.setLastUpdate(lastUpdateTime);
- *
- * // by default the Non-null properties
- * // are included in the update
- * ebeanServer.update(c);
- *
- *
- */
- public void update(Object bean, Set updateProps);
-
- /**
- * Force an update of the specified properties of the bean with an explicit
- * transaction.
- *
- * You can use this method to FORCE an update to occur (even on a bean that
- * has not been fetched but say built from JSON or XML). When
- * {@link EbeanServer#save(Object)} is used Ebean determines whether to use an
- * insert or an update based on the state of the bean. Using this method will
- * force an update to occur.
- *
- *
- * It is expected that this method is most useful in stateless REST services
- * or web applications where you have the values you wish to update but no
- * existing bean.
- *
- *
- * For updates against beans that have not been fetched (say built from JSON
- * or XML) this will treat deleteMissingChildren=true and will delete any
- * 'missing children'. Refer to
- * {@link EbeanServer#update(Object, Set, Transaction, boolean, boolean)}.
- *
- */
- public void update(Object bean, Set updateProps, Transaction t);
-
/**
* Force an update additionally specifying whether to 'deleteMissingChildren'
* when the update cascades to a OneToMany or ManyToMany.
@@ -945,21 +880,14 @@ public interface EbeanServer {
*
* @param bean
* the bean to update
- * @param updateProps
- * optionally you can specify the properties to update (can be null).
* @param t
* optionally you can specify the transaction to use (can be null).
* @param deleteMissingChildren
* specify false if you do not want 'missing children' of a OneToMany
* or ManyToMany to be automatically deleted.
- * @param updateNullProperties
- * specify true if by default you want properties with null values to
- * be included in the update and false if those properties should be
- * treated as 'unloaded' and excluded from the update. This only
- * takes effect if the updateProps is null.
+
*/
- public void update(Object bean, Set updateProps, Transaction t,
- boolean deleteMissingChildren, boolean updateNullProperties);
+ public void update(Object bean, Transaction t, boolean deleteMissingChildren);
/**
* Force the bean to be saved with an explicit insert.
diff --git a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
index 7f5b0361e..b1e39d54e 100644
--- a/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
+++ b/src/main/java/com/avaje/ebean/bean/EntityBeanIntercept.java
@@ -263,6 +263,20 @@ public final class EntityBeanIntercept implements Serializable {
return isNew() || isDirty();
}
+ /**
+ * Return true if only the Id property has been loaded.
+ */
+ public boolean hasIdOnly(int idIndex) {
+ for (int i = 0; i < loadedProps.length; i++) {
+ if (i == idIndex) {
+ if (!loadedProps[i]) return false;
+ } else if (loadedProps[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Return true if the entity is a reference.
*/
@@ -273,8 +287,17 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Set this as a reference object.
*/
- public void setReference() {
+ public void setReference(int idPos) {
state = STATE_REFERENCE;
+ if (idPos > -1) {
+ // For cases where properties are set on constructor
+ // set every non Id property to unloaded (for lazy loading)
+ for (int i=0; i< loadedProps.length; i++) {
+ if (i != idPos) {
+ loadedProps[i] = false;
+ }
+ }
+ }
}
/**
@@ -330,16 +353,18 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
- * Mark this bean as having failed lazy loading due to the underlying row
- * being deleted.
+ * Check if the lazy load succeeded. If not then mark this bean as having
+ * failed lazy loading due to the underlying row being deleted.
*
* We mark the bean this way rather than immediately fail as we might be batch
* lazy loading and this bean might not be used by the client code at all.
* Instead we will fail as soon as the client code tries to use this bean.
*
*/
- public void setLazyLoadFailure() {
- this.lazyLoadFailure = true;
+ public void checkLazyLoadFailure() {
+ if (lazyLoadProperty != -1) {
+ this.lazyLoadFailure = true;
+ }
}
/**
@@ -490,9 +515,13 @@ public final class EntityBeanIntercept implements Serializable {
*/
public void setNewBeanForUpdate() {
+ if (changedProps == null) {
+ changedProps = new boolean[owner._ebean_getPropertyNames().length];
+ }
+
for (int i=0; i< loadedProps.length; i++) {
if (loadedProps[i]) {
- setChangedProperty(i);
+ changedProps[i] = true;
}
}
setDirty(true);
diff --git a/src/main/java/com/avaje/ebean/text/csv/CsvReader.java b/src/main/java/com/avaje/ebean/text/csv/CsvReader.java
index 2052648f2..d35adc00e 100644
--- a/src/main/java/com/avaje/ebean/text/csv/CsvReader.java
+++ b/src/main/java/com/avaje/ebean/text/csv/CsvReader.java
@@ -32,7 +32,6 @@ import com.avaje.ebean.text.StringParser;
* csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
* csvReader.addProperty("billingAddress.line1");
* csvReader.addProperty("billingAddress.city");
- * csvReader.addReference("billingAddress.country.code");
*
* csvReader.process(reader);
*
@@ -41,8 +40,6 @@ import com.avaje.ebean.text.StringParser;
* }
*
*
- * @author rbygrave
- *
* @param
* the entity bean type
*/
@@ -129,13 +126,6 @@ public interface CsvReader {
*/
public void addProperty(String propertyName);
- /**
- * Define the next property to be a reference. This effectively means it
- * represents a foreign key. For example, with an Address object a Country
- * Code could be a reference.
- */
- public void addReference(String propertyName);
-
/**
* Define the next property and use a custom StringParser to convert the
* string content into the appropriate type for the property.
diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java
index c148f2e51..b89fd5223 100644
--- a/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java
+++ b/src/main/java/com/avaje/ebeaninternal/api/SpiEbeanServer.java
@@ -38,11 +38,6 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
*/
public boolean isDefaultDeleteMissingChildren();
- /**
- * Return true if UpdateNullProperties defaults to true for stateless updates.
- */
- public boolean isDefaultUpdateNullProperties();
-
/**
* Return the DatabasePlatform for this server.
*/
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 370d79c33..67bc7cec9 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/cache/CachedBeanDataFromBean.java
@@ -56,10 +56,10 @@ public class CachedBeanDataFromBean {
// 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 idProp = desc.getIdProperty();
+ if (idProp != null) {
+ Object v = idProp.getValue(bean);
+ idProp.setValue(sharableBean, v);
}
BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
for (int i = 0; i < propertiesNonTransient.length; i++) {
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 a6c4348aa..514ab722c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanLoader.java
@@ -317,11 +317,9 @@ public class DefaultBeanLoader {
}
for (int i = 0; i < ebis.length; i++) {
- if (ebis[i].isReference()) {
- // The underlying row in DB was deleted. Mark this bean as 'failed'
- // but allow processing to continue until it is accessed by client code
- ebis[i].setLazyLoadFailure();
- }
+ // Check if the underlying row in DB was deleted. Mark this bean as 'failed' if
+ // necessary but allow processing to continue until it is accessed by client code
+ ebis[i].checkLazyLoadFailure();
}
}
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 6aeb1fa3c..cf409ca2c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultBeanState.java
@@ -70,9 +70,5 @@ public class DefaultBeanState implements BeanState {
public void setLoaded() {
intercept.setLoaded();
}
-
- public void setReference() {
- intercept.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 969d5db85..a8f2e4f37 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java
@@ -142,8 +142,8 @@ public final class DefaultServer implements SpiEbeanServer {
* false;
*/
private final boolean rollbackOnChecked;
+
private final boolean defaultDeleteMissingChildren;
- private final boolean defaultUpdateNullProperties;
/**
* Handles the save, delete, updateSql CallableSql.
@@ -251,8 +251,6 @@ public final class DefaultServer implements SpiEbeanServer {
this.collectQueryStatsByNode = serverConfig.isCollectQueryStatsByNode();
this.maxCallStack = GlobalProperties.getInt("ebean.maxCallStack", 5);
- this.defaultUpdateNullProperties = "true"
- .equalsIgnoreCase(config.getServerConfig().getProperty("defaultUpdateNullProperties", "false"));
this.defaultDeleteMissingChildren = "true".equalsIgnoreCase(config.getServerConfig()
.getProperty("defaultDeleteMissingChildren", "true"));
@@ -315,10 +313,6 @@ public final class DefaultServer implements SpiEbeanServer {
return defaultDeleteMissingChildren;
}
- public boolean isDefaultUpdateNullProperties() {
- return defaultUpdateNullProperties;
- }
-
public int getLazyLoadBatchSize() {
return lazyLoadBatchSize;
}
@@ -656,23 +650,15 @@ public final class DefaultServer implements SpiEbeanServer {
// we actually need to do a query because
// we don't know the type without the
// discriminator value
- BeanProperty[] idProps = desc.propertiesId();
- String idNames;
- switch (idProps.length) {
- case 0:
- throw new PersistenceException("No ID properties for this type? " + desc);
- case 1:
- idNames = idProps[0].getName();
- break;
- default:
- idNames = Arrays.toString(idProps);
- idNames = idNames.substring(1, idNames.length() - 1);
+ BeanProperty idProp = desc.getIdProperty();
+ if (idProp == null) {
+ throw new PersistenceException("No ID properties for this type? " + desc);
}
-
+
// just select the id properties and
// the discriminator column (auto added)
Query query = createQuery(type);
- query.select(idNames).setId(id);
+ query.select(idProp.getName()).setId(id);
ref = query.findUnique();
@@ -1616,39 +1602,24 @@ public final class DefaultServer implements SpiEbeanServer {
* Force an update using the bean updating non-null properties.
*/
public void update(Object bean) {
- update(bean, null, null);
+ update(bean, null);
}
/**
* Force an update using the bean explicitly stating which properties to
* include in the update.
*/
- public void update(Object bean, Set updateProps) {
- update(bean, updateProps, null);
- }
-
- /**
- * Force an update using the bean updating non-null properties.
- */
public void update(Object bean, Transaction t) {
- update(bean, null, t);
+ update(bean, t, defaultDeleteMissingChildren);
}
/**
* Force an update using the bean explicitly stating which properties to
* include in the update.
*/
- public void update(Object bean, Set updateProps, Transaction t) {
- update(bean, updateProps, t, defaultDeleteMissingChildren, defaultUpdateNullProperties);
- }
-
- /**
- * Force an update using the bean explicitly stating which properties to
- * include in the update.
- */
- public void update(Object bean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties) {
+ public void update(Object bean, Transaction t, boolean deleteMissingChildren) {
- persister.forceUpdate(checkEntityBean(bean), updateProps, t, deleteMissingChildren, updateNullProperties);
+ persister.forceUpdate(checkEntityBean(bean), t, deleteMissingChildren);
}
/**
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 e19fd8498..d5eeb86df 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java
@@ -258,12 +258,11 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe
public Map, ?> findMap() {
String mapKey = query.getMapKey();
if (mapKey == null) {
- BeanProperty[] ids = beanDescriptor.propertiesId();
- if (ids.length == 1) {
- query.setMapKey(ids[0].getName());
+ BeanProperty idProp = beanDescriptor.getIdProperty();
+ if (idProp != null) {
+ query.setMapKey(idProp.getName());
} else {
- String msg = "No mapKey specified for query";
- throw new PersistenceException(msg);
+ throw new PersistenceException("No mapKey specified for query");
}
}
return (Map, ?>) queryEngine.findMany(this);
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 31a7983fd..5ce5a750f 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequest.java
@@ -12,7 +12,7 @@ import com.avaje.ebeaninternal.server.persist.PersistExecute;
public abstract class PersistRequest extends BeanRequest implements BatchPostExecute {
public enum Type {
- INSERT, UPDATE, DELETE, ORMUPDATE, UPDATESQL, CALLABLESQL
+ DETERMINE, INSERT, UPDATE, DELETE, ORMUPDATE, UPDATESQL, CALLABLESQL
};
boolean persistCascade;
@@ -31,10 +31,6 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
super(server, t);
this.persistExecute = persistExecute;
}
-
- public void setNotNullAsLoaded() {
- // Do nothing by default
- }
/**
* Execute a the request or queue/batch it for later execution.
@@ -94,14 +90,6 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
return type;
}
- /**
- * Set the type of this request. One of INSERT, UPDATE, DELETE, UPDATESQL or
- * CALLABLESQL.
- */
- public void setType(Type type) {
- this.type = type;
- }
-
/**
* Return true if save and delete should cascade.
*/
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 12d54710f..1201bf44c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/PersistRequestBean.java
@@ -64,7 +64,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
protected ConcurrencyMode concurrencyMode;
-
/**
* The unique id used for logging summary.
*/
@@ -76,17 +75,15 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
protected Integer beanHash;
protected Integer beanIdentityHash;
-
protected boolean notifyCache;
private boolean statelessUpdate;
private boolean deleteMissingChildren;
- private boolean updateNullProperties;
private final Set dirtyPropertyNames;
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager mgr,
- SpiTransaction t, PersistExecute persistExecute) {
+ SpiTransaction t, PersistExecute persistExecute, PersistRequest.Type type) {
super(server, t, persistExecute);
this.entityBean = (EntityBean)bean;
@@ -94,21 +91,35 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
this.beanManager = mgr;
this.beanDescriptor = mgr.getBeanDescriptor();
this.beanPersistListener = beanDescriptor.getPersistListener();
- this.dirtyPropertyNames = (beanPersistListener == null) ? null : intercept.getDirtyPropertyNames();
+
+ if (PersistRequest.Type.DETERMINE != type) {
+ this.type = type;
+ } else {
+ this.type = beanDescriptor.isInsertMode(intercept) ? Type.INSERT : Type.UPDATE;
+ }
+
+ if (this.type == Type.UPDATE && intercept.isNew() ) {
+ intercept.setNewBeanForUpdate();
+ }
+
+ this.dirtyPropertyNames = (beanPersistListener == null) ? null : intercept.getDirtyPropertyNames();
this.bean = bean;
this.parentBean = parentBean;
this.controller = beanDescriptor.getPersistController();
- this.concurrencyMode = beanDescriptor.getConcurrencyMode();
- if (intercept.isReference()) {
- // delete reference objects with no concurrency checking
- this.concurrencyMode = ConcurrencyMode.NONE;
- }
+ this.concurrencyMode = beanDescriptor.getConcurrencyMode(intercept);
// this is ok to not use isNewOrDirty() as used for updates only
this.isDirty = intercept.isDirty();
}
-
+
+ /**
+ * Return true if this is an insert request.
+ */
+ public boolean isInsert() {
+ return Type.INSERT == type;
+ }
+
@Override
public Set getLoadedProperties() {
return intercept.getLoadedPropertyNames();
@@ -124,26 +135,11 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return intercept.getDirtyValues();
}
- 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) {
+ this.notifyCache = beanDescriptor.isCacheNotify();
return notifyCache || isNotifyPersistListener();
}
- public boolean isNotifyCache() {
- return notifyCache;
- }
-
public boolean isNotifyPersistListener() {
return beanPersistListener != null;
}
@@ -171,7 +167,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
public void addToPersistMap(BeanPersistIdMap beanPersistMap) {
- beanPersistMap.add(beanDescriptor, type, idValue);
+ beanPersistMap.add(beanDescriptor, type, idValue);
}
public boolean notifyLocalPersistListener() {
@@ -248,16 +244,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
}
}
- /**
- * Set the type of this request. One of INSERT, UPDATE, DELETE, UPDATESQL or
- * CALLABLESQL.
- */
- @Override
- public void setType(Type type) {
- this.type = type;
- notifyCache = beanDescriptor.isCacheNotify();
- }
-
public BeanManager getBeanManager() {
return beanManager;
}
@@ -284,14 +270,6 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
return deleteMissingChildren;
}
- /**
- * Return true if null properties should be updated (treated as loaded) for
- * stateless updates.
- */
- public boolean isUpdateNullProperties() {
- return updateNullProperties;
- }
-
/**
* Set to true if this is a stateless update.
*
@@ -300,10 +278,9 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
* that was probably created from JSON or XML.
*
*/
- public void setStatelessUpdate(boolean statelessUpdate, boolean deleteMissingChildren, boolean updateNullProperties) {
+ public void setStatelessUpdate(boolean statelessUpdate, boolean deleteMissingChildren) {
this.statelessUpdate = statelessUpdate;
this.deleteMissingChildren = deleteMissingChildren;
- this.updateNullProperties = updateNullProperties;
}
/**
@@ -546,7 +523,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
if (prop != null && intercept.isLoadedProperty(prop.getPropertyIndex())) {
// OK to use version property
} else {
- concurrencyMode = ConcurrencyMode.NONE;//ALL;
+ concurrencyMode = ConcurrencyMode.NONE;
}
}
@@ -560,7 +537,7 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
*
*/
public boolean isDynamicUpdateSql() {
- return beanDescriptor.isUpdateChangesOnly() || !intercept.isFullyLoadedBean();//(loadedProps != null);
+ return beanDescriptor.isUpdateChangesOnly() || !intercept.isFullyLoadedBean();
}
/**
@@ -587,12 +564,15 @@ public class PersistRequestBean extends PersistRequest implements BeanPersist
}
public void postInsert() {
- // mark all properties as loaded after an insert
- // to support immediate update
+ // 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);
}
}
+ public boolean isReference() {
+ return beanDescriptor.isReference(intercept);
+ }
+
}
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 268ddf8ec..177dd712e 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java
@@ -1,7 +1,6 @@
package com.avaje.ebeaninternal.server.core;
import java.util.Collection;
-import java.util.Set;
import com.avaje.ebean.CallableSql;
import com.avaje.ebean.SqlUpdate;
@@ -18,7 +17,7 @@ public interface Persister {
/**
* Force an Update using the given bean.
*/
- public void forceUpdate(EntityBean entityBean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties);
+ public void forceUpdate(EntityBean entityBean, Transaction t, boolean deleteMissingChildren);
/**
* Force an Insert using the given bean.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableVisitor.java b/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableVisitor.java
index b14b1e2ef..1f331dbbd 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableVisitor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/ddl/CreateTableVisitor.java
@@ -201,12 +201,12 @@ public class CreateTableVisitor extends AbstractBeanVisitor {
}
- BeanProperty[] ids = descriptor.propertiesId();
+ BeanProperty idProp = descriptor.getIdProperty();
- if (ids.length == 0){
+ if (idProp == null){
// No comma + new line
ctx.removeLast().removeLast();
- } else if (ids.length > 1 || ddl.isInlinePrimaryKeyConstraint()) {
+ } else if (ddl.isInlinePrimaryKeyConstraint()) {
// The Primary Key constraint was inlined with the column
// ... No comma + new line
ctx.removeLast().removeLast();
@@ -216,7 +216,7 @@ public class CreateTableVisitor extends AbstractBeanVisitor {
String pkName = ddl.getPrimaryKeyName(table);
ctx.write(" constraint ").write(pkName).write(" primary key (");
- VisitorUtil.visit(ids, new AbstractPropertyVisitor() {
+ VisitorUtil.visit(idProp, new AbstractPropertyVisitor() {
@Override
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne> embedded) {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/ddl/VisitorUtil.java b/src/main/java/com/avaje/ebeaninternal/server/ddl/VisitorUtil.java
index 3d5341382..d9520e1a3 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/ddl/VisitorUtil.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/ddl/VisitorUtil.java
@@ -43,36 +43,36 @@ public class VisitorUtil {
/**
* Visit the bean using a visitor.
*/
- public static void visitBean(BeanDescriptor> desc, BeanVisitor visitor) {
+ public static void visitBean(BeanDescriptor> desc, BeanVisitor visitor) {
- if (visitor.visitBean(desc)) {
+ if (visitor.visitBean(desc)) {
- BeanProperty[] propertiesId = desc.propertiesId();
- for (int i = 0; i < propertiesId.length; i++) {
- visit(visitor, propertiesId[i]);
- }
- BeanPropertyAssocOne> unidirectional = desc.getUnidirectional();
- if (unidirectional != null){
- visit(visitor, unidirectional);
- }
- BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
- for (int i = 0; i < propertiesNonTransient.length; i++) {
- BeanProperty p = propertiesNonTransient[i];
- if (!p.isFormula() && !p.isSecondaryTable()){
- visit(visitor, p);
- }
- }
-
- visitor.visitBeanEnd(desc);
- }
- }
-
- private static void visit(BeanVisitor visitor, BeanProperty p) {
- PropertyVisitor pv = visitor.visitProperty(p);
- if (pv != null){
- visit(p, pv);
+ BeanProperty idProp = desc.getIdProperty();
+ if (idProp != null) {
+ visit(visitor, idProp);
+ }
+ BeanPropertyAssocOne> unidirectional = desc.getUnidirectional();
+ if (unidirectional != null) {
+ visit(visitor, unidirectional);
+ }
+ BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
+ for (int i = 0; i < propertiesNonTransient.length; i++) {
+ BeanProperty p = propertiesNonTransient[i];
+ if (!p.isFormula() && !p.isSecondaryTable()) {
+ visit(visitor, p);
}
- }
+ }
+
+ visitor.visitBeanEnd(desc);
+ }
+ }
+
+ private static void visit(BeanVisitor visitor, BeanProperty p) {
+ PropertyVisitor pv = visitor.visitProperty(p);
+ if (pv != null) {
+ visit(p, pv);
+ }
+ }
/**
* Visit all the properties.
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 d8dfab285..743f12b1a 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptor.java
@@ -1,5 +1,6 @@
package com.avaje.ebeaninternal.server.deploy;
+import java.lang.reflect.Modifier;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
@@ -217,12 +218,15 @@ public class BeanDescriptor implements MetaBeanInfo {
/**
* Derived list of properties that make up the unique id.
*/
- private final BeanProperty[] propertiesId;
+ private final BeanProperty idProperty;
+ private final int idPropertyIndex;
/**
* Derived list of properties that are used for version concurrency checking.
*/
private final BeanProperty versionProperty;
+ private final int versionPropertyIndex;
+
private final BeanProperty propertiesNaturalKey;
/**
@@ -281,14 +285,7 @@ public class BeanDescriptor implements MetaBeanInfo {
/**
* All non transient properties excluding the id properties.
*/
- final BeanProperty[] propertiesNonTransient;
-
-
- /**
- * Set when the Id property is a single non-embedded property. Can make life
- * simpler for this case.
- */
- private final BeanProperty propertySingleId;
+ private final BeanProperty[] propertiesNonTransient;
/**
* The bean class name or the table name for MapBeans.
@@ -403,15 +400,15 @@ public class BeanDescriptor implements MetaBeanInfo {
// helper object used to derive lists of properties
DeployBeanPropertyLists listHelper = new DeployBeanPropertyLists(owner, this, deploy);
+ this.idProperty = listHelper.getId();
+ this.versionProperty = listHelper.getVersionProperty();
this.propMap = listHelper.getPropertyMap();
this.propMapByDbColumn = getReverseMap(propMap);
this.propertiesTransient = listHelper.getTransients();
this.propertiesNonTransient = listHelper.getNonTransients();
this.propertiesBaseScalar = listHelper.getBaseScalar();
this.propertiesBaseCompound = listHelper.getBaseCompound();
- this.propertiesId = listHelper.getId();
this.propertiesNaturalKey = listHelper.getNaturalKey();
- this.versionProperty = listHelper.getVersionProperty();
this.propertiesEmbedded = listHelper.getEmbedded();
this.propertiesLocal = listHelper.getLocal();
this.unidirectional = listHelper.getUnidirectional();
@@ -436,12 +433,6 @@ public class BeanDescriptor implements MetaBeanInfo {
this.derivedTableJoins = listHelper.getTableJoin();
- if (propertiesId.length == 1) {
- this.propertySingleId = propertiesId[0];
- } else {
- this.propertySingleId = null;
- }
-
// Check if there are no cascade save associated beans ( subject to change
// in initialiseOther()). Note that if we are in an inheritance hierarchy
// then we also need to check every BeanDescriptors in the InheritInfo as
@@ -454,9 +445,20 @@ public class BeanDescriptor implements MetaBeanInfo {
deleteRecurseSkippable = (0 == (propertiesOneExportedDelete.length + propertiesOneImportedDelete.length + propertiesManyDelete.length));
// object used to handle Id values
- this.idBinder = owner.createIdBinder(propertiesId);
- }
+ this.idBinder = owner.createIdBinder(idProperty);
+ // derive the index position of the Id and Version properties
+ if (Modifier.isAbstract(beanType.getModifiers())) {
+ this.idPropertyIndex = -1;
+ this.versionPropertyIndex = -1;
+ } else {
+ EntityBean entityBean = createEntityBean();
+ EntityBeanIntercept ebi = entityBean._ebean_getIntercept();
+ this.idPropertyIndex = (idProperty == null) ? -1 : ebi.findProperty(idProperty.getName());
+ this.versionPropertyIndex = (versionProperty == null) ? -1 : ebi.findProperty(versionProperty.getName());
+ }
+ }
+
private LinkedHashMap getReverseMap(LinkedHashMap propMap) {
LinkedHashMap revMap = new LinkedHashMap(propMap.size() * 2);
@@ -523,26 +525,6 @@ public class BeanDescriptor implements MetaBeanInfo {
return dirtyProperties;
}
- /**
- * Determine the non-null properties of the bean.
- */
- public Set determineLoadedProperties(EntityBean bean) {
-
- HashSet nonNullProps = new HashSet();
-
- for (int j = 0; j < propertiesId.length; j++) {
- if (propertiesId[j].getValue(bean) != null) {
- nonNullProps.add(propertiesId[j].getName());
- }
- }
- for (int i = 0; i < propertiesNonTransient.length; i++) {
- if (propertiesNonTransient[i].getValue(bean) != null) {
- nonNullProps.add(propertiesNonTransient[i].getName());
- }
- }
- return nonNullProps;
- }
-
/**
* Return the EbeanServer instance that owns this BeanDescriptor.
*/
@@ -591,9 +573,8 @@ public class BeanDescriptor implements MetaBeanInfo {
}
} else {
// initialise just the Id properties
- BeanProperty[] idProps = propertiesId();
- for (int i = 0; i < idProps.length; i++) {
- idProps[i].initialise();
+ if (idProperty != null) {
+ idProperty.initialise();
}
}
}
@@ -1367,7 +1348,7 @@ public class BeanDescriptor implements MetaBeanInfo {
// Note: not creating proxies for many's...
- ebi.setReference();
+ ebi.setReference(idPropertyIndex);
return (T) eb;
@@ -1508,20 +1489,7 @@ public class BeanDescriptor implements MetaBeanInfo {
* properties that make up the unique id.
*/
public Object getId(EntityBean bean) {
-
- if (propertySingleId != null) {
- return propertySingleId.getValue(bean);
- }
-
- // it is a concatenated id Not embedded
- // so return a Map
- LinkedHashMap idMap = new LinkedHashMap();
- for (int i = 0; i < propertiesId.length; i++) {
-
- Object value = propertiesId[i].getValue(bean);
- idMap.put(propertiesId[i].getName(), value);
- }
- return idMap;
+ return (idProperty == null) ? null : idProperty.getValue(bean);
}
/**
@@ -2013,17 +1981,6 @@ public class BeanDescriptor implements MetaBeanInfo {
return propMap.values().iterator();
}
- /**
- * Return the BeanProperty that make up the unique id.
- *
- * The order of these properties can be relied on to be consistent if the bean
- * itself doesn't change or the xml deployment order does not change.
- *
- */
- public BeanProperty[] propertiesId() {
- return propertiesId;
- }
-
/**
* Return the non transient non id properties.
*/
@@ -2038,14 +1995,6 @@ public class BeanDescriptor implements MetaBeanInfo {
return propertiesTransient;
}
- /**
- * If the Id is a single non-embedded property then returns that, otherwise
- * returns null.
- */
- public BeanProperty getSingleIdProperty() {
- return propertySingleId;
- }
-
/**
* Return the beans that are embedded. These share the base table with the
* owner bean.
@@ -2054,6 +2003,51 @@ public class BeanDescriptor implements MetaBeanInfo {
return propertiesEmbedded;
}
+ public BeanProperty getIdProperty() {
+ return idProperty;
+ }
+
+ public boolean isInsertMode(EntityBeanIntercept ebi) {
+ if (idProperty.isEmbedded()) {
+ return !ebi.isLoaded();
+ }
+ //if (idGenerator == null) {
+ // return !ebi.isLoaded();
+ //} else {
+ return !hasIdProperty(ebi);
+ //}
+ }
+
+ public boolean isReference(EntityBeanIntercept ebi) {
+ return ebi.isReference() || hasIdPropertyOnly(ebi);
+ }
+
+ public boolean hasIdPropertyOnly(EntityBeanIntercept ebi) {
+ return ebi.hasIdOnly(idPropertyIndex);
+ }
+
+ public boolean hasIdProperty(EntityBeanIntercept ebi) {
+ if (idPropertyIndex > -1) {
+ return ebi.isLoadedProperty(idPropertyIndex);
+ }
+ return false;
+ }
+
+ public boolean hasVersionProperty(EntityBeanIntercept ebi) {
+ if (versionPropertyIndex > -1) {
+ return ebi.isLoadedProperty(versionPropertyIndex);
+ }
+ return false;
+ }
+
+ public ConcurrencyMode getConcurrencyMode(EntityBeanIntercept ebi) {
+ if (!hasVersionProperty(ebi)) {
+ return ConcurrencyMode.NONE;
+ } else {
+ return concurrencyMode;
+ }
+ }
+
/**
* All the BeanPropertyAssocOne that are not embedded. These are effectively
* joined beans. For ManyToOne and OneToOne associations.
@@ -2248,8 +2242,6 @@ public class BeanDescriptor implements MetaBeanInfo {
@SuppressWarnings("unchecked")
private void jsonWriteProperties(WriteJsonContext ctx, EntityBean bean) {
- boolean referenceBean = ctx.isReferenceBean();
-
JsonWriteBeanVisitor beanVisitor = (JsonWriteBeanVisitor) ctx.getBeanVisitor();
Set props = ctx.getIncludeProperties();
@@ -2264,11 +2256,11 @@ public class BeanDescriptor implements MetaBeanInfo {
}
}
- for (int i = 0; i < propertiesId.length; i++) {
- Object idValue = propertiesId[i].getValue(bean);
+ if (idProperty != null) {
+ Object idValue = idProperty.getValue(bean);
if (idValue != null) {
- if (props == null || props.contains(propertiesId[i].getName())) {
- propertiesId[i].jsonWrite(ctx, bean);
+ if (props == null || props.contains(idProperty.getName())) {
+ idProperty.jsonWrite(ctx, bean);
}
}
}
@@ -2286,7 +2278,7 @@ public class BeanDescriptor implements MetaBeanInfo {
}
}
} else {
- if (explicitAllProps || !referenceBean) {
+ if (explicitAllProps || !isReference(bean._ebean_getIntercept())) {
// render all the properties and invoke lazy loading if required
for (int j = 0; j < propertiesNonTransient.length; j++) {
propertiesNonTransient[j].jsonWrite(ctx, bean);
@@ -2386,44 +2378,11 @@ public class BeanDescriptor implements MetaBeanInfo {
return ctx.popBeanState();
}
- /**
- * Set the loaded properties with additional check to see if the bean is a
- * reference.
- */
- public void setLoadedProps(EntityBeanIntercept ebi, Set loadedProps) {
- if (isLoadedReference(loadedProps)) {
- ebi.setReference();
- } else {
- ebi.setLoaded();
- }
- }
-
- /**
- * Return true if the loadedProperties is just the Id property and therefore
- * this is really a reference.
- */
- public boolean isLoadedReference(Set loadedProps) {
-
- if (loadedProps != null) {
- if (loadedProps.size() == propertiesId.length) {
- for (int i = 0; i < propertiesId.length; i++) {
- if (!loadedProps.contains(propertiesId[i].getName())) {
- return false;
- }
- }
- return true;
- }
- }
-
- return false;
- }
-
public void flushPersistenceContextOnIterate(PersistenceContext persistenceContext) {
persistenceContext.clear(beanType);
for (int i = 0; i < propertiesMany.length; i++) {
persistenceContext.clear(propertiesMany[i].getBeanDescriptor().getBeanType());
}
-
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
index fad2d4cc4..f9fbab992 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorManager.java
@@ -222,8 +222,8 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
}
}
- public IdBinder createIdBinder(BeanProperty[] uids) {
- return idBinderFactory.createIdBinder(uids);
+ public IdBinder createIdBinder(BeanProperty idProperty) {
+ return idBinderFactory.createIdBinder(idProperty);
}
public void deploy() {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorMap.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorMap.java
index 73a197f5b..a4833f578 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorMap.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanDescriptorMap.java
@@ -32,6 +32,6 @@ public interface BeanDescriptorMap {
*/
public EncryptKey getEncryptKey(String tableName, String columnName);
- public IdBinder createIdBinder(BeanProperty[] uids);
+ public IdBinder createIdBinder(BeanProperty id);
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
index 4ce2b4d73..f60483f71 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanFkeyProperty.java
@@ -168,7 +168,7 @@ public final class BeanFkeyProperty implements ElPropertyValue {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
- public void elSetValue(EntityBean bean, Object value, boolean populate, boolean reference) {
+ public void elSetValue(EntityBean bean, Object value, boolean populate) {
throw new RuntimeException("ElPropertyDeploy only - not implemented");
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java
index 7a98140c7..4b8d868be 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanProperty.java
@@ -757,11 +757,7 @@ public class BeanProperty implements ElPropertyValue {
return convertToLogicalType(value);
}
- public void elSetReference(EntityBean bean) {
- throw new RuntimeException("Should not be called");
- }
-
- public void elSetValue(EntityBean bean, Object value, boolean populate, boolean reference) {
+ public void elSetValue(EntityBean bean, Object value, boolean populate) {
if (bean != null) {
// Not using setValueIntercept at this stage
setValue(bean, value);
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
index 9d552e140..54583bb77 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssoc.java
@@ -4,18 +4,18 @@ import java.util.ArrayList;
import javax.persistence.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdEmbedded;
-import com.avaje.ebeaninternal.server.deploy.id.ImportedIdMultiple;
import com.avaje.ebeaninternal.server.deploy.id.ImportedIdSimple;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
@@ -219,11 +219,9 @@ public abstract class BeanPropertyAssoc extends BeanProperty {
public boolean hasId(EntityBean bean) {
BeanDescriptor> targetDesc = getTargetDescriptor();
-
- BeanProperty[] uids = targetDesc.propertiesId();
- for (int i = 0; i < uids.length; i++) {
-
- Object value = uids[i].getValue(bean);
+ BeanProperty idProp = targetDesc.getIdProperty();
+ if (idProp != null) {
+ Object value = idProp.getValue(bean);
if (value == null) {
return false;
}
@@ -311,39 +309,36 @@ public abstract class BeanPropertyAssoc extends BeanProperty {
*/
protected ImportedId createImportedId(BeanPropertyAssoc> owner, BeanDescriptor> target, TableJoin join) {
- BeanProperty[] props = target.propertiesId();
+ BeanProperty idProp = target.getIdProperty();
BeanProperty[] others = target.propertiesBaseScalar();
if (descriptor.isSqlSelectBased()){
String dbColumn = owner.getDbColumn();
- return new ImportedIdSimple(owner, dbColumn, props[0], 0);
+ return new ImportedIdSimple(owner, dbColumn, idProp, 0);
}
TableJoinColumn[] cols = join.columns();
- if (props.length == 1) {
- if (!props[0].isEmbedded()) {
- // simple single scalar id
- if (cols.length != 1){
- String msg = "No Imported Id column for ["+props[0]+"] in table ["+join.getTable()+"]";
- logger.error(msg);
- return null;
- } else {
- return createImportedScalar(owner, cols[0], props, others);
- }
+ if (idProp == null) {
+ return null;
+ }
+ if (!idProp.isEmbedded()) {
+ // simple single scalar id
+ if (cols.length != 1){
+ String msg = "No Imported Id column for ["+idProp+"] in table ["+join.getTable()+"]";
+ logger.error(msg);
+ return null;
} else {
- // embedded id
- BeanPropertyAssocOne> embProp = (BeanPropertyAssocOne>)props[0];
- BeanProperty[] embBaseProps = embProp.getTargetDescriptor().propertiesBaseScalar();
- ImportedIdSimple[] scalars = createImportedList(owner, cols, embBaseProps, others);
-
- return new ImportedIdEmbedded(owner, embProp, scalars);
+ BeanProperty[] idProps = {idProp};
+ return createImportedScalar(owner, cols[0], idProps, others);
}
-
} else {
- // Concatenated key that is not embedded
- ImportedIdSimple[] scalars = createImportedList(owner, cols, props, others);
- return new ImportedIdMultiple(owner, scalars);
+ // embedded id
+ BeanPropertyAssocOne> embProp = (BeanPropertyAssocOne>)idProp;
+ BeanProperty[] embBaseProps = embProp.getTargetDescriptor().propertiesBaseScalar();
+ ImportedIdSimple[] scalars = createImportedList(owner, cols, embBaseProps, others);
+
+ return new ImportedIdEmbedded(owner, embProp, scalars);
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
index 238368b8b..8ceb86d6a 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocMany.java
@@ -588,8 +588,8 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc {
if (embeddedExportedProperties) {
// use the EmbeddedId object instead of the parentBean
- BeanProperty[] uids = descriptor.propertiesId();
- parentBean = (EntityBean)uids[0].getValue(parentBean);
+ BeanProperty idProp = descriptor.getIdProperty();
+ parentBean = (EntityBean)idProp.getValue(parentBean);
}
for (int i = 0; i < exportedProperties.length; i++) {
@@ -621,13 +621,13 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc {
*/
private ExportedProperty[] createExported() {
- BeanProperty[] uids = descriptor.propertiesId();
+ BeanProperty idProp = descriptor.getIdProperty();
ArrayList list = new ArrayList();
- if (uids.length == 1 && uids[0].isEmbedded()) {
+ if (idProp != null && idProp.isEmbedded()) {
- BeanPropertyAssocOne> one = (BeanPropertyAssocOne>) uids[0];
+ BeanPropertyAssocOne> one = (BeanPropertyAssocOne>) idProp;
BeanDescriptor> targetDesc = one.getTargetDescriptor();
BeanProperty[] emIds = targetDesc.propertiesBaseScalar();
try {
@@ -641,8 +641,8 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc {
}
} else {
- for (int i = 0; i < uids.length; i++) {
- ExportedProperty expProp = findMatch(false, uids[i]);
+ if (idProp != null) {
+ ExportedProperty expProp = findMatch(false, idProp);
list.add(expProp);
}
}
@@ -773,8 +773,8 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc {
private void buildExport(IntersectionRow row, EntityBean parentBean) {
if (embeddedExportedProperties) {
- BeanProperty[] uids = descriptor.propertiesId();
- parentBean = (EntityBean)uids[0].getValue(parentBean);
+ BeanProperty idProp = descriptor.getIdProperty();
+ parentBean = (EntityBean)idProp.getValue(parentBean);
}
for (int i = 0; i < exportedProperties.length; i++) {
Object val = exportedProperties[i].getValue(parentBean);
@@ -856,6 +856,5 @@ public class BeanPropertyAssocMany extends BeanPropertyAssoc {
} while(true);
setValue(bean, collection);
-
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java
index facdfdc03..e9756f7ed 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyAssocOne.java
@@ -397,13 +397,6 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc {
return targetDescriptor.createEntityBean();
}
- public void elSetReference(EntityBean bean) {
- Object value = getValueIntercept(bean);
- if (value != null) {
- ((EntityBean) value)._ebean_getIntercept().setReference();
- }
- }
-
@Override
public Object elGetReference(EntityBean bean) {
Object value = getValueIntercept(bean);
@@ -441,13 +434,13 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc {
*/
private ExportedProperty[] createExported() {
- BeanProperty[] uids = descriptor.propertiesId();
+ BeanProperty idProp = descriptor.getIdProperty();
ArrayList list = new ArrayList();
- if (uids.length == 1 && uids[0].isEmbedded()) {
+ if (idProp != null && idProp.isEmbedded()) {
- BeanPropertyAssocOne> one = (BeanPropertyAssocOne>) uids[0];
+ BeanPropertyAssocOne> one = (BeanPropertyAssocOne>) idProp;
BeanDescriptor> targetDesc = one.getTargetDescriptor();
BeanProperty[] emIds = targetDesc.propertiesBaseScalar();
try {
@@ -461,8 +454,8 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc {
}
} else {
- for (int i = 0; i < uids.length; i++) {
- ExportedProperty expProp = findMatch(false, uids[i]);
+ if (idProp != null) {
+ ExportedProperty expProp = findMatch(false, idProp);
list.add(expProp);
}
}
@@ -806,8 +799,7 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc {
@Override
void appendSelect(DbSqlContext ctx, boolean subQuery) {
- // set appropriate tableAlias for
- // the exported id columns
+ // set appropriate tableAlias for the exported id columns
String relativePrefix = ctx.getRelativePrefix(getName());
ctx.pushTableAlias(relativePrefix);
@@ -838,20 +830,29 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc {
// bi-directional and already rendered parent
} else {
+ // Hmmm, not writing complex non-entity bean
+ if (value instanceof EntityBean) {
ctx.pushParentBean(bean);
ctx.beginAssocOne(name);
BeanDescriptor> refDesc = descriptor.getBeanDescriptor(value.getClass());
- refDesc.jsonWrite(ctx, (EntityBean)value);
+ refDesc.jsonWrite(ctx, (EntityBean)value);
ctx.endAssocOne();
ctx.popParentBean();
+ }
}
}
}
@Override
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
-
- T assocBean = targetDescriptor.jsonReadBean(ctx, name);
- setValue(bean, assocBean);
+ if (targetDescriptor != null) {
+ T assocBean = targetDescriptor.jsonReadBean(ctx, name);
+ setValue(bean, assocBean);
+ }
+ }
+
+ public boolean isReference(Object detailBean) {
+ EntityBean eb = (EntityBean)detailBean;
+ return targetDescriptor.isReference(eb._ebean_getIntercept());
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java
index 67c9725be..d05cf0e89 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/BeanPropertyCompoundScalar.java
@@ -90,13 +90,8 @@ public class BeanPropertyCompoundScalar extends BeanProperty {
}
@Override
- public void elSetReference(EntityBean bean) {
- super.elSetReference(bean);
- }
-
- @Override
- public void elSetValue(EntityBean bean, Object value, boolean populate, boolean reference) {
- super.elSetValue(bean, value, populate, reference);
+ public void elSetValue(EntityBean bean, Object value, boolean populate) {//, boolean reference) {
+ super.elSetValue(bean, value, populate);
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/DRawSqlSelectColumnsParser.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/DRawSqlSelectColumnsParser.java
index 1d2507839..10a44e251 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/DRawSqlSelectColumnsParser.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/DRawSqlSelectColumnsParser.java
@@ -193,11 +193,10 @@ public final class DRawSqlSelectColumnsParser {
}
}
- BeanProperty[] propertiesId = desc.propertiesId();
- for (int i = 0; i < propertiesId.length; i++) {
- BeanProperty prop = propertiesId[i];
- if (isMatch(prop, searchColumn)) {
- return prop;
+ BeanProperty idProp = desc.getIdProperty();
+ if (idProp != null) {
+ if (isMatch(idProp, searchColumn)) {
+ return idProp;
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java
index f0de30e87..7eab5eaf9 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinder.java
@@ -44,6 +44,11 @@ public interface IdBinder {
*/
public String getIdProperty();
+ /**
+ * Return the Id BeanProperty.
+ */
+ public BeanProperty getBeanProperty();
+
/**
* Find a BeanProperty that is mapped to the database column.
*/
@@ -154,11 +159,6 @@ public interface IdBinder {
*/
public String getBindIdSql(String baseTableAlias);
- /**
- * Return the id properties in flat form.
- */
- public BeanProperty[] getProperties();
-
/**
* Cast or convert the Id value if necessary and optionally set it.
*
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java
index dac8f83ea..fed1f003c 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmbedded.java
@@ -6,8 +6,6 @@ import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
-import javax.persistence.PersistenceException;
-
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
@@ -24,378 +22,382 @@ import com.avaje.ebeaninternal.server.type.DataBind;
*/
public final class IdBinderEmbedded implements IdBinder {
- private final BeanPropertyAssocOne> embIdProperty;
+ private final BeanPropertyAssocOne> embIdProperty;
- private final boolean idInExpandedForm;
-
- private BeanProperty[] props;
+ private final boolean idInExpandedForm;
- private BeanDescriptor> idDesc;
+ private BeanProperty[] props;
- private String idInValueSql;
-
-
- public IdBinderEmbedded(boolean idInExpandedForm, BeanPropertyAssocOne> embIdProperty) {
- this.idInExpandedForm = idInExpandedForm;
- this.embIdProperty = embIdProperty;
+ private BeanDescriptor> idDesc;
+
+ private String idInValueSql;
+
+ public IdBinderEmbedded(boolean idInExpandedForm, BeanPropertyAssocOne> embIdProperty) {
+ this.idInExpandedForm = idInExpandedForm;
+ this.embIdProperty = embIdProperty;
+ }
+
+ public void initialise() {
+ this.idDesc = embIdProperty.getTargetDescriptor();
+ this.props = embIdProperty.getProperties();
+ this.idInValueSql = idInExpandedForm ? idInExpanded() : idInCompressed();
+ }
+
+ private String idInExpanded() {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(" and ");
+ }
+ sb.append(embIdProperty.getName());
+ sb.append(".");
+ sb.append(props[i].getName());
+ sb.append("=?");
+ }
+ sb.append(")");
+
+ return sb.toString();
+ }
+
+ private String idInCompressed() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append("?");
+ }
+ sb.append(")");
+
+ return sb.toString();
+ }
+
+ @Override
+ public BeanProperty getBeanProperty() {
+ return embIdProperty;
+ }
+
+ public String getOrderBy(String pathPrefix, boolean ascending) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ if (pathPrefix != null) {
+ sb.append(pathPrefix).append(".");
+ }
+
+ sb.append(embIdProperty.getName()).append(".");
+ sb.append(props[i].getName());
+ if (!ascending) {
+ sb.append(" desc");
+ }
+ }
+ return sb.toString();
+ }
+
+ public BeanDescriptor> getIdBeanDescriptor() {
+ return idDesc;
+ }
+
+ public int getPropertyCount() {
+ return props.length;
+ }
+
+ public String getIdProperty() {
+ return embIdProperty.getName();
+ }
+
+ public void buildSelectExpressionChain(String prefix, List selectChain) {
+
+ prefix = SplitName.add(prefix, embIdProperty.getName());
+
+ for (int i = 0; i < props.length; i++) {
+ props[i].buildSelectExpressionChain(prefix, selectChain);
+ }
+ }
+
+ public BeanProperty findBeanProperty(String dbColumnName) {
+ for (int i = 0; i < props.length; i++) {
+ if (dbColumnName.equalsIgnoreCase(props[i].getDbColumn())) {
+ return props[i];
+ }
+ }
+ return null;
+ }
+
+ public boolean isComplexId() {
+ return true;
+ }
+
+ public String getDefaultOrderBy() {
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+
+ sb.append(embIdProperty.getName());
+ sb.append(".");
+ sb.append(props[i].getName());
}
- public void initialise() {
- this.idDesc = embIdProperty.getTargetDescriptor();
- this.props = embIdProperty.getProperties();
- this.idInValueSql = idInExpandedForm ? idInExpanded() : idInCompressed();
+ return sb.toString();
+ }
+
+ public BeanProperty[] getProperties() {
+ return props;
+ }
+
+ public void addIdInBindValue(SpiExpressionRequest request, Object value) {
+ for (int i = 0; i < props.length; i++) {
+ request.addBindValue(props[i].getValue((EntityBean) value));
+ }
+ }
+
+ public String getIdInValueExprDelete(int size) {
+ if (!idInExpandedForm) {
+ return getIdInValueExpr(size);
}
- private String idInExpanded() {
-
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- sb.append(embIdProperty.getName());
- sb.append(".");
- sb.append(props[i].getName());
- sb.append("=?");
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+
+ for (int j = 0; j < size; j++) {
+ if (j > 0) {
+ sb.append(" or ");
+ }
+ sb.append("(");
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(" and ");
}
- sb.append(")");
-
- return sb.toString();
+ sb.append(props[i].getDbColumn());
+ sb.append("=?");
+ }
+ sb.append(")");
}
-
- private String idInCompressed() {
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
- sb.append("?");
- }
- sb.append(")");
+ sb.append(") ");
+ return sb.toString();
+ }
- return sb.toString();
+ public String getIdInValueExpr(int size) {
+
+ StringBuilder sb = new StringBuilder();
+
+ if (!idInExpandedForm) {
+ sb.append(" in");
}
-
- public String getOrderBy(String pathPrefix, boolean ascending){
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(", ");
- }
- if (pathPrefix != null){
- sb.append(pathPrefix).append(".");
- }
-
- sb.append(embIdProperty.getName()).append(".");
- sb.append(props[i].getName());
- if (!ascending){
- sb.append(" desc");
- }
- }
- return sb.toString();
- }
-
- public BeanDescriptor> getIdBeanDescriptor() {
- return idDesc;
- }
-
- public int getPropertyCount() {
- return props.length;
- }
-
- public String getIdProperty() {
- return embIdProperty.getName();
- }
-
- public void buildSelectExpressionChain(String prefix, List selectChain) {
-
- prefix = SplitName.add(prefix, embIdProperty.getName());
-
- for (int i = 0; i < props.length; i++) {
- props[i].buildSelectExpressionChain(prefix, selectChain);
- }
- }
-
- public BeanProperty findBeanProperty(String dbColumnName) {
- for (int i = 0; i < props.length; i++) {
- if (dbColumnName.equalsIgnoreCase(props[i].getDbColumn())) {
- return props[i];
- }
- }
- return null;
- }
-
- public boolean isComplexId() {
- return true;
- }
-
- public String getDefaultOrderBy() {
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
-
- sb.append(embIdProperty.getName());
- sb.append(".");
- sb.append(props[i].getName());
- }
-
- return sb.toString();
- }
-
- public BeanProperty[] getProperties() {
- return props;
- }
-
- public void addIdInBindValue(SpiExpressionRequest request, Object value) {
- for (int i = 0; i < props.length; i++) {
- request.addBindValue(props[i].getValue((EntityBean)value));
- }
- }
-
- public String getIdInValueExprDelete(int size) {
- if (!idInExpandedForm){
- return getIdInValueExpr(size);
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append("(");
-
- for (int j = 0; j < size; j++) {
- if (j > 0){
- sb.append(" or ");
- }
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- sb.append(props[i].getDbColumn());
- sb.append("=?");
- }
- sb.append(")");
- }
- sb.append(") ");
- return sb.toString();
- }
-
- public String getIdInValueExpr(int size) {
-
- StringBuilder sb = new StringBuilder();
-
- if (!idInExpandedForm){
- sb.append(" in");
- }
- sb.append(" (");
- for (int i = 0; i < size; i++) {
- if (i > 0){
- if (idInExpandedForm) {
- sb.append(" or ");
- } else {
- sb.append(",");
- }
- }
- sb.append(idInValueSql);
- }
- sb.append(") ");
- return sb.toString();
- }
-
- public String getIdInValueExpr() {
- return idInValueSql;
- }
-
- public Object[] getIdValues(EntityBean bean) {
- Object val = embIdProperty.getValue(bean);
- Object[] bindvalues = new Object[props.length];
- for (int i = 0; i < props.length; i++) {
- bindvalues[i] = props[i].getValue((EntityBean)val);
- }
- return bindvalues;
- }
-
- public Object[] getBindValues(Object value) {
-
- Object[] bindvalues = new Object[props.length];
- for (int i = 0; i < props.length; i++) {
- bindvalues[i] = props[i].getValue((EntityBean)value);
- }
- return bindvalues;
- }
-
- public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
- for (int i = 0; i < props.length; i++) {
- Object embFieldValue = props[i].getValue((EntityBean)value);
- sqlUpdate.addParameter(embFieldValue);
- }
- }
-
- public void bindId(DataBind dataBind, Object value) throws SQLException {
-
- for (int i = 0; i < props.length; i++) {
- Object embFieldValue = props[i].getValue((EntityBean)value);
- props[i].bind(dataBind, embFieldValue);
- }
- }
-
- public Object readData(DataInput dataInput) throws IOException {
-
- EntityBean embId = idDesc.createBean();
- boolean notNull = true;
-
- for (int i = 0; i < props.length; i++) {
- Object value = props[i].readData(dataInput);
- props[i].setValue(embId, value);
- if (value == null) {
- notNull = false;
- }
- }
-
- if (notNull) {
- return embId;
+ sb.append(" (");
+ for (int i = 0; i < size; i++) {
+ if (i > 0) {
+ if (idInExpandedForm) {
+ sb.append(" or ");
} else {
- return null;
+ sb.append(",");
}
+ }
+ sb.append(idInValueSql);
+ }
+ sb.append(") ");
+ return sb.toString();
+ }
+
+ public String getIdInValueExpr() {
+ return idInValueSql;
+ }
+
+ public Object[] getIdValues(EntityBean bean) {
+ Object val = embIdProperty.getValue(bean);
+ Object[] bindvalues = new Object[props.length];
+ for (int i = 0; i < props.length; i++) {
+ bindvalues[i] = props[i].getValue((EntityBean) val);
+ }
+ return bindvalues;
+ }
+
+ public Object[] getBindValues(Object value) {
+
+ Object[] bindvalues = new Object[props.length];
+ for (int i = 0; i < props.length; i++) {
+ bindvalues[i] = props[i].getValue((EntityBean) value);
+ }
+ return bindvalues;
+ }
+
+ public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
+ for (int i = 0; i < props.length; i++) {
+ Object embFieldValue = props[i].getValue((EntityBean) value);
+ sqlUpdate.addParameter(embFieldValue);
+ }
+ }
+
+ public void bindId(DataBind dataBind, Object value) throws SQLException {
+
+ for (int i = 0; i < props.length; i++) {
+ Object embFieldValue = props[i].getValue((EntityBean) value);
+ props[i].bind(dataBind, embFieldValue);
+ }
+ }
+
+ public Object readData(DataInput dataInput) throws IOException {
+
+ EntityBean embId = idDesc.createBean();
+ boolean notNull = true;
+
+ for (int i = 0; i < props.length; i++) {
+ Object value = props[i].readData(dataInput);
+ props[i].setValue(embId, value);
+ if (value == null) {
+ notNull = false;
+ }
}
- public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
- for (int i = 0; i < props.length; i++) {
- Object embFieldValue = props[i].getValue((EntityBean)idValue);
- props[i].writeData(dataOutput, embFieldValue);
- }
+ if (notNull) {
+ return embId;
+ } else {
+ return null;
+ }
+ }
+
+ public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
+ for (int i = 0; i < props.length; i++) {
+ Object embFieldValue = props[i].getValue((EntityBean) idValue);
+ props[i].writeData(dataOutput, embFieldValue);
+ }
+ }
+
+ public void loadIgnore(DbReadContext ctx) {
+ for (int i = 0; i < props.length; i++) {
+ props[i].loadIgnore(ctx);
+ }
+ }
+
+ public Object read(DbReadContext ctx) throws SQLException {
+
+ EntityBean embId = idDesc.createBean();
+ boolean notNull = true;
+
+ for (int i = 0; i < props.length; i++) {
+ Object value = props[i].readSet(ctx, embId, null);
+ if (value == null) {
+ notNull = false;
+ }
}
- public void loadIgnore(DbReadContext ctx) {
- for (int i = 0; i < props.length; i++) {
- props[i].loadIgnore(ctx);
- }
+ if (notNull) {
+ return embId;
+ } else {
+ return null;
+ }
+ }
+
+ public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
+
+ Object embId = read(ctx);
+ if (embId != null) {
+ embIdProperty.setValue(bean, embId);
+ return embId;
+ } else {
+ return null;
+ }
+ }
+
+ public void appendSelect(DbSqlContext ctx, boolean subQuery) {
+ for (int i = 0; i < props.length; i++) {
+ props[i].appendSelect(ctx, subQuery);
+ }
+ }
+
+ public String getAssocIdInExpr(String prefix) {
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ if (prefix != null) {
+ sb.append(prefix);
+ sb.append(".");
+ }
+ sb.append(props[i].getName());
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+
+ public String getAssocOneIdExpr(String prefix, String operator) {
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(" and ");
+ }
+ if (prefix != null) {
+ sb.append(prefix);
+ sb.append(".");
+ }
+
+ sb.append(embIdProperty.getName());
+ sb.append(".");
+ sb.append(props[i].getName());
+ sb.append(operator);
+ }
+ return sb.toString();
+ }
+
+ public String getBindIdSql(String baseTableAlias) {
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(" and ");
+ }
+ if (baseTableAlias != null) {
+ sb.append(baseTableAlias);
+ sb.append(".");
+ }
+ sb.append(props[i].getDbColumn());
+ sb.append(" = ? ");
+ }
+ return sb.toString();
+ }
+
+ public String getBindIdInSql(String baseTableAlias) {
+
+ if (idInExpandedForm) {
+ return "";
}
- public Object read(DbReadContext ctx) throws SQLException {
+ StringBuilder sb = new StringBuilder();
+ sb.append("(");
+ for (int i = 0; i < props.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ if (baseTableAlias != null) {
+ sb.append(baseTableAlias);
+ sb.append(".");
+ }
+ sb.append(props[i].getDbColumn());
+ }
+ sb.append(")");
+ return sb.toString();
+ }
- EntityBean embId = idDesc.createBean();
- boolean notNull = true;
+ public Object convertSetId(Object idValue, EntityBean bean) {
- for (int i = 0; i < props.length; i++) {
- Object value = props[i].readSet(ctx, embId, null);
- if (value == null) {
- notNull = false;
- }
- }
-
- if (notNull) {
- return embId;
- } else {
- return null;
- }
+ // can not cast/convert if it is embedded
+ if (bean != null) {
+ // support PropertyChangeSupport
+ embIdProperty.setValueIntercept(bean, idValue);
}
- public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
-
- Object embId = read(ctx);
- if (embId != null) {
- embIdProperty.setValue(bean, embId);
- return embId;
- } else {
- return null;
- }
- }
-
- public void appendSelect(DbSqlContext ctx, boolean subQuery) {
- for (int i = 0; i < props.length; i++) {
- props[i].appendSelect(ctx, subQuery);
- }
- }
-
- public String getAssocIdInExpr(String prefix) {
-
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
- if (prefix != null) {
- sb.append(prefix);
- sb.append(".");
- }
- sb.append(props[i].getName());
- }
- sb.append(")");
- return sb.toString();
- }
-
- public String getAssocOneIdExpr(String prefix, String operator) {
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- if (prefix != null) {
- sb.append(prefix);
- sb.append(".");
- }
-
- sb.append(embIdProperty.getName());
- sb.append(".");
- sb.append(props[i].getName());
- sb.append(operator);
- }
- return sb.toString();
- }
-
- public String getBindIdSql(String baseTableAlias) {
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- if (baseTableAlias != null) {
- sb.append(baseTableAlias);
- sb.append(".");
- }
- sb.append(props[i].getDbColumn());
- sb.append(" = ? ");
- }
- return sb.toString();
- }
-
- public String getBindIdInSql(String baseTableAlias) {
-
- if (idInExpandedForm){
- return "";
- }
-
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
- if (baseTableAlias != null){
- sb.append(baseTableAlias);
- sb.append(".");
- }
- sb.append(props[i].getDbColumn());
- }
- sb.append(")");
- return sb.toString();
- }
-
- public Object convertSetId(Object idValue, EntityBean bean) {
-
- // can not cast/convert if it is embedded
- if (bean != null) {
- // support PropertyChangeSupport
- embIdProperty.setValueIntercept(bean, idValue);
- }
-
- return idValue;
- }
+ return idValue;
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java
index 1bf87c9f4..defe57740 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderEmpty.java
@@ -22,8 +22,6 @@ public final class IdBinderEmpty implements IdBinder {
private static final String bindIdSql = "";
- private static final BeanProperty[] properties = new BeanProperty[0];
-
public IdBinderEmpty() {
}
@@ -43,6 +41,11 @@ public final class IdBinderEmpty implements IdBinder {
return 0;
}
+ @Override
+ public BeanProperty getBeanProperty() {
+ return null;
+ }
+
public String getIdProperty() {
return null;
}
@@ -60,10 +63,6 @@ public final class IdBinderEmpty implements IdBinder {
return "";
}
- public BeanProperty[] getProperties() {
- return properties;
- }
-
public String getBindIdSql(String baseTableAlias) {
return bindIdSql;
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderFactory.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderFactory.java
index b11ea2f79..502fdfff3 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderFactory.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderFactory.java
@@ -19,21 +19,17 @@ public class IdBinderFactory {
/**
* Create the IdConvertSet for the given type of Id properties.
*/
- public IdBinder createIdBinder(BeanProperty[] uids) {
+ public IdBinder createIdBinder(BeanProperty id) {
- if (uids.length == 0){
+ if (id == null){
// for report type beans that don't need an id
return EMPTY;
- } else if (uids.length == 1){
- if (uids[0].isEmbedded()){
- return new IdBinderEmbedded(idInExpandedForm, (BeanPropertyAssocOne>)uids[0]);
- } else {
- return new IdBinderSimple(uids[0]);
- }
-
+ }
+ if (id.isEmbedded()){
+ return new IdBinderEmbedded(idInExpandedForm, (BeanPropertyAssocOne>)id);
} else {
- return new IdBinderMultiple(uids);
+ return new IdBinderSimple(id);
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderMultiple.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderMultiple.java
deleted file mode 100644
index 01179b0b8..000000000
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderMultiple.java
+++ /dev/null
@@ -1,399 +0,0 @@
-package com.avaje.ebeaninternal.server.deploy.id;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.persistence.PersistenceException;
-
-import com.avaje.ebean.bean.EntityBean;
-import com.avaje.ebeaninternal.api.SpiExpressionRequest;
-import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
-import com.avaje.ebeaninternal.server.core.InternString;
-import com.avaje.ebeaninternal.server.deploy.BeanProperty;
-import com.avaje.ebeaninternal.server.deploy.DbReadContext;
-import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
-import com.avaje.ebeaninternal.server.lib.util.MapFromString;
-import com.avaje.ebeaninternal.server.type.DataBind;
-
-/**
- * Bind an Id that is made up of multiple separate properties.
- *
- * The id passed in for binding is expected to be a map with the key being the
- * String name of the property and the value being that properties bind value.
- *
- */
-public final class IdBinderMultiple implements IdBinder {
-
- private final BeanProperty[] props;
-
- private final String idProperties;
-
- private final String idInValueSql;
-
- public IdBinderMultiple(BeanProperty[] idProps) {
- this.props = idProps;
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < idProps.length; i++) {
- if (i > 0){
- sb.append(",");
- }
- sb.append(idProps[i].getName());
- }
- idProperties = InternString.intern(sb.toString());
-
- sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0){
- sb.append(",");
- }
- sb.append("?");
- }
- sb.append(")");
-
- idInValueSql = sb.toString();
- }
-
- public void initialise(){
- // do nothing
- }
-
- public String getOrderBy(String pathPrefix, boolean ascending){
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" ");
- }
- if (pathPrefix != null){
- sb.append(pathPrefix).append(".");
- }
- sb.append(props[i].getName());
- if (!ascending){
- sb.append(" desc");
- }
- }
- return sb.toString();
- }
-
-
- public void buildSelectExpressionChain(String prefix, List selectChain) {
-
- for (int i = 0; i < props.length; i++) {
- props[i].buildSelectExpressionChain(prefix, selectChain);
- }
- }
-
-
- public int getPropertyCount() {
- return props.length;
- }
-
- public String getIdProperty() {
- return idProperties;
- }
-
-
- public BeanProperty findBeanProperty(String dbColumnName) {
-
- for (int i = 0; i < props.length; i++) {
- if (dbColumnName.equalsIgnoreCase(props[i].getDbColumn())){
- return props[i];
- }
- }
-
- return null;
- }
-
- public boolean isComplexId(){
- return true;
- }
-
- public String getDefaultOrderBy() {
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0){
- sb.append(",");
- }
-
- sb.append(props[i].getName());
- }
-
- return sb.toString();
- }
-
- public BeanProperty[] getProperties() {
- return props;
- }
-
- public void addIdInBindValue(SpiExpressionRequest request, Object value) {
- for (int i = 0; i < props.length; i++) {
- request.addBindValue(props[i].getValue((EntityBean)value));
- }
- }
-
- public String getIdInValueExprDelete(int size) {
- return getIdInValueExpr(size);
- }
-
- public String getIdInValueExpr(int size) {
- StringBuilder sb = new StringBuilder();
- sb.append(" in");
- sb.append(" (");
- sb.append(idInValueSql);
- for (int i = 1; i < size; i++) {
- sb.append(",").append(idInValueSql);
- }
- sb.append(") ");
- return sb.toString();
- }
-
- public String getBindIdInSql(String baseTableAlias) {
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
- if (baseTableAlias != null){
- sb.append(baseTableAlias);
- sb.append(".");
- }
- sb.append(props[i].getDbColumn());
- }
- sb.append(")");
- return sb.toString();
- }
-
- public Object[] getIdValues(EntityBean bean){
- Object[] bindvalues = new Object[props.length];
- for (int i = 0; i < props.length; i++) {
- bindvalues[i] = props[i].getValue(bean);
- }
- return bindvalues;
- }
-
- @SuppressWarnings("unchecked")
- public Object[] getBindValues(Object idValue){
-
- Object[] bindvalues = new Object[props.length];
- // concatenated id as a Map
- try {
- Map uidMap = (Map) idValue;
-
- for (int i = 0; i < props.length; i++) {
- Object value = uidMap.get(props[i].getName());
- bindvalues[i] = value;
- }
-
- return bindvalues;
-
- } catch (ClassCastException e) {
- String msg = "Expecting concatinated idValue to be a Map";
- throw new PersistenceException(msg, e);
- }
- }
-
- public Object readData(DataInput dataInput) throws IOException {
-
- LinkedHashMap map = new LinkedHashMap();
-
- boolean notNull = true;
-
- for (int i = 0; i < props.length; i++) {
- Object value = props[i].readData(dataInput);
- map.put(props[i].getName(), value);
- if (value == null) {
- notNull = false;
- }
- }
-
- if (notNull) {
- return map;
- } else {
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
-
- Map map = (Map)idValue;
- for (int i = 0; i < props.length; i++) {
- Object embFieldValue = map.get(props[i].getName());
- //Object embFieldValue = props[i].getValue(idValue);
- props[i].writeData(dataOutput, embFieldValue);
- }
- }
-
- public void loadIgnore(DbReadContext ctx) {
- for (int i = 0; i < props.length; i++) {
- props[i].loadIgnore(ctx);
- }
- }
-
- public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
-
- LinkedHashMap map = new LinkedHashMap();
- boolean notNull = false;
- for (int i = 0; i < props.length; i++) {
- Object value = props[i].readSet(ctx, bean, null);
- if (value != null){
- map.put(props[i].getName(), value);
- notNull = true;
- }
- }
- if (notNull){
- return map;
- } else {
- return null;
- }
- }
-
- public Object read(DbReadContext ctx) throws SQLException {
-
- LinkedHashMap map = new LinkedHashMap();
- boolean notNull = false;
- for (int i = 0; i < props.length; i++) {
- Object value = props[i].read(ctx);
- if (value != null){
- map.put(props[i].getName(), value);
- notNull = true;
- }
- }
- if (notNull){
- return map;
- } else {
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- public void bindId(DefaultSqlUpdate sqlUpdate, Object idValue) {
- // concatenated id as a Map
- try {
- Map uidMap = (Map) idValue;
-
- for (int i = 0; i < props.length; i++) {
- Object value = uidMap.get(props[i].getName());
- sqlUpdate.addParameter(value);
- }
-
- } catch (ClassCastException e) {
- String msg = "Expecting concatinated idValue to be a Map";
- throw new PersistenceException(msg, e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public void bindId(DataBind bind, Object idValue) throws SQLException {
-
- // concatenated id as a Map
- try {
- Map uidMap = (Map) idValue;
-
- for (int i = 0; i < props.length; i++) {
- Object value = uidMap.get(props[i].getName());
- props[i].bind(bind, value);
- }
-
- } catch (ClassCastException e) {
- String msg = "Expecting concatinated idValue to be a Map";
- throw new PersistenceException(msg, e);
- }
- }
-
- public void appendSelect(DbSqlContext ctx, boolean subQuery) {
- for (int i = 0; i < props.length; i++) {
- props[i].appendSelect(ctx, subQuery);
- }
- }
-
- public String getAssocIdInExpr(String prefix) {
-
- StringBuilder sb = new StringBuilder();
- sb.append("(");
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(",");
- }
- if (prefix != null) {
- sb.append(prefix);
- sb.append(".");
- }
- sb.append(props[i].getName());
- }
- sb.append(")");
- return sb.toString();
- }
-
- public String getAssocOneIdExpr(String prefix, String operator){
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- if (prefix != null){
- sb.append(prefix);
- sb.append(".");
- }
- sb.append(props[i].getName());
- sb.append(operator);
- }
- return sb.toString();
- }
-
- public String getBindIdSql(String baseTableAlias) {
-
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < props.length; i++) {
- if (i > 0) {
- sb.append(" and ");
- }
- if (baseTableAlias != null){
- sb.append(baseTableAlias);
- sb.append(".");
- }
- sb.append(props[i].getDbColumn());
- sb.append(" = ? ");
- }
- return sb.toString();
- }
-
- public Object convertSetId(Object idValue, EntityBean bean) {
-
- // allow Map or String for concatenated id
- Map,?> mapVal = null;
- if (idValue instanceof Map,?>) {
- mapVal = (Map,?>) idValue;
- } else {
- mapVal = MapFromString.parse(idValue.toString());
- }
-
- // Use a new LinkedHashMap to control the order
- LinkedHashMap newMap = new LinkedHashMap();
-
- for (int i = 0; i < props.length; i++) {
- BeanProperty prop = props[i];
-
- Object value = mapVal.get(prop.getName());
-
- // Convert the property type if required
- value = props[i].getScalarType().toBeanType(value);
- newMap.put(prop.getName(), value);
- if (bean != null) {
- // support PropertyChangeSupport
- prop.setValueIntercept(bean, value);
- }
- }
-
- return newMap;
- }
-}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
index 4a23e69ba..babff92ea 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/id/IdBinderSimple.java
@@ -26,8 +26,6 @@ public final class IdBinderSimple implements IdBinder {
private final String bindIdSql;
- private final BeanProperty[] properties;
-
private final Class> expectedType;
@SuppressWarnings("rawtypes")
@@ -37,8 +35,6 @@ public final class IdBinderSimple implements IdBinder {
this.idProperty = idProperty;
this.scalarType = idProperty.getScalarType();
this.expectedType = idProperty.getPropertyType();
- this.properties = new BeanProperty[1];
- properties[0] = idProperty;
bindIdSql = InternString.intern(idProperty.getDbColumn()+" = ? ");
}
@@ -46,33 +42,37 @@ public final class IdBinderSimple implements IdBinder {
// do nothing
}
+ public String getOrderBy(String pathPrefix, boolean ascending) {
- public String getOrderBy(String pathPrefix, boolean ascending){
-
- StringBuilder sb = new StringBuilder();
- if (pathPrefix != null){
- sb.append(pathPrefix).append(".");
- }
- sb.append(idProperty.getName());
- if (!ascending){
- sb.append(" desc");
- }
- return sb.toString();
+ StringBuilder sb = new StringBuilder();
+ if (pathPrefix != null) {
+ sb.append(pathPrefix).append(".");
}
+ sb.append(idProperty.getName());
+ if (!ascending) {
+ sb.append(" desc");
+ }
+ return sb.toString();
+ }
- public void buildSelectExpressionChain(String prefix, List selectChain) {
+ public void buildSelectExpressionChain(String prefix, List selectChain) {
+
+ idProperty.buildSelectExpressionChain(prefix, selectChain);
+ }
- idProperty.buildSelectExpressionChain(prefix, selectChain);
- }
+ /**
+ * Returns 1.
+ */
+ public int getPropertyCount() {
+ return 1;
+ }
+
+ @Override
+ public BeanProperty getBeanProperty() {
+ return idProperty;
+ }
- /**
- * Returns 1.
- */
- public int getPropertyCount() {
- return 1;
- }
-
- public String getIdProperty() {
+ public String getIdProperty() {
return idProperty.getName();
}
@@ -90,128 +90,124 @@ public final class IdBinderSimple implements IdBinder {
public String getDefaultOrderBy() {
return idProperty.getName();
}
-
- public BeanProperty[] getProperties() {
- return properties;
- }
- public String getBindIdInSql(String baseTableAlias) {
- if (baseTableAlias == null){
- return idProperty.getDbColumn();
- } else {
- return baseTableAlias+"."+idProperty.getDbColumn();
- }
- }
+ public String getBindIdInSql(String baseTableAlias) {
+ if (baseTableAlias == null) {
+ return idProperty.getDbColumn();
+ } else {
+ return baseTableAlias + "." + idProperty.getDbColumn();
+ }
+ }
- public String getBindIdSql(String baseTableAlias) {
- if (baseTableAlias == null){
- return bindIdSql;
- } else {
- return baseTableAlias+"."+bindIdSql;
- }
- }
+ public String getBindIdSql(String baseTableAlias) {
+ if (baseTableAlias == null) {
+ return bindIdSql;
+ } else {
+ return baseTableAlias + "." + bindIdSql;
+ }
+ }
- public Object[] getIdValues(EntityBean bean){
- return new Object[]{idProperty.getValue(bean)};
- }
-
- public Object[] getBindValues(Object idValue){
- return new Object[]{idValue};
- }
+ public Object[] getIdValues(EntityBean bean) {
+ return new Object[] { idProperty.getValue(bean) };
+ }
- public String getIdInValueExprDelete(int size) {
- return getIdInValueExpr(size);
+ public Object[] getBindValues(Object idValue) {
+ return new Object[] { idValue };
+ }
+
+ public String getIdInValueExprDelete(int size) {
+ return getIdInValueExpr(size);
+ }
+
+ public String getIdInValueExpr(int size) {
+ StringBuilder sb = new StringBuilder(2 * size + 10);
+ sb.append(" in");
+ sb.append(" (?");
+ for (int i = 1; i < size; i++) {
+ sb.append(",?");
+ }
+ sb.append(") ");
+ return sb.toString();
+ }
+
+ public void addIdInBindValue(SpiExpressionRequest request, Object value) {
+ value = convertSetId(value, null);
+ request.addBindValue(value);
+ }
+
+ public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
+ sqlUpdate.addParameter(value);
+ }
+
+ public void bindId(DataBind dataBind, Object value) throws SQLException {
+ if (!value.getClass().equals(expectedType)) {
+ value = scalarType.toBeanType(value);
+ }
+ idProperty.bind(dataBind, value);
+ }
+
+ public void writeData(DataOutput os, Object value) throws IOException {
+ idProperty.writeData(os, value);
+ }
+
+ public Object readData(DataInput is) throws IOException {
+ return idProperty.readData(is);
+ }
+
+ public void loadIgnore(DbReadContext ctx) {
+ idProperty.loadIgnore(ctx);
+ }
+
+ public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
+ Object id = idProperty.read(ctx);
+ if (id != null) {
+ idProperty.setValue(bean, id);
+ }
+ return id;
+ }
+
+ public Object read(DbReadContext ctx) throws SQLException {
+ return idProperty.read(ctx);
+ }
+
+ public void appendSelect(DbSqlContext ctx, boolean subQuery) {
+ idProperty.appendSelect(ctx, subQuery);
+ }
+
+ public String getAssocOneIdExpr(String prefix, String operator) {
+
+ StringBuilder sb = new StringBuilder();
+ if (prefix != null) {
+ sb.append(prefix);
+ sb.append(".");
+ }
+ sb.append(idProperty.getName());
+ sb.append(operator);
+ return sb.toString();
+ }
+
+ public String getAssocIdInExpr(String prefix) {
+
+ StringBuilder sb = new StringBuilder();
+ if (prefix != null) {
+ sb.append(prefix);
+ sb.append(".");
+ }
+ sb.append(idProperty.getName());
+ return sb.toString();
+ }
+
+ public Object convertSetId(Object idValue, EntityBean bean) {
+
+ if (!idValue.getClass().equals(expectedType)) {
+ idValue = scalarType.toBeanType(idValue);
}
- public String getIdInValueExpr(int size) {
- StringBuilder sb = new StringBuilder(2*size+10);
- sb.append(" in");
- sb.append(" (?");
- for (int i = 1; i < size; i++) {
- sb.append(",?");
- }
- sb.append(") ");
- return sb.toString();
+ if (bean != null) {
+ // support PropertyChangeSupport
+ idProperty.setValueIntercept(bean, idValue);
}
- public void addIdInBindValue(SpiExpressionRequest request, Object value) {
- value = convertSetId(value, null);
- request.addBindValue(value);
- }
-
- public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
- sqlUpdate.addParameter(value);
- }
-
- public void bindId(DataBind dataBind, Object value) throws SQLException {
- if( !value.getClass().equals(expectedType) ){
- value = scalarType.toBeanType(value);
- }
- idProperty.bind(dataBind, value);
- }
-
- public void writeData(DataOutput os, Object value) throws IOException {
- idProperty.writeData(os, value);
- }
-
- public Object readData(DataInput is) throws IOException {
- return idProperty.readData(is);
- }
-
- public void loadIgnore(DbReadContext ctx) {
- idProperty.loadIgnore(ctx);
- }
-
- public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
- Object id = idProperty.read(ctx);
- if (id != null){
- idProperty.setValue(bean, id);
- }
- return id;
- }
-
- public Object read(DbReadContext ctx) throws SQLException {
- return idProperty.read(ctx);
- }
-
- public void appendSelect(DbSqlContext ctx, boolean subQuery) {
- idProperty.appendSelect(ctx, subQuery);
- }
-
- public String getAssocOneIdExpr(String prefix, String operator){
-
- StringBuilder sb = new StringBuilder();
- if (prefix != null){
- sb.append(prefix);
- sb.append(".");
- }
- sb.append(idProperty.getName());
- sb.append(operator);
- return sb.toString();
- }
-
- public String getAssocIdInExpr(String prefix) {
-
- StringBuilder sb = new StringBuilder();
- if (prefix != null) {
- sb.append(prefix);
- sb.append(".");
- }
- sb.append(idProperty.getName());
- return sb.toString();
- }
-
- public Object convertSetId(Object idValue, EntityBean bean) {
-
- if (!idValue.getClass().equals(expectedType)){
- idValue = scalarType.toBeanType(idValue);
- }
-
- if (bean != null) {
- // support PropertyChangeSupport
- idProperty.setValueIntercept(bean, idValue);
- }
-
- return idValue;
- }
+ return idValue;
+ }
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyLists.java b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyLists.java
index 7c6e32262..b39aa6b2e 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyLists.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/deploy/meta/DeployBeanPropertyLists.java
@@ -185,8 +185,16 @@ public class DeployBeanPropertyLists {
return null;
}
- public BeanProperty[] getId() {
- return (BeanProperty[]) ids.toArray(new BeanProperty[ids.size()]);
+ public BeanProperty getId() {
+ if (ids.size() > 1) {
+ String msg = "Ebean does not support multiple @Id properties. You need to convert to using an @EmbeddedId."
+ +" Please email the ebean google group if you need further clarification.";
+ throw new IllegalStateException(msg);
+ }
+ if (ids.isEmpty()) {
+ return null;
+ }
+ return ids.get(0);
}
public BeanProperty[] getNonTransients() {
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
index 1fefe6d34..c23dc7465 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyChain.java
@@ -268,20 +268,7 @@ public class ElPropertyChain implements ElPropertyValue {
}
}
- public void elSetReference(EntityBean bean) {
-
- for (int i = 0; i < last; i++) {
- bean = (EntityBean)chain[i].elGetValue(bean);
- if (bean == null){
- break;
- }
- }
- if (bean != null){
- ((EntityBean)bean)._ebean_getIntercept().setReference();
- }
- }
-
- public void elSetValue(EntityBean bean, Object value, boolean populate, boolean reference){
+ public void elSetValue(EntityBean bean, Object value, boolean populate) {
EntityBean prevBean = bean;
if (populate){
@@ -302,12 +289,10 @@ public class ElPropertyChain implements ElPropertyValue {
if (lastBeanProperty != null){
// last chain element maps to a real scalar property
lastBeanProperty.setValueIntercept(prevBean, value);
- if (reference){
- ((EntityBean)prevBean)._ebean_getIntercept().setReference();
- }
+
} else {
// a non-scalar property of a Compound value object
- lastElPropertyValue.elSetValue(prevBean, value, populate, reference);
+ lastElPropertyValue.elSetValue(prevBean, value, populate);
}
}
}
diff --git a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
index 4f250e092..344e3b4f2 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/el/ElPropertyValue.java
@@ -104,12 +104,7 @@ public interface ElPropertyValue extends ElPropertyDeploy {
* If populate then
*
*/
- public void elSetValue(EntityBean bean, Object value, boolean populate, boolean reference);
-
- /**
- * Make the owning bean of this property a reference (as in not new/dirty).
- */
- public void elSetReference(EntityBean bean);
+ public void elSetValue(EntityBean bean, Object value, boolean populate);
/**
* Convert the value to the expected type.
diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java
index a09d5eb64..748e41127 100644
--- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java
+++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java
@@ -2,13 +2,15 @@ package com.avaje.ebeaninternal.server.persist;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.PersistenceException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.avaje.ebean.CallableSql;
import com.avaje.ebean.Query;
import com.avaje.ebean.SqlUpdate;
@@ -38,8 +40,6 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
import com.avaje.ebeaninternal.server.deploy.ManyType;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Persister implementation using DML.
@@ -76,7 +76,6 @@ public final class DefaultPersister implements Persister {
this.server = server;
this.beanDescriptorManager = descMgr;
this.persistExecute = new DefaultPersistExecute(binder, pstmtBatch);
-
}
/**
@@ -150,44 +149,25 @@ public final class DefaultPersister implements Persister {
server.delete(detailBean, t);
}
- /**
- * Force an Update using the given bean.
- */
- public void forceUpdate(EntityBean bean, Set updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties) {
+ /**
+ * Force an Update using the given bean.
+ */
+ public void forceUpdate(EntityBean entityBean, Transaction t, boolean deleteMissingChildren) {
- EntityBean entityBean = (EntityBean)bean;
- EntityBeanIntercept ebi = entityBean._ebean_getIntercept();
- if (ebi.isNew()) {
- ebi.setNewBeanForUpdate();
- }
+ PersistRequestBean> req = createRequest(entityBean, t, null, PersistRequest.Type.UPDATE);
+ req.setStatelessUpdate(true, deleteMissingChildren);
+ try {
+ req.initTransIfRequired();
+ update(req);
+ req.commitTransIfRequired();
+ // finished a 'normal' update
+ return;
- if (ebi.isDirty() || ebi.isLoaded()) {
- // a 'normal' update using 'dirty' properties from internal bean state.
- // if not dirty we still update in case any cascading save occurs
- PersistRequestBean> req = createRequest(bean, t, null);
- req.setStatelessUpdate(true, deleteMissingChildren, updateNullProperties);
- try {
- req.initTransIfRequired();
- update(req);
- req.commitTransIfRequired();
- // finished a 'normal' update
- return;
-
- } catch (RuntimeException ex) {
- req.rollbackTransIfRequired();
- throw ex;
- }
-
- } else if (ebi.isReference()) {
- // just return as no point in cascading (no modified beans/lists)
- ((SpiTransaction)t).logSql("-- No update as bean is just a reference bean");
- return;
-
- } else {
- ((SpiTransaction)t).logSql("-- No update as bean is not dirty");
- }
-
- }
+ } catch (RuntimeException ex) {
+ req.rollbackTransIfRequired();
+ throw ex;
+ }
+ }
public void save(EntityBean bean, Transaction t) {
saveRecurse(bean, t, null);
@@ -198,7 +178,7 @@ public final class DefaultPersister implements Persister {
*/
public void forceInsert(EntityBean bean, Transaction t) {
- PersistRequestBean> req = createRequest(bean, t, null);
+ PersistRequestBean> req = createRequest(bean, t, null, PersistRequest.Type.INSERT);
try {
req.initTransIfRequired();
insert(req);
@@ -219,7 +199,7 @@ public final class DefaultPersister implements Persister {
throw new IllegalArgumentException("This bean is of type ["+bean.getClass()+"] is not enhanced?");
}
- PersistRequestBean> req = createRequest(bean, t, parentBean);
+ PersistRequestBean> req = createRequest(bean, t, parentBean, PersistRequest.Type.DETERMINE);
try {
req.initTransIfRequired();
saveEnhanced(req);
@@ -238,21 +218,20 @@ public final class DefaultPersister implements Persister {
EntityBeanIntercept intercept = request.getEntityBeanIntercept();
- if (intercept.isReference()) {
+ if (request.isReference()) {
// its a reference...
if (request.isPersistCascade()) {
// save any associated List held beans
intercept.setLoaded();
saveAssocMany(false, request);
- intercept.setReference();
+ intercept.setReference(-1);
}
} else {
- if (intercept.isLoaded()) {
- // Need to call setLoaded(false) to simulate insert
- update(request);
+ if (request.isInsert()) {
+ insert(request);
} else {
- insert(request);
+ update(request);
}
}
}
@@ -268,9 +247,6 @@ public final class DefaultPersister implements Persister {
}
try {
- request.setType(PersistRequest.Type.INSERT);
- request.setNotNullAsLoaded();
-
if (request.isPersistCascade()) {
// save associated One beans recursively first
saveAssocOne(request);
@@ -300,8 +276,6 @@ public final class DefaultPersister implements Persister {
}
try {
- // we have determined that it is an update
- request.setType(PersistRequest.Type.UPDATE);
if (request.isPersistCascade()) {
// save associated One beans recursively first
saveAssocOne(request);
@@ -331,7 +305,7 @@ public final class DefaultPersister implements Persister {
*/
public void delete(EntityBean bean, Transaction t) {
- PersistRequestBean> req = createRequest(bean, t, null);
+ PersistRequestBean> req = createRequest(bean, t, null, PersistRequest.Type.DELETE);
if (req.isRegisteredForDeleteBean()) {
// skip deleting bean. Used where cascade is on
// both sides of a relationship
@@ -340,7 +314,7 @@ public final class DefaultPersister implements Persister {
}
return;
}
- req.setType(PersistRequest.Type.DELETE);
+
try {
req.initTransIfRequired();
delete(req);
@@ -603,7 +577,6 @@ public final class DefaultPersister implements Persister {
private final boolean cascade;
private final boolean statelessUpdate;
private final boolean deleteMissingChildren;
- private final boolean updateNullProperties;
private SaveManyPropRequest(boolean insertedParent, BeanPropertyAssocMany> many, EntityBean parentBean, PersistRequestBean> request) {
this.insertedParent = insertedParent;
@@ -613,7 +586,6 @@ public final class DefaultPersister implements Persister {
this.t = request.getTransaction();
this.statelessUpdate = request.isStatelessUpdate();
this.deleteMissingChildren = request.isDeleteMissingChildren();
- this.updateNullProperties = request.isUpdateNullProperties();
}
private SaveManyPropRequest(BeanPropertyAssocMany> many, EntityBean parentBean, SpiTransaction t) {
@@ -624,7 +596,6 @@ public final class DefaultPersister implements Persister {
this.cascade = true;
this.statelessUpdate = false;
this.deleteMissingChildren = false;
- this.updateNullProperties = false;
}
public boolean isSaveIntersection() {
@@ -646,10 +617,6 @@ public final class DefaultPersister implements Persister {
private boolean isDeleteMissingChildren() {
return deleteMissingChildren;
}
-
- private boolean isUpdateNullProperties() {
- return updateNullProperties;
- }
private boolean isInsertedParent() {
return insertedParent;
@@ -680,7 +647,7 @@ public final class DefaultPersister implements Persister {
boolean saveIntersectionFromThisDirection = saveMany.isSaveIntersection();
if (saveMany.isCascade()) {
// Need explicit Cascade to save the beans on other side
- saveAssocManyDetails(saveMany, false, saveMany.isUpdateNullProperties());
+ saveAssocManyDetails(saveMany, false);
}
// for ManyToMany save the 'relationship' via inserts/deletes
// into/from the intersection table
@@ -690,7 +657,7 @@ public final class DefaultPersister implements Persister {
}
} else {
if (saveMany.isCascade()) {
- saveAssocManyDetails(saveMany, saveMany.isDeleteMissingChildren(), saveMany.isUpdateNullProperties());
+ saveAssocManyDetails(saveMany, saveMany.isDeleteMissingChildren());
}
if (saveMany.isModifyListenMode()) {
removeAssocManyPrivateOwned(saveMany);
@@ -731,7 +698,7 @@ public final class DefaultPersister implements Persister {
/**
* Save the details from a OneToMany collection.
*/
- private void saveAssocManyDetails(SaveManyPropRequest saveMany, boolean deleteMissingChildren, boolean updateNullProperties) {
+ private void saveAssocManyDetails(SaveManyPropRequest saveMany, boolean deleteMissingChildren) {
BeanPropertyAssocMany> prop = saveMany.getMany();
@@ -747,12 +714,12 @@ public final class DefaultPersister implements Persister {
return;
}
+ BeanDescriptor> targetDescriptor = prop.getTargetDescriptor();
if (saveMany.isInsertedParent()) {
// performance optimisation for large collections
- prop.getTargetDescriptor().preAllocateIds(collection.size());
+ targetDescriptor.preAllocateIds(collection.size());
}
- BeanDescriptor> targetDescriptor = prop.getTargetDescriptor();
ArrayList