mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
merge of develop-v4
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -46,6 +47,11 @@ public interface BeanState {
|
||||
*/
|
||||
public Set<String> getChangedProps();
|
||||
|
||||
/**
|
||||
* Return a map of the updated properties and their new and old values.
|
||||
*/
|
||||
public Map<String,ValuePair> getDirtyValues();
|
||||
|
||||
/**
|
||||
* Return true if the bean is readOnly.
|
||||
* <p>
|
||||
@@ -69,16 +75,6 @@ public interface BeanState {
|
||||
*/
|
||||
public void removePropertyChangeListener(PropertyChangeListener listener);
|
||||
|
||||
/**
|
||||
* Advanced - Used to programmatically build a reference object.
|
||||
* <p>
|
||||
* You can create a new EntityBean (
|
||||
* {@link EbeanServer#createEntityBean(Class)}, set its Id property and then
|
||||
* call this setReference() method.
|
||||
* </p>
|
||||
*/
|
||||
public void setReference();
|
||||
|
||||
/**
|
||||
* Advanced - Used to programmatically build a partially or fully loaded
|
||||
* entity bean. First create an entity bean via
|
||||
@@ -90,5 +86,5 @@ public interface BeanState {
|
||||
* the properties that where loaded or null for a fully loaded entity
|
||||
* bean.
|
||||
*/
|
||||
public void setLoaded(Set<String> loadedProperties);
|
||||
public void setLoaded();
|
||||
}
|
||||
@@ -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.
|
||||
* <p>
|
||||
@@ -496,29 +504,6 @@ public final class Ebean {
|
||||
serverMgr.getPrimaryServer().update(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force an update using the bean explicitly stating the properties to update.
|
||||
* <p>
|
||||
* If you don't specify explicit properties to use in the update then the
|
||||
* non-null properties are included in the update.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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)}.
|
||||
* </p>
|
||||
*
|
||||
* @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<String> updateProps) {
|
||||
serverMgr.getPrimaryServer().update(bean, updateProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from an Iterator.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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)}.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
*
|
||||
* 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);
|
||||
*
|
||||
* </pre>
|
||||
*/
|
||||
public void update(Object bean, Set<String> updateProps);
|
||||
|
||||
/**
|
||||
* Force an update of the specified properties of the bean with an explicit
|
||||
* transaction.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
* <p>
|
||||
* 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)}.
|
||||
* </p>
|
||||
*/
|
||||
public void update(Object bean, Set<String> 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<String> 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.
|
||||
|
||||
@@ -244,14 +244,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the number of rows after which the fetching should continue in a
|
||||
* background thread.
|
||||
*
|
||||
* @see Query#setBackgroundFetchAfter(int)
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the name of the property which values become the key of a map.
|
||||
*
|
||||
@@ -259,15 +251,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}.
|
||||
* Set a QueryListener for bean by bean processing.
|
||||
*
|
||||
* @see Query#setListener(QueryListener)
|
||||
* @deprecated Migrate to {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set to true to use the query for executing this query.
|
||||
*
|
||||
|
||||
@@ -663,36 +663,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
* <p>
|
||||
* Set a listener to process the query on a row by row basis.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use this when you want to process a large query and do not want to hold the
|
||||
* entire query result in memory.
|
||||
* </p>
|
||||
* <p>
|
||||
* It this case the rows are not loaded into the persistence context and
|
||||
* instead are processed by the query listener.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* QueryListener<Order> listener = ...;
|
||||
*
|
||||
* Query<Order> query = Ebean.createQuery(Order.class);
|
||||
*
|
||||
* // set the listener that will process each order one at a time
|
||||
* query.setListener(listener);
|
||||
*
|
||||
* // execute the query. Note that the returned
|
||||
* // list (emptyList) will be empty ...
|
||||
* List<Order> emtyList = query.findList();
|
||||
* </pre>
|
||||
* @deprecated Deprecated in favor of {@link #findIterate()} and {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public Query<T> setListener(QueryListener<T> queryListener);
|
||||
|
||||
/**
|
||||
* Set the Id value to query. This is used with findUnique().
|
||||
* <p>
|
||||
@@ -966,13 +936,6 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
public Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the rows after which fetching should continue in a background thread.
|
||||
*
|
||||
* @param backgroundFetchAfter
|
||||
*/
|
||||
public Query<T> setBackgroundFetchAfter(int backgroundFetchAfter);
|
||||
|
||||
/**
|
||||
* Set the property to use as keys for a map.
|
||||
* <p>
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* Deprecated, please migrate to using {@link #findIterate()} or {@link #findVisit(QueryResultVisitor)}
|
||||
* <p>
|
||||
* Provides a mechanism for processing a query one bean at a time.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is useful when the query will return a large number of results and you
|
||||
* want to process the beans one at a time rather than whole all of the beans in
|
||||
* memory at once.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* QueryListener<Order> listener = ...;
|
||||
*
|
||||
* Query<Order> query = Ebean.createQuery(Order.class);
|
||||
*
|
||||
* // set the listener that will process each order one at a time
|
||||
* query.setListener(listener);
|
||||
*
|
||||
* // execute the query. Note that the returned
|
||||
* // list will be empty ... so don't bother assigning it
|
||||
* query.findList();
|
||||
* </pre>
|
||||
*
|
||||
* @param <T>
|
||||
* the type of entity bean
|
||||
* @deprecated Please migrate to using {@link #findIterate()} or
|
||||
* {@link #findVisit(QueryResultVisitor)}
|
||||
*/
|
||||
public interface QueryListener<T> {
|
||||
|
||||
/**
|
||||
* Process the bean that has just been read.
|
||||
* <p>
|
||||
* This bean will not be added to the List Set or Map and nor will it be put
|
||||
* into the PersistenceContext. This is what makes this a good way to process
|
||||
* a large result set (which could normally use a lot of memory).
|
||||
* </p>
|
||||
*/
|
||||
public void process(T bean);
|
||||
}
|
||||
@@ -5,30 +5,46 @@ package com.avaje.ebean;
|
||||
*/
|
||||
public class ValuePair {
|
||||
|
||||
final Object value1;
|
||||
private final Object newValue;
|
||||
|
||||
final Object value2;
|
||||
private final Object oldValue;
|
||||
|
||||
public ValuePair(Object value1, Object value2) {
|
||||
this.value1 = value1;
|
||||
this.value2 = value2;
|
||||
public ValuePair(Object newValue, Object oldValue) {
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first value.
|
||||
* Return the new value.
|
||||
*/
|
||||
public Object getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the old value.
|
||||
*/
|
||||
public Object getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue1() {
|
||||
return value1;
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the second value.
|
||||
* Return the old value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue2() {
|
||||
return value2;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value1 + "," + value2;
|
||||
return newValue + "," + oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,5 @@ public enum ConcurrencyMode {
|
||||
/**
|
||||
* Use a version column.
|
||||
*/
|
||||
VERSION,
|
||||
|
||||
/**
|
||||
* Use all the columns (except Lobs).
|
||||
*/
|
||||
ALL
|
||||
VERSION
|
||||
}
|
||||
|
||||
@@ -3,11 +3,8 @@ package com.avaje.ebean.bean;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
/**
|
||||
* Lazy loading capable Maps, Lists and Sets.
|
||||
@@ -34,10 +31,16 @@ public interface BeanCollection<E> extends Serializable {
|
||||
ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the collection is empty and untouched. Used to detect if a
|
||||
* collection was 'cleared' deliberately or just un-initialised.
|
||||
*/
|
||||
public boolean isEmptyAndUntouched();
|
||||
|
||||
/**
|
||||
* Return the bean that owns this collection.
|
||||
*/
|
||||
public Object getOwnerBean();
|
||||
public EntityBean getOwnerBean();
|
||||
|
||||
/**
|
||||
* Return the bean property name this collection represents.
|
||||
@@ -75,30 +78,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
*/
|
||||
public void setFilterMany(ExpressionList<?> filterMany);
|
||||
|
||||
/**
|
||||
* Set when this collection is being loaded via a background thread.
|
||||
* <p>
|
||||
* Refer to {@link Query#setBackgroundFetchAfter(int)}
|
||||
* </p>
|
||||
*/
|
||||
public void setBackgroundFetch(Future<Integer> future);
|
||||
|
||||
/**
|
||||
* Wait for the fetch to complete with a given timeout.
|
||||
* <p>
|
||||
* Refer to {@link Query#setBackgroundFetchAfter(int)}
|
||||
* </p>
|
||||
*/
|
||||
public void backgroundFetchWait(long wait, TimeUnit timeUnit);
|
||||
|
||||
/**
|
||||
* Wait for the fetch to complete.
|
||||
* <p>
|
||||
* Refer to {@link Query#setBackgroundFetchAfter(int)}
|
||||
* </p>
|
||||
*/
|
||||
public void backgroundFetchWait();
|
||||
|
||||
/**
|
||||
* Set a listener to be notified when the BeanCollection is first touched.
|
||||
*/
|
||||
@@ -174,18 +153,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
*/
|
||||
public void setHasMoreRows(boolean hasMoreRows);
|
||||
|
||||
/**
|
||||
* Returns true if the fetch has finished. False if the fetch is continuing in
|
||||
* a background thread.
|
||||
*/
|
||||
public boolean isFinishedFetch();
|
||||
|
||||
/**
|
||||
* Set to true when a fetch has finished. Used when a fetch continues in the
|
||||
* background.
|
||||
*/
|
||||
public void setFinishedFetch(boolean finishedFetch);
|
||||
|
||||
/**
|
||||
* return true if there are real rows held. Return false is this is using
|
||||
* Deferred fetch to lazy load the rows and the rows have not yet been
|
||||
|
||||
@@ -12,5 +12,5 @@ public interface BeanCollectionAdd {
|
||||
/**
|
||||
* Add a loaded bean to the collection.
|
||||
*/
|
||||
public void addBean(Object bean);
|
||||
public void addBean(EntityBean bean);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,10 @@ import java.io.Serializable;
|
||||
*/
|
||||
public interface EntityBean extends Serializable {
|
||||
|
||||
public String[] _ebean_getPropertyNames();
|
||||
|
||||
public String _ebean_getPropertyName(int pos);
|
||||
|
||||
/**
|
||||
* Return the enhancement marker value.
|
||||
* <p>
|
||||
@@ -79,31 +83,19 @@ public interface EntityBean extends Serializable {
|
||||
*/
|
||||
public Object _ebean_createCopy();
|
||||
|
||||
/**
|
||||
* Return the fields in their index order.
|
||||
*/
|
||||
public String[] _ebean_getFieldNames();
|
||||
|
||||
/**
|
||||
* Set the value of a field of an entity bean of this type.
|
||||
* <p>
|
||||
* Note that using this method bypasses any interception that otherwise occurs
|
||||
* on entity beans. That means lazy loading and oldValues creation.
|
||||
* </p>
|
||||
*
|
||||
* @param fieldIndex
|
||||
* the index of the field
|
||||
* @param entityBean
|
||||
* the entityBean of this type to modify
|
||||
* @param value
|
||||
* the value to set
|
||||
*/
|
||||
public void _ebean_setField(int fieldIndex, Object entityBean, Object value);
|
||||
public void _ebean_setField(int fieldIndex, Object value);
|
||||
|
||||
/**
|
||||
* Set the field value with interception.
|
||||
*/
|
||||
public void _ebean_setFieldIntercept(int fieldIndex, Object entityBean, Object value);
|
||||
public void _ebean_setFieldIntercept(int fieldIndex, Object value);
|
||||
|
||||
/**
|
||||
* Return the value of a field from an entity bean of this type.
|
||||
@@ -111,17 +103,12 @@ public interface EntityBean extends Serializable {
|
||||
* Note that using this method bypasses any interception that otherwise occurs
|
||||
* on entity beans. That means lazy loading.
|
||||
* </p>
|
||||
*
|
||||
* @param fieldIndex
|
||||
* the index of the field
|
||||
* @param entityBean
|
||||
* the entityBean to get the value from
|
||||
*/
|
||||
public Object _ebean_getField(int fieldIndex, Object entityBean);
|
||||
public Object _ebean_getField(int fieldIndex);
|
||||
|
||||
/**
|
||||
* Return the field value with interception.
|
||||
*/
|
||||
public Object _ebean_getFieldIntercept(int fieldIndex, Object entityBean);
|
||||
public Object _ebean_getFieldIntercept(int fieldIndex);
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,6 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
@@ -12,7 +10,6 @@ import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
|
||||
/**
|
||||
* Base class for List Set and Map implementations of BeanCollection.
|
||||
@@ -38,25 +35,16 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
protected transient BeanCollectionTouched beanCollectionTouched;
|
||||
|
||||
protected transient Future<Integer> fetchFuture;
|
||||
|
||||
/**
|
||||
* The owning bean (used for lazy fetch).
|
||||
*/
|
||||
protected final Object ownerBean;
|
||||
protected final EntityBean ownerBean;
|
||||
|
||||
/**
|
||||
* The name of this property in the owning bean (used for lazy fetch).
|
||||
*/
|
||||
protected final String propertyName;
|
||||
|
||||
/**
|
||||
* Can be false when a background thread is used to continue the fetch the
|
||||
* rows. It will set this to true when it is finished. If no background thread
|
||||
* is used then this should already be true.
|
||||
*/
|
||||
protected boolean finishedFetch = true;
|
||||
|
||||
/**
|
||||
* Flag set to true if rows are limited by firstRow maxRows and more rows
|
||||
* exist. For use by client to enable 'next' for paging.
|
||||
@@ -70,6 +58,12 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
protected boolean modifyRemoveListening;
|
||||
protected boolean modifyListening;
|
||||
|
||||
/**
|
||||
* Flag used to tell if empty collections have been cleared etc or just
|
||||
* uninitialised.
|
||||
*/
|
||||
protected boolean touched;
|
||||
|
||||
/**
|
||||
* Constructor not non-lazy loading collection.
|
||||
*/
|
||||
@@ -81,19 +75,15 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
/**
|
||||
* Used to create deferred fetch proxy.
|
||||
*/
|
||||
public AbstractBeanCollection(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
|
||||
public AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
this.loader = loader;
|
||||
this.ebeanServerName = loader.getName();
|
||||
this.ownerBean = ownerBean;
|
||||
this.propertyName = propertyName;
|
||||
|
||||
if (ownerBean instanceof EntityBean) {
|
||||
EntityBeanIntercept ebi = ((EntityBean) ownerBean)._ebean_getIntercept();
|
||||
this.readOnly = ebi.isReadOnly();
|
||||
}
|
||||
this.readOnly = ownerBean._ebean_getIntercept().isReadOnly();
|
||||
}
|
||||
|
||||
public Object getOwnerBean() {
|
||||
public EntityBean getOwnerBean() {
|
||||
return ownerBean;
|
||||
}
|
||||
|
||||
@@ -128,7 +118,14 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
checkEmptyLazyLoad();
|
||||
}
|
||||
|
||||
protected void touched() {
|
||||
/**
|
||||
* Set touched. If setFlag is false then typically an isEmpty() call and still
|
||||
* considering that to be untouched.
|
||||
*/
|
||||
protected void touched(boolean setFlag) {
|
||||
if (setFlag) {
|
||||
touched = true;
|
||||
}
|
||||
if (beanCollectionTouched != null) {
|
||||
// only call this once
|
||||
beanCollectionTouched.notifyTouched(this);
|
||||
@@ -174,46 +171,6 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.hasMoreRows = hasMoreRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the fetch has finished. False if the fetch is continuing in
|
||||
* a background thread.
|
||||
*/
|
||||
public boolean isFinishedFetch() {
|
||||
return finishedFetch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true when a fetch has finished. Used when a fetch continues in the
|
||||
* background.
|
||||
*/
|
||||
public void setFinishedFetch(boolean finishedFetch) {
|
||||
this.finishedFetch = finishedFetch;
|
||||
}
|
||||
|
||||
public void setBackgroundFetch(Future<Integer> fetchFuture) {
|
||||
this.fetchFuture = fetchFuture;
|
||||
}
|
||||
|
||||
public void backgroundFetchWait(long wait, TimeUnit timeUnit) {
|
||||
if (fetchFuture != null) {
|
||||
try {
|
||||
fetchFuture.get(wait, timeUnit);
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void backgroundFetchWait() {
|
||||
if (fetchFuture != null) {
|
||||
try {
|
||||
fetchFuture.get();
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkReadOnly() {
|
||||
if (readOnly) {
|
||||
String msg = "This collection is in ReadOnly mode";
|
||||
|
||||
@@ -10,13 +10,15 @@ import java.util.ListIterator;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* List capable of lazy loading.
|
||||
*/
|
||||
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>,
|
||||
BeanCollectionAdd {
|
||||
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The underlying List implementation.
|
||||
*/
|
||||
@@ -40,12 +42,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
/**
|
||||
* Used to create deferred fetch proxy.
|
||||
*/
|
||||
public BeanList(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
|
||||
public BeanList(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmptyAndUntouched() {
|
||||
return !touched && (list == null || list.isEmpty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addBean(Object bean) {
|
||||
public void addBean(EntityBean bean) {
|
||||
list.add((E) bean);
|
||||
}
|
||||
|
||||
@@ -75,16 +82,24 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
list = new ArrayList<E>();
|
||||
}
|
||||
}
|
||||
touched();
|
||||
touched(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAsUntouched() {
|
||||
init(false);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
init(true);
|
||||
}
|
||||
|
||||
private void init(boolean setTouched) {
|
||||
synchronized (this) {
|
||||
if (list == null) {
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
touched();
|
||||
touched(setTouched);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +272,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
init();
|
||||
initAsUntouched();
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,15 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Map capable of lazy loading.
|
||||
*/
|
||||
public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Map<K, E> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The underlying map implementation.
|
||||
*/
|
||||
@@ -33,9 +36,13 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
this(new LinkedHashMap<K, E>());
|
||||
}
|
||||
|
||||
public BeanMap(BeanCollectionLoader ebeanServer, Object ownerBean, String propertyName) {
|
||||
public BeanMap(BeanCollectionLoader ebeanServer, EntityBean ownerBean, String propertyName) {
|
||||
super(ebeanServer, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
public boolean isEmptyAndUntouched() {
|
||||
return !touched && (map == null || map.isEmpty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void internalPut(Object key, Object bean) {
|
||||
@@ -83,16 +90,24 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
map = new LinkedHashMap<K, E>();
|
||||
}
|
||||
}
|
||||
touched();
|
||||
touched(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAsUntouched() {
|
||||
init(false);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
init(true);
|
||||
}
|
||||
|
||||
private void init(boolean setTouched) {
|
||||
synchronized (this) {
|
||||
if (map == null) {
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
touched();
|
||||
touched(setTouched);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +224,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
init();
|
||||
initAsUntouched();
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,15 @@ import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Set capable of lazy loading.
|
||||
*/
|
||||
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>, BeanCollectionAdd {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The underlying Set implementation.
|
||||
*/
|
||||
@@ -33,12 +36,16 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
this(new LinkedHashSet<E>());
|
||||
}
|
||||
|
||||
public BeanSet(BeanCollectionLoader loader, Object ownerBean, String propertyName) {
|
||||
public BeanSet(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
public boolean isEmptyAndUntouched() {
|
||||
return !touched && (set == null || set.isEmpty());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addBean(Object bean) {
|
||||
public void addBean(EntityBean bean) {
|
||||
set.add((E) bean);
|
||||
}
|
||||
|
||||
@@ -83,16 +90,24 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
set = new LinkedHashSet<E>();
|
||||
}
|
||||
}
|
||||
touched();
|
||||
touched(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAsUntouched() {
|
||||
init(false);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
init(true);
|
||||
}
|
||||
|
||||
private void init(boolean setTouched) {
|
||||
synchronized (this) {
|
||||
if (set == null) {
|
||||
lazyLoadCollection(true);
|
||||
}
|
||||
touched();
|
||||
touched(setTouched);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +232,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
init();
|
||||
initAsUntouched();
|
||||
return set.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.avaje.ebean.event;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
|
||||
/**
|
||||
* Listens for committed bean events.
|
||||
* <p>
|
||||
@@ -31,8 +33,9 @@ import java.util.Set;
|
||||
* </p>
|
||||
* <p>
|
||||
* A BeanPersistListener is either found automatically via class path search or
|
||||
* can be added programmatically via ServerConfiguration.addEntity().
|
||||
* can be added programmatically via {@link ServerConfig#add(BeanPersistListener)}.
|
||||
* </p>
|
||||
* @see ServerConfig#add(BeanPersistListener)
|
||||
*/
|
||||
public interface BeanPersistListener<T> {
|
||||
|
||||
@@ -52,7 +55,7 @@ public interface BeanPersistListener<T> {
|
||||
* @param bean
|
||||
* The bean that was updated.
|
||||
* @param updatedProperties
|
||||
* the properties on the bean that where updated
|
||||
* The properties that were modified by this update.
|
||||
*/
|
||||
public boolean updated(T bean, Set<String> updatedProperties);
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package com.avaje.ebean.event;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
|
||||
/**
|
||||
* Holds the information available for a bean persist (insert, update or
|
||||
@@ -41,12 +43,8 @@ public interface BeanPersistRequest<T> {
|
||||
public T getBean();
|
||||
|
||||
/**
|
||||
* Returns a bean containing the original values prior to the bean being
|
||||
* modified.
|
||||
* <p>
|
||||
* This is for updates only.
|
||||
* </p>
|
||||
* Returns a map of the properties that have changed and their new and old values.
|
||||
*/
|
||||
public T getOldValues();
|
||||
public Map<String,ValuePair> getUpdatedValues();
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* @param <T>
|
||||
* the entity bean type
|
||||
*/
|
||||
@@ -129,13 +126,6 @@ public interface CsvReader<T> {
|
||||
*/
|
||||
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.
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -509,12 +508,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public String getMapKey();
|
||||
|
||||
/**
|
||||
* Return the number of rows after which fetching should occur in a
|
||||
* background thread.
|
||||
*/
|
||||
public int getBackgroundFetchAfter();
|
||||
|
||||
/**
|
||||
* Return the maximum number of rows to return in the query.
|
||||
*/
|
||||
@@ -545,19 +538,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
public Object getId();
|
||||
|
||||
/**
|
||||
* Return the queryListener.
|
||||
*/
|
||||
public QueryListener<T> getListener();
|
||||
|
||||
/**
|
||||
* Return true if this query should use its own transaction.
|
||||
* <p>
|
||||
* This is true for background fetching and when using QueryListener.
|
||||
* </p>
|
||||
*/
|
||||
public boolean createOwnTransaction();
|
||||
|
||||
/**
|
||||
* Set the generated sql for debug purposes.
|
||||
*
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.annotation.ConcurrencyMode;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.DmlHandler;
|
||||
import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
|
||||
|
||||
@@ -21,20 +21,20 @@ import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
|
||||
*/
|
||||
public interface SpiUpdatePlan {
|
||||
|
||||
/**
|
||||
* Return true if the set clause has no columns.
|
||||
* <p>
|
||||
* Can occur when the only columns updated have a updatable=false in their
|
||||
* deployment.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isEmptySetClause();
|
||||
/**
|
||||
* Return true if the set clause has no columns.
|
||||
* <p>
|
||||
* Can occur when the only columns updated have a updatable=false in their
|
||||
* deployment.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isEmptySetClause();
|
||||
|
||||
/**
|
||||
* Bind given the request and bean. The bean could be the oldValues bean
|
||||
* when binding a update or delete where clause with ALL concurrency mode.
|
||||
*/
|
||||
public void bindSet(DmlHandler bind, Object bean) throws SQLException;
|
||||
public void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* Return the time this plan was created.
|
||||
@@ -66,10 +66,10 @@ public interface SpiUpdatePlan {
|
||||
*/
|
||||
public Bindable getSet();
|
||||
|
||||
/**
|
||||
* Return the properties that where changed and should be included in the
|
||||
* update statement.
|
||||
*/
|
||||
public Set<String> getProperties();
|
||||
// /**
|
||||
// * Return the properties that where changed and should be included in the
|
||||
// * update statement.
|
||||
// */
|
||||
// public Set<String> getProperties();
|
||||
|
||||
}
|
||||
@@ -86,9 +86,9 @@ public class StatisticsNodeUsage implements Serializable {
|
||||
}
|
||||
|
||||
if ((modified || queryTuningAddVersion) && desc != null) {
|
||||
BeanProperty[] versionProps = desc.propertiesVersion();
|
||||
if (versionProps.length > 0) {
|
||||
pathProps.addToPath(path, versionProps[0].getName());
|
||||
BeanProperty versionProp = desc.getVersionProperty();
|
||||
if (versionProp != null) {
|
||||
pathProps.addToPath(path, versionProp.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,102 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Data held in the bean cache for cached beans.
|
||||
*/
|
||||
public class CachedBeanData {
|
||||
|
||||
private final Object sharableBean;
|
||||
private final Set<String> loadedProperties;
|
||||
private final Object[] data;
|
||||
private final int naturalKeyUpdate;
|
||||
|
||||
public CachedBeanData(Object sharableBean, Set<String> loadedProperties, Object[] data, int naturalKeyUpdate) {
|
||||
this.sharableBean = sharableBean;
|
||||
this.loadedProperties= loadedProperties;
|
||||
this.data = data;
|
||||
this.naturalKeyUpdate = naturalKeyUpdate;
|
||||
}
|
||||
|
||||
public Object getSharableBean() {
|
||||
return sharableBean;
|
||||
}
|
||||
private final long whenCreated;
|
||||
private final Object sharableBean;
|
||||
private final boolean[] loaded;
|
||||
private final Object[] data;
|
||||
|
||||
private final boolean naturalKeyUpdate;
|
||||
private final Object naturalKey;
|
||||
private final Object oldNaturalKey;
|
||||
|
||||
public boolean isNaturalKeyUpdate() {
|
||||
return naturalKeyUpdate > -1;
|
||||
}
|
||||
|
||||
public Object getNaturalKey() {
|
||||
return data[naturalKeyUpdate];
|
||||
}
|
||||
public CachedBeanData(Object sharableBean, boolean[] loaded, Object[] data, Object naturalKey, Object oldNaturalKey) {
|
||||
this.whenCreated = System.currentTimeMillis();
|
||||
this.sharableBean = sharableBean;
|
||||
this.loaded = loaded;
|
||||
this.data = data;
|
||||
this.naturalKeyUpdate = naturalKey != null;
|
||||
this.naturalKey = (naturalKey != null) ? naturalKey : oldNaturalKey;
|
||||
this.oldNaturalKey = oldNaturalKey;
|
||||
}
|
||||
|
||||
public boolean containsProperty(String propName) {
|
||||
return loadedProperties == null || loadedProperties.contains(propName);
|
||||
public String toString() {
|
||||
return Arrays.toString(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of the property data.
|
||||
*/
|
||||
public Object[] copyData() {
|
||||
Object[] dest = new Object[data.length];
|
||||
System.arraycopy(data, 0, dest, 0, data.length);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of the loaded status for the properties.
|
||||
*/
|
||||
public boolean[] copyLoaded() {
|
||||
boolean[] dest = new boolean[data.length];
|
||||
for (int i = 0; i < dest.length; i++) {
|
||||
dest[i] = loaded[i];
|
||||
}
|
||||
|
||||
public Object getData(int i){
|
||||
return data[i];
|
||||
}
|
||||
|
||||
public Set<String> getLoadedProperties() {
|
||||
return loadedProperties;
|
||||
}
|
||||
|
||||
public Object[] copyData() {
|
||||
Object[] dest = new Object[data.length];
|
||||
System.arraycopy(data, 0, dest, 0, data.length);
|
||||
return dest;
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return when the cached data was created.
|
||||
*/
|
||||
public long getWhenCreated() {
|
||||
return whenCreated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a sharable (immutable read only) bean.
|
||||
*/
|
||||
public Object getSharableBean() {
|
||||
return sharableBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this data requires an update to the natural key cache.
|
||||
*/
|
||||
public boolean isNaturalKeyUpdate() {
|
||||
return naturalKeyUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new/current natural key value.
|
||||
*/
|
||||
public Object getNaturalKey() {
|
||||
return naturalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the old natural key (its entry should be removed).
|
||||
*/
|
||||
public Object getOldNaturalKey() {
|
||||
return oldNaturalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data for the specific property.
|
||||
*/
|
||||
public Object getData(int i) {
|
||||
return data[i];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is contained in this data.
|
||||
*/
|
||||
public boolean isLoaded(int i) {
|
||||
return loaded[i];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+49
-85
@@ -1,8 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -10,94 +7,61 @@ import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
public class CachedBeanDataFromBean {
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
private final Object bean;
|
||||
private final EntityBeanIntercept ebi;
|
||||
|
||||
private final Set<String> loadedProps;
|
||||
private final Set<String> extractProps;
|
||||
|
||||
public static CachedBeanData extract(BeanDescriptor<?> desc, Object bean){
|
||||
if (bean instanceof EntityBean){
|
||||
return new CachedBeanDataFromBean(desc, bean, ((EntityBean)bean)._ebean_getIntercept()).extract();
|
||||
|
||||
} else {
|
||||
return new CachedBeanDataFromBean(desc, bean, null).extract();
|
||||
}
|
||||
}
|
||||
|
||||
public static CachedBeanData extract(BeanDescriptor<?> desc, Object bean, EntityBeanIntercept ebi){
|
||||
return new CachedBeanDataFromBean(desc, bean, ebi).extract();
|
||||
}
|
||||
|
||||
private CachedBeanDataFromBean(BeanDescriptor<?> desc, Object bean, EntityBeanIntercept ebi) {
|
||||
this.desc = desc;
|
||||
this.bean = bean;
|
||||
this.ebi = ebi;
|
||||
if (ebi != null){
|
||||
this.loadedProps = ebi.getLoadedProps();
|
||||
this.extractProps = (loadedProps == null) ? null : new HashSet<String>();
|
||||
} else {
|
||||
this.extractProps = new HashSet<String>();
|
||||
this.loadedProps = null;
|
||||
}
|
||||
}
|
||||
|
||||
private CachedBeanData extract(){
|
||||
public static CachedBeanData extract(BeanDescriptor<?> desc, EntityBean bean) {
|
||||
|
||||
BeanProperty[] props = desc.propertiesNonMany();
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
|
||||
Object[] data = new Object[desc.getPropertyCount()];
|
||||
boolean[] loaded = new boolean[desc.getPropertyCount()];
|
||||
|
||||
BeanProperty[] props = desc.propertiesNonMany();
|
||||
|
||||
Object[] data = new Object[props.length];
|
||||
|
||||
int naturalKeyUpdate = -1;
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
BeanProperty prop = props[i];
|
||||
if (includeNonManyProperty(prop.getName())){
|
||||
|
||||
data[i] = prop.getCacheDataValue(bean);
|
||||
if (prop.isNaturalKey()) {
|
||||
naturalKeyUpdate = i;
|
||||
}
|
||||
if (ebi != null){
|
||||
if (extractProps != null){
|
||||
extractProps.add(prop.getName());
|
||||
}
|
||||
} else if (data[i] != null){
|
||||
if (extractProps != null){
|
||||
extractProps.add(prop.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
Object naturalKey = null;
|
||||
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
BeanProperty prop = props[i];
|
||||
if (ebi.isLoadedProperty(prop.getPropertyIndex())) {
|
||||
int propertyIndex = prop.getPropertyIndex();
|
||||
data[propertyIndex] = prop.getCacheDataValue(bean);
|
||||
loaded[propertyIndex] = true;
|
||||
if (prop.isNaturalKey()) {
|
||||
naturalKey = prop.getValue(bean);
|
||||
}
|
||||
|
||||
Object sharableBean = null;
|
||||
if (desc.isCacheSharableBeans() && ebi != null && loadedProps == null){
|
||||
if (ebi.isReadOnly()){
|
||||
sharableBean = bean;
|
||||
} else {
|
||||
// create a readOnly sharable instance by copying the data
|
||||
sharableBean = desc.createBean();
|
||||
BeanProperty[] propertiesId = desc.propertiesId();
|
||||
for (int i = 0; i < propertiesId.length; i++) {
|
||||
Object v = propertiesId[i].getValue(bean);
|
||||
propertiesId[i].setValue(sharableBean, v);
|
||||
}
|
||||
BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
|
||||
for (int i = 0; i < propertiesNonTransient.length; i++) {
|
||||
Object v = propertiesNonTransient[i].getValue(bean);
|
||||
propertiesNonTransient[i].setValue(sharableBean, v);
|
||||
}
|
||||
EntityBeanIntercept ebi = ((EntityBean)sharableBean)._ebean_intercept();
|
||||
ebi.setReadOnly(true);
|
||||
ebi.setLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
return new CachedBeanData(sharableBean, extractProps, data, naturalKeyUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
EntityBean sharableBean = createSharableBean(desc, bean, ebi);
|
||||
|
||||
return new CachedBeanData(sharableBean, loaded, data, naturalKey, null);
|
||||
}
|
||||
|
||||
private static EntityBean createSharableBean(BeanDescriptor<?> desc, EntityBean bean, EntityBeanIntercept beanEbi) {
|
||||
|
||||
private boolean includeNonManyProperty(String name) {
|
||||
return loadedProps == null || loadedProps.contains(name);
|
||||
if (!desc.isCacheSharableBeans() || !beanEbi.isFullyLoadedBean()) {
|
||||
return null;
|
||||
}
|
||||
if (beanEbi.isReadOnly()) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
// create a readOnly sharable instance by copying the data
|
||||
EntityBean sharableBean = desc.createBean();
|
||||
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++) {
|
||||
Object v = propertiesNonTransient[i].getValue(bean);
|
||||
propertiesNonTransient[i].setValue(sharableBean, v);
|
||||
}
|
||||
EntityBeanIntercept intercept = sharableBean._ebean_intercept();
|
||||
intercept.setReadOnly(true);
|
||||
intercept.setLoaded();
|
||||
return sharableBean;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+23
-99
@@ -1,8 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -11,107 +8,34 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
|
||||
public class CachedBeanDataToBean {
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
private final Object bean;
|
||||
private final EntityBeanIntercept ebi;
|
||||
private final CachedBeanData cacheBeandata;
|
||||
private final Set<String> cacheLoadedProperties;
|
||||
private final Set<String> loadedProps;
|
||||
|
||||
private final Set<String> excludeProps;
|
||||
private final Object oldValuesBean;
|
||||
private final boolean readOnly;
|
||||
|
||||
public static void load(BeanDescriptor<?> desc, Object bean, CachedBeanData cacheBeandata) {
|
||||
if (bean instanceof EntityBean){
|
||||
load(desc, bean, ((EntityBean)bean)._ebean_getIntercept(), cacheBeandata);
|
||||
} else {
|
||||
load(desc, bean, null, cacheBeandata);
|
||||
}
|
||||
}
|
||||
|
||||
public static void load(BeanDescriptor<?> desc, Object bean, EntityBeanIntercept ebi, CachedBeanData cacheBeandata) {
|
||||
new CachedBeanDataToBean(desc, bean, ebi, cacheBeandata).load();
|
||||
}
|
||||
public static boolean load(BeanDescriptor<?> desc, EntityBean bean, CachedBeanData cacheBeanData) {
|
||||
|
||||
private CachedBeanDataToBean(BeanDescriptor<?> desc, Object bean, EntityBeanIntercept ebi, CachedBeanData cacheBeandata) {
|
||||
this.desc = desc;
|
||||
this.bean = bean;
|
||||
this.ebi = ebi;
|
||||
this.cacheBeandata = cacheBeandata;
|
||||
this.cacheLoadedProperties = cacheBeandata.getLoadedProperties();
|
||||
this.loadedProps = (cacheLoadedProperties == null) ? null : new HashSet<String>();
|
||||
|
||||
if (ebi != null){
|
||||
this.excludeProps = ebi.getLoadedProps();
|
||||
this.oldValuesBean = ebi.getOldValues();
|
||||
this.readOnly = ebi.isReadOnly();
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
|
||||
BeanProperty[] props = desc.propertiesNonMany();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
|
||||
BeanProperty prop = props[i];
|
||||
int propertyIndex = prop.getPropertyIndex();
|
||||
if (cacheBeanData.isLoaded(propertyIndex)) {
|
||||
if (ebi.isLoadedProperty(propertyIndex)) {
|
||||
// already loaded (lazy load on partially loaded bean)
|
||||
} else {
|
||||
this.excludeProps = null;
|
||||
this.oldValuesBean = null;
|
||||
this.readOnly = false;
|
||||
Object data = cacheBeanData.getData(propertyIndex);
|
||||
prop.setCacheDataValue(bean, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean load(){
|
||||
|
||||
BeanProperty[] propertiesNonTransient = desc.propertiesNonMany();
|
||||
for (int i = 0; i < propertiesNonTransient.length; i++) {
|
||||
BeanProperty prop = propertiesNonTransient[i];
|
||||
if (includeNonManyProperty(prop.getName())){
|
||||
Object data = cacheBeandata.getData(i);
|
||||
prop.setCacheDataValue(bean, data, oldValuesBean, readOnly);
|
||||
}
|
||||
}
|
||||
BeanPropertyAssocMany<?>[] manys = desc.propertiesMany();
|
||||
for (int i = 0; i < manys.length; i++) {
|
||||
BeanPropertyAssocMany<?> prop = manys[i];
|
||||
if (includeManyProperty(prop.getName())){
|
||||
// set a lazy loading proxy
|
||||
prop.createReference(bean);
|
||||
}
|
||||
}
|
||||
|
||||
if (ebi != null){
|
||||
if (loadedProps == null){
|
||||
ebi.setLoadedProps(null);
|
||||
} else {
|
||||
HashSet<String> mergeProps = new HashSet<String>();
|
||||
if (excludeProps != null) {
|
||||
mergeProps.addAll(excludeProps);
|
||||
}
|
||||
mergeProps.addAll(loadedProps);
|
||||
ebi.setLoadedProps(mergeProps);
|
||||
}
|
||||
ebi.setLoadedLazy();
|
||||
}
|
||||
|
||||
return true;
|
||||
BeanPropertyAssocMany<?>[] manys = desc.propertiesMany();
|
||||
for (int i = 0; i < manys.length; i++) {
|
||||
manys[i].createReferenceIfNull(bean);
|
||||
}
|
||||
|
||||
private boolean includeManyProperty(String name) {
|
||||
if (excludeProps != null && excludeProps.contains(name)){
|
||||
// ignore this property (partial bean lazy loading)
|
||||
return false;
|
||||
}
|
||||
if (loadedProps != null){
|
||||
loadedProps.add(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean includeNonManyProperty(String name) {
|
||||
if (excludeProps != null && excludeProps.contains(name)){
|
||||
// ignore this property (partial bean lazy loading)
|
||||
return false;
|
||||
}
|
||||
if (cacheLoadedProperties != null && !cacheLoadedProperties.contains(name)){
|
||||
return false;
|
||||
}
|
||||
if (loadedProps != null){
|
||||
loadedProps.add(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ebi.setLoadedLazy();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+32
-37
@@ -1,49 +1,44 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
* Create a new CachedBeanData based on the existing CachedBeanData and the updated bean.
|
||||
*/
|
||||
public class CachedBeanDataUpdate {
|
||||
|
||||
public static CachedBeanData update(BeanDescriptor<?> desc, CachedBeanData data, PersistRequestBean<?> updateRequest){
|
||||
/**
|
||||
* Create a new CachedBeanData based on the existing CachedBeanData and the updated bean.
|
||||
*/
|
||||
public static CachedBeanData update(BeanDescriptor<?> desc, CachedBeanData existingData, EntityBean updateBean) {
|
||||
|
||||
|
||||
Set<String> loadedProperties = data.getLoadedProperties();
|
||||
Object[] copyOfData = data.copyData();
|
||||
|
||||
Object updateBean = updateRequest.getBean();
|
||||
Set<String> updatedProperties = updateRequest.getUpdatedProperties();
|
||||
|
||||
int naturalKeyUpdate = -1;
|
||||
boolean mergeProperties = false;
|
||||
BeanProperty[] props = desc.propertiesNonMany();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (updatedProperties.contains(props[i].getName())){
|
||||
if (props[i].isNaturalKey()){
|
||||
naturalKeyUpdate = i;
|
||||
}
|
||||
copyOfData[i] = props[i].getCacheDataValue(updateBean);
|
||||
if (loadedProperties != null && !mergeProperties && !loadedProperties.contains(props[i].getName())){
|
||||
mergeProperties = true;
|
||||
}
|
||||
}
|
||||
// take a copy of the raw data and loaded status
|
||||
boolean[] copyLoaded = existingData.copyLoaded();
|
||||
Object[] copyData = existingData.copyData();
|
||||
|
||||
EntityBeanIntercept ebi = updateBean._ebean_getIntercept();
|
||||
|
||||
Object newNaturalKey = null;
|
||||
Object oldNaturalKey = existingData.getNaturalKey();
|
||||
|
||||
BeanProperty[] props = desc.propertiesNonMany();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
// check if the properties was in the update
|
||||
int propertyIndex = props[i].getPropertyIndex();
|
||||
if (ebi.isLoadedProperty(propertyIndex)) {
|
||||
if (props[i].isNaturalKey()) {
|
||||
newNaturalKey = updateBean._ebean_getField(propertyIndex);
|
||||
}
|
||||
|
||||
if (mergeProperties){
|
||||
HashSet<String> mergeProps = new HashSet<String>();
|
||||
mergeProps.addAll(loadedProperties);
|
||||
mergeProps.addAll(updatedProperties);
|
||||
loadedProperties = mergeProps;
|
||||
}
|
||||
|
||||
return new CachedBeanData(null, loadedProperties, copyOfData, naturalKeyUpdate);
|
||||
|
||||
// set the cache safe value for the property and mark it as loaded
|
||||
copyData[propertyIndex] = props[i].getCacheDataValue(updateBean);
|
||||
copyLoaded[propertyIndex] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return new CachedBeanData(null, copyLoaded, copyData, newNaturalKey, oldNaturalKey);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,16 +2,26 @@ package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The cached data for O2M and M2M relationships.
|
||||
* <p>
|
||||
* This is effectively just the Id values for each of the beans in the collection.
|
||||
* </p>
|
||||
*/
|
||||
public class CachedManyIds {
|
||||
|
||||
private final List<Object> idList;
|
||||
|
||||
public CachedManyIds(List<Object> idList) {
|
||||
this.idList = idList;
|
||||
}
|
||||
private final List<Object> idList;
|
||||
|
||||
public List<Object> getIdList() {
|
||||
return idList;
|
||||
}
|
||||
public CachedManyIds(List<Object> idList) {
|
||||
this.idList = idList;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return idList.toString();
|
||||
}
|
||||
|
||||
public List<Object> getIdList() {
|
||||
return idList;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import javax.persistence.Table;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.CompoundType;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
@@ -52,6 +51,7 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
private ArrayList<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
|
||||
|
||||
|
||||
private ArrayList<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
|
||||
private ArrayList<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
|
||||
|
||||
@@ -311,7 +311,7 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
} else if (isEntity(cls)) {
|
||||
entityList.add(cls);
|
||||
|
||||
|
||||
} else if (isInterestingInterface(cls)) {
|
||||
return true;
|
||||
|
||||
|
||||
@@ -4,87 +4,126 @@ package com.avaje.ebeaninternal.server.core;
|
||||
* Options for controlling cache behaviour for a given type.
|
||||
*/
|
||||
public class CacheOptions {
|
||||
|
||||
private boolean useCache;
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
private String naturalKey;
|
||||
|
||||
private String warmingQuery;
|
||||
|
||||
/**
|
||||
* Construct with options.
|
||||
*/
|
||||
public CacheOptions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this should use a cache for lazy loading.
|
||||
*/
|
||||
public boolean isUseCache() {
|
||||
return useCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use the bean cache for the associated type.
|
||||
*/
|
||||
public void setUseCache(boolean useCache) {
|
||||
this.useCache = useCache;
|
||||
private boolean useCache;
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
private String naturalKey;
|
||||
|
||||
private String warmingQuery;
|
||||
|
||||
private int maxIdleSecs;
|
||||
|
||||
private long maxSecsToLive;
|
||||
|
||||
/**
|
||||
* Construct with options.
|
||||
*/
|
||||
public CacheOptions() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this should use a cache for lazy loading.
|
||||
*/
|
||||
public boolean isUseCache() {
|
||||
return useCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to use the bean cache for the associated type.
|
||||
*/
|
||||
public void setUseCache(boolean useCache) {
|
||||
this.useCache = useCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the readOnly default setting.
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set read Only default setting.
|
||||
*/
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query used to warm the cache.
|
||||
*/
|
||||
public String getWarmingQuery() {
|
||||
return warmingQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache warming query.
|
||||
*/
|
||||
public void setWarmingQuery(String warmingQuery) {
|
||||
this.warmingQuery = warmingQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a natural key is set.
|
||||
*/
|
||||
public boolean isUseNaturalKeyCache() {
|
||||
return naturalKey != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the natural key property.
|
||||
*/
|
||||
public String getNaturalKey() {
|
||||
return naturalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the natural key property.
|
||||
*/
|
||||
public void setNaturalKey(String naturalKey) {
|
||||
if (naturalKey == null || naturalKey.length() == 0) {
|
||||
naturalKey = null;
|
||||
} else {
|
||||
this.naturalKey = naturalKey.trim();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max age of entries in seconds.
|
||||
*/
|
||||
public long getMaxSecsToLive() {
|
||||
return maxSecsToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the readOnly default setting.
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
/**
|
||||
* Set the max age of entries in seconds.
|
||||
*/
|
||||
public void setMaxSecsToLive(long maxSecsToLive) {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set read Only default setting.
|
||||
*/
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
/**
|
||||
* Set the max idle seconds.
|
||||
*/
|
||||
public void setMaxIdleSecs(int maxIdleSecs) {
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query used to warm the cache.
|
||||
*/
|
||||
public String getWarmingQuery() {
|
||||
return warmingQuery;
|
||||
}
|
||||
/**
|
||||
* Return the max idle seconds.
|
||||
*/
|
||||
public int getMaxIdleSecs() {
|
||||
return maxIdleSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache warming query.
|
||||
*/
|
||||
public void setWarmingQuery(String warmingQuery) {
|
||||
this.warmingQuery = warmingQuery;
|
||||
}
|
||||
/**
|
||||
* Return true if the entry exceeds the maxIdleSecs or maxSecsToLive.
|
||||
*/
|
||||
public boolean isTooOldInMillis(long ageMillis) {
|
||||
long secs = ageMillis / 1000;
|
||||
return (maxIdleSecs > 0 && secs > maxIdleSecs) || (maxSecsToLive > 0 && secs > maxSecsToLive);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if a natural key is set.
|
||||
*/
|
||||
public boolean isUseNaturalKeyCache() {
|
||||
return naturalKey != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the natural key property.
|
||||
*/
|
||||
public String getNaturalKey() {
|
||||
return naturalKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the natural key property.
|
||||
*/
|
||||
public void setNaturalKey(String naturalKey) {
|
||||
if (naturalKey == null || naturalKey.length() == 0){
|
||||
naturalKey = null;
|
||||
} else {
|
||||
this.naturalKey = naturalKey.trim();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class DefaultBeanLoader {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
public void refreshMany(Object parentBean, String propertyName) {
|
||||
public void refreshMany(EntityBean parentBean, String propertyName) {
|
||||
refreshMany(parentBean, propertyName, null);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class DefaultBeanLoader {
|
||||
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
BeanCollection<?> bc = batch.get(i);
|
||||
Object ownerBean = bc.getOwnerBean();
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
Object id = many.getParentId(ownerBean);
|
||||
idList.add(id);
|
||||
}
|
||||
@@ -136,14 +136,14 @@ public class DefaultBeanLoader {
|
||||
}
|
||||
} else if (loadRequest.isLoadCache()) {
|
||||
Object parentId = desc.getId(bc.getOwnerBean());
|
||||
desc.cachePutMany(many, bc, parentId);
|
||||
desc.cacheManyPropPut(many, bc, parentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
|
||||
Object parentBean = bc.getOwnerBean();
|
||||
EntityBean parentBean = bc.getOwnerBean();
|
||||
String propertyName = bc.getPropertyName();
|
||||
|
||||
//ObjectGraphNode node = ctx == null ? null : ctx.getObjectGraphNode();
|
||||
@@ -151,11 +151,11 @@ public class DefaultBeanLoader {
|
||||
loadManyInternal(parentBean, propertyName, null, false, null, onlyIds);
|
||||
}
|
||||
|
||||
public void refreshMany(Object parentBean, String propertyName, Transaction t) {
|
||||
public void refreshMany(EntityBean parentBean, String propertyName, Transaction t) {
|
||||
loadManyInternal(parentBean, propertyName, t, true, null, false);
|
||||
}
|
||||
|
||||
private void loadManyInternal(Object parentBean, String propertyName, Transaction t, boolean refresh, ObjectGraphNode node, boolean onlyIds) {
|
||||
private void loadManyInternal(EntityBean parentBean, String propertyName, Transaction t, boolean refresh, ObjectGraphNode node, boolean onlyIds) {
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) parentBean)._ebean_getIntercept();
|
||||
PersistenceContext pc = ebi.getPersistenceContext();
|
||||
@@ -179,13 +179,13 @@ public class DefaultBeanLoader {
|
||||
pc.put(parentId, parentBean);
|
||||
}
|
||||
|
||||
boolean useManyIdCache = beanCollection != null && parentDesc.cacheIsUseManyId();
|
||||
boolean useManyIdCache = beanCollection != null && parentDesc.isManyPropCaching();
|
||||
if (useManyIdCache) {
|
||||
Boolean readOnly = null;
|
||||
if (ebi != null && ebi.isReadOnly()) {
|
||||
readOnly = Boolean.TRUE;
|
||||
}
|
||||
if (parentDesc.cacheLoadMany(many, beanCollection, parentId, readOnly)) {
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentId, readOnly)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ public class DefaultBeanLoader {
|
||||
logger.debug("BeanCollection after load was empty. Owner:" + beanCollection.getOwnerBean());
|
||||
}
|
||||
} else if (useManyIdCache) {
|
||||
parentDesc.cachePutMany(many, beanCollection, parentId);
|
||||
parentDesc.cacheManyPropPut(many, beanCollection, parentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,7 +267,7 @@ public class DefaultBeanLoader {
|
||||
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
EntityBeanIntercept ebi = batch.get(i);
|
||||
Object bean = ebi.getOwner();
|
||||
EntityBean bean = ebi.getOwner();
|
||||
Object id = desc.getId(bean);
|
||||
idList.add(id);
|
||||
}
|
||||
@@ -290,17 +290,6 @@ public class DefaultBeanLoader {
|
||||
|
||||
PersistenceContext persistenceContext = ctx.getPersistenceContext();
|
||||
|
||||
// query the database
|
||||
for (int i = 0; i < ebis.length; i++) {
|
||||
Object parentBean = ebis[i].getParentBean();
|
||||
if (parentBean != null) {
|
||||
// Special case for OneToOne
|
||||
BeanDescriptor<?> parentDesc = server.getBeanDescriptor(parentBean.getClass());
|
||||
Object parentId = parentDesc.getId(parentBean);
|
||||
persistenceContext.put(parentId, parentBean);
|
||||
}
|
||||
}
|
||||
|
||||
SpiQuery<?> query = (SpiQuery<?>) server.createQuery(beanType);
|
||||
|
||||
query.setMode(Mode.LAZYLOAD_BEAN);
|
||||
@@ -323,20 +312,18 @@ public class DefaultBeanLoader {
|
||||
|
||||
if (loadRequest.isLoadCache()) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
desc.cachePutBeanData(list.get(i));
|
||||
desc.cacheBeanPutData((EntityBean)list.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public void refresh(Object bean) {
|
||||
public void refresh(EntityBean bean) {
|
||||
refreshBeanInternal(bean, SpiQuery.Mode.REFRESH_BEAN);
|
||||
}
|
||||
|
||||
@@ -344,7 +331,7 @@ public class DefaultBeanLoader {
|
||||
refreshBeanInternal(ebi.getOwner(), SpiQuery.Mode.LAZYLOAD_BEAN);
|
||||
}
|
||||
|
||||
private void refreshBeanInternal(Object bean, SpiQuery.Mode mode) {
|
||||
private void refreshBeanInternal(EntityBean bean, SpiQuery.Mode mode) {
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();;
|
||||
PersistenceContext pc = ebi.getPersistenceContext();
|
||||
@@ -364,7 +351,7 @@ public class DefaultBeanLoader {
|
||||
if (ebi != null) {
|
||||
if (SpiQuery.Mode.LAZYLOAD_BEAN.equals(mode) && desc.isBeanCaching()) {
|
||||
// lazy loading and the bean cache is active
|
||||
if (desc.loadFromCache(bean, ebi, id)) {
|
||||
if (desc.cacheBeanLoad((EntityBean)bean, ebi, id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -375,14 +362,6 @@ public class DefaultBeanLoader {
|
||||
|
||||
SpiQuery<?> query = (SpiQuery<?>) server.createQuery(desc.getBeanType());
|
||||
if (ebi != null) {
|
||||
Object parentBean = ebi.getParentBean();
|
||||
if (parentBean != null) {
|
||||
// Special case for OneToOne
|
||||
BeanDescriptor<?> parentDesc = server.getBeanDescriptor(parentBean.getClass());
|
||||
Object parentId = parentDesc.getId(parentBean);
|
||||
pc.putIfAbsent(parentId, parentBean);
|
||||
}
|
||||
|
||||
query.setLazyLoadProperty(ebi.getLazyLoadProperty());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.BeanState;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
|
||||
@@ -13,9 +14,9 @@ import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
*/
|
||||
public class DefaultBeanState implements BeanState {
|
||||
|
||||
final EntityBean entityBean;
|
||||
private final EntityBean entityBean;
|
||||
|
||||
final EntityBeanIntercept intercept;
|
||||
private final EntityBeanIntercept intercept;
|
||||
|
||||
public DefaultBeanState(EntityBean entityBean){
|
||||
this.entityBean = entityBean;
|
||||
@@ -39,14 +40,16 @@ public class DefaultBeanState implements BeanState {
|
||||
}
|
||||
|
||||
public Set<String> getLoadedProps() {
|
||||
Set<String> props = intercept.getLoadedProps();
|
||||
return props == null ? null : Collections.unmodifiableSet(props);
|
||||
return intercept.getLoadedPropertyNames();
|
||||
}
|
||||
|
||||
public Set<String> getChangedProps() {
|
||||
Set<String> props = intercept.getChangedProps();
|
||||
return props == null ? null : Collections.unmodifiableSet(props);
|
||||
}
|
||||
return intercept.getDirtyPropertyNames();
|
||||
}
|
||||
|
||||
public Map<String,ValuePair> getDirtyValues() {
|
||||
return intercept.getDirtyValues();
|
||||
}
|
||||
|
||||
public boolean isReadOnly() {
|
||||
return intercept.isReadOnly();
|
||||
@@ -64,14 +67,8 @@ public class DefaultBeanState implements BeanState {
|
||||
entityBean.removePropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
public void setLoaded(Set<String> loadedProperties) {
|
||||
intercept.setLoadedProps(loadedProperties);
|
||||
intercept.setLoaded();
|
||||
public void setLoaded() {
|
||||
intercept.setLoaded();
|
||||
}
|
||||
|
||||
public void setReference() {
|
||||
intercept.setReference();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -121,6 +121,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultServer.class);
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
|
||||
private static final String AVAJE_EBEAN = Ebean.class.getName().substring(0, 15);
|
||||
|
||||
private final String serverName;
|
||||
|
||||
private final DatabasePlatform databasePlatform;
|
||||
@@ -138,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.
|
||||
@@ -247,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"));
|
||||
|
||||
@@ -311,10 +313,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
return defaultDeleteMissingChildren;
|
||||
}
|
||||
|
||||
public boolean isDefaultUpdateNullProperties() {
|
||||
return defaultUpdateNullProperties;
|
||||
}
|
||||
|
||||
public int getLazyLoadBatchSize() {
|
||||
return lazyLoadBatchSize;
|
||||
}
|
||||
@@ -522,12 +520,12 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
public void refreshMany(Object parentBean, String propertyName, Transaction t) {
|
||||
|
||||
beanLoader.refreshMany(parentBean, propertyName, t);
|
||||
beanLoader.refreshMany(checkEntityBean(parentBean), propertyName, t);
|
||||
}
|
||||
|
||||
public void refreshMany(Object parentBean, String propertyName) {
|
||||
|
||||
beanLoader.refreshMany(parentBean, propertyName);
|
||||
beanLoader.refreshMany(checkEntityBean(parentBean), propertyName);
|
||||
}
|
||||
|
||||
public void loadMany(LoadManyRequest loadRequest) {
|
||||
@@ -542,7 +540,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
public void refresh(Object bean) {
|
||||
|
||||
beanLoader.refresh(bean);
|
||||
beanLoader.refresh(checkEntityBean(bean));
|
||||
}
|
||||
|
||||
public void loadBean(LoadBeanRequest loadRequest) {
|
||||
@@ -652,29 +650,21 @@ 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<T> query = createQuery(type);
|
||||
query.select(idNames).setId(id);
|
||||
query.select(idProp.getName()).setId(id);
|
||||
|
||||
ref = query.findUnique();
|
||||
|
||||
} else {
|
||||
// use the default reference options
|
||||
ref = desc.createReference(null, id, null);
|
||||
ref = desc.createReference(null, id);
|
||||
}
|
||||
|
||||
if (ctx != null && (ref instanceof EntityBean)) {
|
||||
@@ -1133,7 +1123,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
if (Mode.LAZYLOAD_MANY.equals(query.getMode())) {
|
||||
allowOneManyFetch = false;
|
||||
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect() && query.getBackgroundFetchAfter() == 0) {
|
||||
} else if (query.hasMaxRowsOrFirstRow() && !query.isRawSql() && !query.isSqlSelect()) {
|
||||
// convert ALL fetch joins to Many's to be query joins
|
||||
// so that limit offset type SQL clauses work
|
||||
allowOneManyFetch = false;
|
||||
@@ -1190,23 +1180,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
|
||||
// Hit the L2 bean cache
|
||||
Object cachedBean = beanDescriptor.cacheGetBean(query.getId(), query.isReadOnly());
|
||||
if (cachedBean != null) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
|
||||
}
|
||||
context.put(query.getId(), cachedBean);
|
||||
|
||||
DLoadContext loadContext = new DLoadContext(this, beanDescriptor, query.isReadOnly(), query);
|
||||
loadContext.setPersistenceContext(context);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) cachedBean)._ebean_getIntercept();
|
||||
ebi.setPersistenceContext(context);
|
||||
loadContext.register(null, ebi);
|
||||
}
|
||||
|
||||
return (T) cachedBean;
|
||||
return beanDescriptor.cacheBeanGet(query, context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -1255,17 +1229,9 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
BeanDescriptor<T> desc = beanDescriptorManager.getBeanDescriptor(q.getBeanType());
|
||||
|
||||
if (desc.calculateUseNaturalKeyCache(q.isUseBeanCache())) {
|
||||
// check if it is a find by unique id
|
||||
NaturalKeyBindParam keyBindParam = q.getNaturalKeyBindParam();
|
||||
if (keyBindParam != null && desc.cacheIsNaturalKey(keyBindParam.getName())) {
|
||||
Object id2 = desc.cacheGetNaturalKeyId(keyBindParam.getValue());
|
||||
if (id2 != null) {
|
||||
SpiQuery<T> copy = q.copy();
|
||||
copy.convertWhereNaturalKeyToId(id2);
|
||||
return findId(copy, t);
|
||||
}
|
||||
}
|
||||
T bean = desc.cacheNaturalKeyLookup(q, (SpiTransaction)t);
|
||||
if (bean != null) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
// a query that is expected to return either 0 or 1 rows
|
||||
@@ -1273,9 +1239,10 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
|
||||
} else if (list.size() > 1) {
|
||||
String m = "Unique expecting 0 or 1 rows but got [" + list.size() + "]";
|
||||
throw new PersistenceException(m);
|
||||
throw new PersistenceException("Unique expecting 0 or 1 rows but got [" + list.size() + "]");
|
||||
|
||||
} else {
|
||||
return list.get(0);
|
||||
}
|
||||
@@ -1604,51 +1571,32 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
* Save the bean with an explicit transaction.
|
||||
*/
|
||||
public void save(Object bean, Transaction t) {
|
||||
if (bean == null) {
|
||||
throw new NullPointerException(Message.msg("bean.isnull"));
|
||||
}
|
||||
persister.save(bean, t);
|
||||
|
||||
persister.save(checkEntityBean(bean), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<String> 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<String> 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<String> updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties) {
|
||||
if (bean == null) {
|
||||
throw new NullPointerException(Message.msg("bean.isnull"));
|
||||
}
|
||||
persister.forceUpdate(bean, updateProps, t, deleteMissingChildren, updateNullProperties);
|
||||
public void update(Object bean, Transaction t, boolean deleteMissingChildren) {
|
||||
|
||||
persister.forceUpdate(checkEntityBean(bean), t, deleteMissingChildren);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1674,12 +1622,19 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
* </p>
|
||||
*/
|
||||
public void insert(Object bean, Transaction t) {
|
||||
persister.forceInsert(checkEntityBean(bean), t);
|
||||
}
|
||||
|
||||
private EntityBean checkEntityBean(Object bean) {
|
||||
if (bean == null) {
|
||||
throw new NullPointerException(Message.msg("bean.isnull"));
|
||||
}
|
||||
persister.forceInsert(bean, t);
|
||||
if (bean instanceof EntityBean == false) {
|
||||
throw new IllegalArgumentException("Was expecting an EntityBean but got a "+bean.getClass());
|
||||
}
|
||||
return (EntityBean)bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the associations (from the intersection table) of a ManyToMany given
|
||||
* the owner bean and the propertyName of the ManyToMany collection.
|
||||
@@ -1700,10 +1655,11 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
*/
|
||||
public int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t) {
|
||||
|
||||
EntityBean owner = checkEntityBean(ownerBean);
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
try {
|
||||
SpiTransaction trans = wrap.transaction;
|
||||
int rc = persister.deleteManyToManyAssociations(ownerBean, propertyName, trans);
|
||||
int rc = persister.deleteManyToManyAssociations(owner, propertyName, trans);
|
||||
wrap.commitIfCreated();
|
||||
return rc;
|
||||
|
||||
@@ -1727,11 +1683,12 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
*/
|
||||
public void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t) {
|
||||
|
||||
EntityBean owner = checkEntityBean(ownerBean);
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
try {
|
||||
SpiTransaction trans = wrap.transaction;
|
||||
|
||||
persister.saveManyToManyAssociations(ownerBean, propertyName, trans);
|
||||
persister.saveManyToManyAssociations(owner, propertyName, trans);
|
||||
|
||||
wrap.commitIfCreated();
|
||||
|
||||
@@ -1747,21 +1704,12 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
public void saveAssociation(Object ownerBean, String propertyName, Transaction t) {
|
||||
|
||||
if (ownerBean instanceof EntityBean) {
|
||||
Set<String> loadedProps = ((EntityBean) ownerBean)._ebean_getIntercept().getLoadedProps();
|
||||
if (loadedProps != null && !loadedProps.contains(propertyName)) {
|
||||
// skip as property is not actually loaded in this partially
|
||||
// loaded bean
|
||||
logger.debug("Skip saveAssociation as property " + propertyName + " is not loaded");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EntityBean owner = checkEntityBean(ownerBean);
|
||||
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
try {
|
||||
SpiTransaction trans = wrap.transaction;
|
||||
|
||||
persister.saveAssociation(ownerBean, propertyName, trans);
|
||||
persister.saveAssociation(owner, propertyName, trans);
|
||||
|
||||
wrap.commitIfCreated();
|
||||
|
||||
@@ -1797,7 +1745,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
SpiTransaction trans = wrap.transaction;
|
||||
int saveCount = 0;
|
||||
while (it.hasNext()) {
|
||||
Object bean = it.next();
|
||||
EntityBean bean = checkEntityBean(it.next());
|
||||
persister.save(bean, trans);
|
||||
saveCount++;
|
||||
}
|
||||
@@ -1861,10 +1809,8 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
* Delete the bean with the explicit transaction.
|
||||
*/
|
||||
public void delete(Object bean, Transaction t) {
|
||||
if (bean == null) {
|
||||
throw new NullPointerException(Message.msg("bean.isnull"));
|
||||
}
|
||||
persister.delete(bean, t);
|
||||
|
||||
persister.delete(checkEntityBean(bean), t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1892,7 +1838,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
SpiTransaction trans = wrap.transaction;
|
||||
int deleteCount = 0;
|
||||
while (it.hasNext()) {
|
||||
Object bean = it.next();
|
||||
EntityBean bean = checkEntityBean(it.next());
|
||||
persister.delete(bean, trans);
|
||||
deleteCount++;
|
||||
}
|
||||
@@ -1995,13 +1941,14 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
|
||||
public Object getBeanId(Object bean) {
|
||||
EntityBean eb = checkEntityBean(bean);
|
||||
BeanDescriptor<?> desc = getBeanDescriptor(bean.getClass());
|
||||
if (desc == null) {
|
||||
String m = bean.getClass().getName() + " is NOT an Entity Bean registered with this server?";
|
||||
throw new PersistenceException(m);
|
||||
}
|
||||
|
||||
return desc.getId(bean);
|
||||
return desc.getId(eb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2067,8 +2014,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
return transactionManager.createQueryTransaction();
|
||||
}
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
private static final String AVAJE_EBEAN = Ebean.class.getName().substring(0, 15);
|
||||
|
||||
/**
|
||||
* Create a CallStack object.
|
||||
|
||||
@@ -19,50 +19,55 @@ import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
public class DiffHelp {
|
||||
|
||||
|
||||
/**
|
||||
* Return a map of the differences between a and b.
|
||||
* <p>
|
||||
* A and B must be of the same type. B can be null, in which case the
|
||||
* 'OldValues' of a is used to compare with (as B).
|
||||
* </p>
|
||||
* <p>
|
||||
* This intentionally does not include as OneToMany or ManyToMany
|
||||
* properties.
|
||||
* </p>
|
||||
*/
|
||||
/**
|
||||
* Return a map of the differences between a and b.
|
||||
* <p>
|
||||
* A and B must be of the same type. B can be null, in which case the 'dirty
|
||||
* values' of a is returned.
|
||||
* </p>
|
||||
* <p>
|
||||
* This intentionally does not include as OneToMany or ManyToMany properties.
|
||||
* </p>
|
||||
*/
|
||||
public Map<String, ValuePair> diff(Object a, Object b, BeanDescriptor<?> desc) {
|
||||
|
||||
boolean oldValues = false;
|
||||
if (a instanceof EntityBean == false) {
|
||||
throw new IllegalArgumentException("First bean expected to be an enhanced EntityBean? bean:"+a);
|
||||
}
|
||||
|
||||
if (b != null) {
|
||||
if (b instanceof EntityBean == false) {
|
||||
throw new IllegalArgumentException("Second bean expected to be an enhanced EntityBean? bean:"+b);
|
||||
}
|
||||
if (!a.getClass().isAssignableFrom(b.getClass())) {
|
||||
throw new IllegalArgumentException("Second bean not assignable to the first bean?");
|
||||
}
|
||||
}
|
||||
|
||||
if (b == null) {
|
||||
// get the old values from a
|
||||
if (a instanceof EntityBean) {
|
||||
EntityBean eb = (EntityBean) a;
|
||||
b = eb._ebean_getIntercept().getOldValues();
|
||||
oldValues = true;
|
||||
}
|
||||
return ((EntityBean) a)._ebean_getIntercept().getDirtyValues();
|
||||
}
|
||||
|
||||
Map<String, ValuePair> map = new LinkedHashMap<String, ValuePair>();
|
||||
|
||||
if (b == null) {
|
||||
return map;
|
||||
}
|
||||
Map<String, ValuePair> map = new LinkedHashMap<String, ValuePair>();
|
||||
diff(null, map, (EntityBean)a, (EntityBean)b, desc);
|
||||
return map;
|
||||
}
|
||||
|
||||
public void diff(String prefix, Map<String, ValuePair> map, EntityBean first, EntityBean sec, BeanDescriptor<?> desc) {
|
||||
|
||||
// check the simple properties
|
||||
BeanProperty[] base = desc.propertiesBaseScalar();
|
||||
for (int i = 0; i < base.length; i++) {
|
||||
|
||||
Object aval = base[i].getValue(a);
|
||||
Object bval = base[i].getValue(b);
|
||||
Object aval = base[i].getValue(first);
|
||||
Object bval = base[i].getValue(sec);
|
||||
if (!ValueUtil.areEqual(aval, bval)) {
|
||||
map.put(base[i].getName(), new ValuePair(aval, bval));
|
||||
String propName = (prefix == null) ? base[i].getName() : prefix + base[i].getName();
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
}
|
||||
}
|
||||
|
||||
diffAssocOne(a, b, desc, map);
|
||||
diffEmbedded(a, b, desc, map, oldValues);
|
||||
|
||||
return map;
|
||||
diffAssocOne(prefix, first, sec, desc, map);
|
||||
diffEmbedded(prefix, first, sec, desc, map);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,40 +77,24 @@ public class DiffHelp {
|
||||
* determined to be different as is added to the map.
|
||||
* </p>
|
||||
*/
|
||||
private void diffEmbedded(Object a, Object b, BeanDescriptor<?> desc, Map<String, ValuePair> map,
|
||||
boolean oldValues) {
|
||||
private void diffEmbedded(String prefix, EntityBean a, EntityBean b, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] emb = desc.propertiesEmbedded();
|
||||
|
||||
for (int i = 0; i < emb.length; i++) {
|
||||
Object aval = emb[i].getValue(a);
|
||||
Object bval = emb[i].getValue(b);
|
||||
if (oldValues) {
|
||||
bval = ((EntityBean) bval)._ebean_getIntercept().getOldValues();
|
||||
if (bval == null) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
EntityBean aval = (EntityBean)emb[i].getValue(a);
|
||||
EntityBean bval = (EntityBean)emb[i].getValue(b);
|
||||
|
||||
if (!isBothNull(aval, bval)) {
|
||||
String propName = (prefix == null) ? emb[i].getName() : prefix + emb[i].getName();
|
||||
if (isDiffNull(aval, bval)) {
|
||||
// one of the embedded beans is null
|
||||
map.put(emb[i].getName(), new ValuePair(aval, bval));
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
|
||||
} else {
|
||||
// if ANY of the properties in an Embedded bean is
|
||||
// different, treat the whole bean as being different
|
||||
BeanProperty[] props = emb[i].getProperties();
|
||||
for (int j = 0; j < props.length; j++) {
|
||||
Object aEmbPropVal = props[j].getValue(aval);
|
||||
Object bEmbPropVal = props[j].getValue(bval);
|
||||
if (!ValueUtil.areEqual(aEmbPropVal, bEmbPropVal)) {
|
||||
|
||||
// if one prop is different put the
|
||||
// embedded bean in the map
|
||||
map.put(emb[i].getName(), new ValuePair(aval, bval));
|
||||
}
|
||||
}
|
||||
// recursively diff into the embedded bean
|
||||
BeanDescriptor<?> embDesc = emb[i].getTargetDescriptor();
|
||||
diff(emb[i].getName()+".", map, aval, bval, embDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +104,7 @@ public class DiffHelp {
|
||||
* If the properties are different by null OR if the id value is different,
|
||||
* then add the Assoc One bean to the map.
|
||||
*/
|
||||
private void diffAssocOne(Object a, Object b, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
private void diffAssocOne(String prefix, EntityBean a, EntityBean b, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] ones = desc.propertiesOne();
|
||||
|
||||
@@ -124,20 +113,21 @@ public class DiffHelp {
|
||||
Object bval = ones[i].getValue(b);
|
||||
|
||||
if (!isBothNull(aval, bval)) {
|
||||
String propName = (prefix == null) ? ones[i].getName() : prefix + ones[i].getName();
|
||||
if (isDiffNull(aval, bval)) {
|
||||
// one of them is/was null
|
||||
map.put(ones[i].getName(), new ValuePair(aval, bval));
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
|
||||
} else {
|
||||
// check to see if the Id properties
|
||||
// are different
|
||||
BeanDescriptor<?> oneDesc = ones[i].getTargetDescriptor();
|
||||
Object aOneId = oneDesc.getId(aval);
|
||||
Object bOneId = oneDesc.getId(bval);
|
||||
Object aOneId = oneDesc.getId((EntityBean)aval);
|
||||
Object bOneId = oneDesc.getId((EntityBean)bval);
|
||||
|
||||
if (!ValueUtil.areEqual(aOneId, bOneId)) {
|
||||
// the ids are different
|
||||
map.put(ones[i].getName(), new ValuePair(aval, bval));
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ public class InternalConfiguration {
|
||||
this.transactionManager = new TransactionManager(clusterManager, backgroundExecutor,
|
||||
serverConfig, beanDescriptorManager, this.getBootupClasses());
|
||||
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder, backgroundExecutor);
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder);
|
||||
|
||||
ExternalTransactionManager externalTransactionManager = serverConfig.getExternalTransactionManager();
|
||||
if (externalTransactionManager == null && serverConfig.isUseJtaTransactionManager()) {
|
||||
|
||||
@@ -55,13 +55,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private HashQueryPlan queryPlanHash;
|
||||
|
||||
/**
|
||||
* Flag set if background fetching taking place. In this case the transaction
|
||||
* is rolled back by the background fetching thread. Background fetching
|
||||
* always takes place in its own transaction.
|
||||
*/
|
||||
private boolean backgroundFetching;
|
||||
|
||||
/**
|
||||
* Create the InternalQueryRequest.
|
||||
*/
|
||||
@@ -163,12 +156,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
@Override
|
||||
public void initTransIfRequired() {
|
||||
// first check if the query requires its own transaction
|
||||
if (query.createOwnTransaction()) {
|
||||
// using background fetch or query listener etc
|
||||
transaction = ebeanServer.createQueryTransaction();
|
||||
createdTransaction = true;
|
||||
|
||||
} else if (transaction == null) {
|
||||
if (transaction == null) {
|
||||
// maybe a current one
|
||||
transaction = ebeanServer.getCurrentServerTransaction();
|
||||
if (transaction == null) {
|
||||
@@ -202,19 +190,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
* </p>
|
||||
*/
|
||||
public void endTransIfRequired() {
|
||||
if (createdTransaction && !backgroundFetching) {
|
||||
if (createdTransaction) {
|
||||
// we can rollback as readOnly transaction
|
||||
transaction.rollback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This query is using background fetching.
|
||||
*/
|
||||
public void setBackgroundFetching() {
|
||||
backgroundFetching = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a find by id (rather than List Set or Map).
|
||||
*/
|
||||
@@ -277,12 +258,11 @@ public final class OrmQueryRequest<T> 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);
|
||||
@@ -356,8 +336,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
cacheKey = query.queryHash();
|
||||
|
||||
// TODO: Sort out returning BeanCollection from L2 cache
|
||||
return null;
|
||||
return beanDescriptor.queryCacheGet(cacheKey);
|
||||
}
|
||||
|
||||
public void putToQueryCache(BeanCollection<T> queryResult) {
|
||||
|
||||
@@ -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,7 +31,7 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
|
||||
super(server, t);
|
||||
this.persistExecute = persistExecute;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute a the request or queue/batch it for later execution.
|
||||
*/
|
||||
@@ -90,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.
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.annotation.ConcurrencyMode;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
@@ -19,6 +22,7 @@ import com.avaje.ebeaninternal.api.TransactionEvent;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanManager;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.persist.BatchControl;
|
||||
import com.avaje.ebeaninternal.server.persist.PersistExecute;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
|
||||
@@ -41,6 +45,13 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
*/
|
||||
protected final BeanPersistController controller;
|
||||
|
||||
/**
|
||||
* The bean being persisted.
|
||||
*/
|
||||
protected final T bean;
|
||||
|
||||
protected final EntityBean entityBean;
|
||||
|
||||
/**
|
||||
* The associated intercept.
|
||||
*/
|
||||
@@ -51,25 +62,10 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
*/
|
||||
protected final Object parentBean;
|
||||
|
||||
protected final boolean isDirty;
|
||||
protected final boolean dirty;
|
||||
|
||||
/**
|
||||
* The bean being persisted.
|
||||
*/
|
||||
protected final T bean;
|
||||
|
||||
/**
|
||||
* Old values used for concurrency checking.
|
||||
*/
|
||||
protected T oldValues;
|
||||
|
||||
/**
|
||||
* The concurrency mode used for update or delete.
|
||||
*/
|
||||
protected ConcurrencyMode concurrencyMode;
|
||||
|
||||
protected final Set<String> loadedProps;
|
||||
|
||||
/**
|
||||
* The unique id used for logging summary.
|
||||
*/
|
||||
@@ -81,97 +77,82 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
protected Integer beanHash;
|
||||
protected Integer beanIdentityHash;
|
||||
|
||||
protected final Set<String> changedProps;
|
||||
|
||||
protected boolean notifyCache;
|
||||
|
||||
private boolean statelessUpdate;
|
||||
private boolean deleteMissingChildren;
|
||||
private boolean updateNullProperties;
|
||||
|
||||
private final Set<String> dirtyPropertyNames;
|
||||
|
||||
/**
|
||||
* Flag used to detect when only many properties where updated via a cascade. Used to ensure
|
||||
* appropriate cache updates occur in that case.
|
||||
*/
|
||||
private boolean updatedManysOnly;
|
||||
|
||||
/**
|
||||
* Used for forced update of a bean.
|
||||
* Many properties that were cascade saved (and hence might need cache update later).
|
||||
*/
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, Set<String> updateProps, ConcurrencyMode concurrencyMode) {
|
||||
private List<BeanPropertyAssocMany<?>> updatedManys;
|
||||
|
||||
super(server, t, persistExecute);
|
||||
this.beanManager = mgr;
|
||||
this.beanDescriptor = mgr.getBeanDescriptor();
|
||||
this.beanPersistListener = beanDescriptor.getPersistListener();
|
||||
this.bean = bean;
|
||||
this.parentBean = parentBean;
|
||||
|
||||
this.controller = beanDescriptor.getPersistController();
|
||||
this.concurrencyMode = beanDescriptor.getConcurrencyMode();
|
||||
|
||||
this.concurrencyMode = concurrencyMode;
|
||||
this.loadedProps = updateProps;
|
||||
this.changedProps = updateProps;
|
||||
this.isDirty = true;
|
||||
this.oldValues = bean;
|
||||
if (bean instanceof EntityBean) {
|
||||
this.intercept = ((EntityBean) bean)._ebean_getIntercept();
|
||||
} else {
|
||||
this.intercept = null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr,
|
||||
SpiTransaction t, PersistExecute persistExecute) {
|
||||
SpiTransaction t, PersistExecute persistExecute, PersistRequest.Type type) {
|
||||
|
||||
super(server, t, persistExecute);
|
||||
this.entityBean = (EntityBean)bean;
|
||||
this.intercept = entityBean._ebean_getIntercept();
|
||||
this.beanManager = mgr;
|
||||
this.beanDescriptor = mgr.getBeanDescriptor();
|
||||
this.beanPersistListener = beanDescriptor.getPersistListener();
|
||||
|
||||
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();
|
||||
this.intercept = ((EntityBean) bean)._ebean_getIntercept();
|
||||
if (intercept.isReference()) {
|
||||
// allowed to 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();
|
||||
if (!isDirty) {
|
||||
this.changedProps = intercept.getChangedProps();
|
||||
} else {
|
||||
// merge changed properties on the bean with changed embedded beans
|
||||
Set<String> beanChangedProps = intercept.getChangedProps();
|
||||
Set<String> dirtyEmbedded = beanDescriptor.getDirtyEmbeddedProperties(bean);
|
||||
this.changedProps = mergeChangedProperties(beanChangedProps, dirtyEmbedded);
|
||||
}
|
||||
this.loadedProps = intercept.getLoadedProps();
|
||||
this.oldValues = (T) intercept.getOldValues();
|
||||
this.dirty = intercept.isDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge the changed properties for the bean and embedded beans.
|
||||
* Return true if this is an insert request.
|
||||
*/
|
||||
private Set<String> mergeChangedProperties(Set<String> beanChangedProps, Set<String> embChanged) {
|
||||
if (embChanged == null) {
|
||||
return beanChangedProps;
|
||||
} else if (beanChangedProps == null) {
|
||||
return embChanged;
|
||||
} else {
|
||||
beanChangedProps.addAll(embChanged);
|
||||
return beanChangedProps;
|
||||
}
|
||||
}
|
||||
public boolean isInsert() {
|
||||
return Type.INSERT == type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getLoadedProperties() {
|
||||
return intercept.getLoadedPropertyNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getUpdatedProperties() {
|
||||
return intercept.getDirtyPropertyNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ValuePair> getUpdatedValues() {
|
||||
return intercept.getDirtyValues();
|
||||
}
|
||||
|
||||
public boolean isNotify(TransactionEvent txnEvent) {
|
||||
this.notifyCache = beanDescriptor.isCacheNotify();
|
||||
return notifyCache || isNotifyPersistListener();
|
||||
}
|
||||
|
||||
public boolean isNotifyCache() {
|
||||
return notifyCache;
|
||||
}
|
||||
|
||||
public boolean isNotifyPersistListener() {
|
||||
return beanPersistListener != null;
|
||||
}
|
||||
@@ -183,10 +164,10 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
if (notifyCache) {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
beanDescriptor.cacheInsert(idValue, this);
|
||||
beanDescriptor.cacheHandleInsert(idValue, this);
|
||||
break;
|
||||
case UPDATE:
|
||||
beanDescriptor.cacheUpdate(idValue, this);
|
||||
beanDescriptor.cacheHandleUpdate(idValue, this);
|
||||
break;
|
||||
case DELETE:
|
||||
// Bean deleted from cache early via postDelete()
|
||||
@@ -199,7 +180,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
|
||||
public void addToPersistMap(BeanPersistIdMap beanPersistMap) {
|
||||
|
||||
beanPersistMap.add(beanDescriptor, type, idValue);
|
||||
beanPersistMap.add(beanDescriptor, type, idValue);
|
||||
}
|
||||
|
||||
public boolean notifyLocalPersistListener() {
|
||||
@@ -212,7 +193,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
return beanPersistListener.inserted(bean);
|
||||
|
||||
case UPDATE:
|
||||
return beanPersistListener.updated(bean, getUpdatedProperties());
|
||||
return beanPersistListener.updated(bean, dirtyPropertyNames);
|
||||
|
||||
case DELETE:
|
||||
return beanPersistListener.deleted(bean);
|
||||
@@ -229,7 +210,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
|
||||
/**
|
||||
* Return true if this bean has been already been persisted
|
||||
* (inserted/updated or deleted) in this transaction.
|
||||
* (inserted or updated) in this transaction.
|
||||
*/
|
||||
public boolean isRegisteredBean() {
|
||||
return transaction.isRegisteredBean(bean);
|
||||
@@ -247,7 +228,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
*/
|
||||
private Integer getBeanHash() {
|
||||
if (beanHash == null) {
|
||||
Object id = beanDescriptor.getId(bean);
|
||||
Object id = beanDescriptor.getId(entityBean);
|
||||
int hc = 31 * bean.getClass().getName().hashCode();
|
||||
if (id != null) {
|
||||
hc += id.hashCode();
|
||||
@@ -276,21 +257,6 @@ public class PersistRequestBean<T> 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();
|
||||
if (type == Type.DELETE || type == Type.UPDATE) {
|
||||
if (oldValues == null) {
|
||||
oldValues = bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BeanManager<T> getBeanManager() {
|
||||
return beanManager;
|
||||
}
|
||||
@@ -317,14 +283,6 @@ public class PersistRequestBean<T> 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.
|
||||
* <p>
|
||||
@@ -333,10 +291,9 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* that was probably created from JSON or XML.
|
||||
* </p>
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,7 +301,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* for EntityBeans that have not been modified.
|
||||
*/
|
||||
public boolean isDirty() {
|
||||
return isDirty;
|
||||
return dirty;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,20 +311,6 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
return concurrencyMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set loaded properties when generated values has added properties such as
|
||||
* created and updated timestamps.
|
||||
*/
|
||||
public void setLoadedProps(Set<String> additionalProps) {
|
||||
if (intercept != null) {
|
||||
intercept.setLoadedProps(additionalProps);
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getLoadedProperties() {
|
||||
return loadedProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the request. This is typically the bean class
|
||||
* name or the base table for MapBeans.
|
||||
@@ -387,25 +330,22 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
public EntityBean getEntityBean() {
|
||||
return entityBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id value for the bean.
|
||||
*/
|
||||
public Object getBeanId() {
|
||||
return beanDescriptor.getId(bean);
|
||||
return beanDescriptor.getId(entityBean);
|
||||
}
|
||||
|
||||
public BeanDelta createDeltaBean() {
|
||||
return new BeanDelta(beanDescriptor, getBeanId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the old values bean. This is used to perform optimistic concurrency
|
||||
* checking on updates and deletes.
|
||||
*/
|
||||
public T getOldValues() {
|
||||
return oldValues;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parent bean for cascading save with unidirectional
|
||||
* relationship.
|
||||
@@ -434,11 +374,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* bean).
|
||||
*/
|
||||
public boolean isLoadedProperty(BeanProperty prop) {
|
||||
if (loadedProps == null) {
|
||||
return true;
|
||||
} else {
|
||||
return loadedProps.contains(prop.getName());
|
||||
}
|
||||
return intercept.isLoadedProperty(prop.getPropertyIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -485,13 +421,8 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
*/
|
||||
public void setGeneratedKey(Object idValue) {
|
||||
if (idValue != null) {
|
||||
|
||||
// set back to the bean so that we can use the same bean later
|
||||
// for update [refer ebeanIntercept.setLoaded(true)].
|
||||
idValue = beanDescriptor.convertSetId(idValue, bean);
|
||||
|
||||
// remember it for logging summary
|
||||
this.idValue = idValue;
|
||||
this.idValue = beanDescriptor.convertSetId(idValue, entityBean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,7 +449,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
// Delete the bean from the PersistenceContent
|
||||
transaction.getPersistenceContext().clear(beanDescriptor.getBeanType(), idValue);
|
||||
// Delete from cache early even if transaction fails
|
||||
beanDescriptor.cacheDelete(idValue, this);
|
||||
beanDescriptor.cacheHandleDelete(idValue, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -597,18 +528,18 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* </p>
|
||||
*/
|
||||
public ConcurrencyMode determineConcurrencyMode() {
|
||||
if (loadedProps != null) {
|
||||
// 'partial bean' update/delete...
|
||||
if (concurrencyMode.equals(ConcurrencyMode.VERSION)) {
|
||||
// check the version property was loaded
|
||||
BeanProperty prop = beanDescriptor.firstVersionProperty();
|
||||
if (prop != null && loadedProps.contains(prop.getName())) {
|
||||
// OK to use version property
|
||||
} else {
|
||||
concurrencyMode = ConcurrencyMode.ALL;
|
||||
}
|
||||
|
||||
// 'partial bean' update/delete...
|
||||
if (concurrencyMode.equals(ConcurrencyMode.VERSION)) {
|
||||
// check the version property was loaded
|
||||
BeanProperty prop = beanDescriptor.getVersionProperty();
|
||||
if (prop != null && intercept.isLoadedProperty(prop.getPropertyIndex())) {
|
||||
// OK to use version property
|
||||
} else {
|
||||
concurrencyMode = ConcurrencyMode.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return concurrencyMode;
|
||||
}
|
||||
|
||||
@@ -619,7 +550,7 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* </p>
|
||||
*/
|
||||
public boolean isDynamicUpdateSql() {
|
||||
return beanDescriptor.isUpdateChangesOnly() || (loadedProps != null);
|
||||
return beanDescriptor.isUpdateChangesOnly() || !intercept.isFullyLoadedBean();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -630,37 +561,74 @@ public class PersistRequestBean<T> extends PersistRequest implements BeanPersist
|
||||
* </p>
|
||||
*/
|
||||
public GenerateDmlRequest createGenerateDmlRequest(boolean emptyStringAsNull) {
|
||||
if (beanDescriptor.isUpdateChangesOnly()) {
|
||||
return new GenerateDmlRequest(emptyStringAsNull, changedProps, loadedProps, oldValues);
|
||||
} else {
|
||||
return new GenerateDmlRequest(emptyStringAsNull, loadedProps, loadedProps, oldValues);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the updated properties. If this returns null then all the
|
||||
* properties on the bean where updated.
|
||||
*/
|
||||
public Set<String> getUpdatedProperties() {
|
||||
if (changedProps != null) {
|
||||
return changedProps;
|
||||
}
|
||||
return loadedProps;
|
||||
return new GenerateDmlRequest(emptyStringAsNull, intercept, beanDescriptor.isUpdateChangesOnly());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the property value has changed and if so include it in the
|
||||
* update.
|
||||
*/
|
||||
public boolean hasChanged(BeanProperty prop) {
|
||||
if (changedProps == null) {
|
||||
return false;
|
||||
}
|
||||
return changedProps.contains(prop.getName());
|
||||
public boolean isAddToUpdate(BeanProperty prop) {
|
||||
return intercept.isDirtyProperty(prop.getPropertyIndex());
|
||||
}
|
||||
|
||||
public List<DerivedRelationshipData> getDerivedRelationships() {
|
||||
return transaction.getDerivedRelationship(bean);
|
||||
public List<DerivedRelationshipData> getDerivedRelationships() {
|
||||
return transaction.getDerivedRelationship(bean);
|
||||
}
|
||||
|
||||
public void postInsert() {
|
||||
// mark all properties as loaded after an insert to support immediate update
|
||||
int len = intercept.getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
intercept.setLoadedProperty(i);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReference() {
|
||||
return beanDescriptor.isReference(intercept);
|
||||
}
|
||||
|
||||
/**
|
||||
* This many property has been cascade saved. Keep note of this and update the 'many property'
|
||||
* cache on post commit.
|
||||
*/
|
||||
public void addUpdatedManyProperty(BeanPropertyAssocMany<?> updatedAssocMany) {
|
||||
//if (notifyCache) {
|
||||
if (updatedManys == null) {
|
||||
updatedManys = new ArrayList<BeanPropertyAssocMany<?>>(5);
|
||||
}
|
||||
updatedManys.add(updatedAssocMany);
|
||||
//}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of cascade updated many properties (can be null).
|
||||
*/
|
||||
public List<BeanPropertyAssocMany<?>> getUpdatedManyCollections() {
|
||||
return updatedManys;
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference bean was saved. Check if any of its many properties where
|
||||
* cascade saved and hence we need to update related many property caches.
|
||||
*/
|
||||
public void checkUpdatedManysOnly() {
|
||||
if (!dirty && updatedManys != null) {
|
||||
// set the flag and register for post commit processing if there
|
||||
// is caching or registered listeners
|
||||
if (idValue == null) {
|
||||
this.idValue = beanDescriptor.getId(entityBean);
|
||||
}
|
||||
updatedManysOnly = true;
|
||||
addEvent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if only many properties where updated.
|
||||
*/
|
||||
public boolean isUpdatedManysOnly() {
|
||||
return updatedManysOnly;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.CallableSql;
|
||||
import com.avaje.ebean.SqlUpdate;
|
||||
import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.Update;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
|
||||
/**
|
||||
@@ -17,23 +17,23 @@ public interface Persister {
|
||||
/**
|
||||
* Force an Update using the given bean.
|
||||
*/
|
||||
public void forceUpdate(Object entityBean, Set<String> updateProps, Transaction t, boolean deleteMissingChildren, boolean updateNullProperties);
|
||||
public void forceUpdate(EntityBean entityBean, Transaction t, boolean deleteMissingChildren);
|
||||
|
||||
/**
|
||||
* Force an Insert using the given bean.
|
||||
*/
|
||||
public void forceInsert(Object entityBean, Transaction t);
|
||||
public void forceInsert(EntityBean entityBean, Transaction t);
|
||||
|
||||
/**
|
||||
* Insert or update the bean depending on its state.
|
||||
*/
|
||||
public void save(Object entityBean, Transaction t);
|
||||
public void save(EntityBean entityBean, Transaction t);
|
||||
|
||||
/**
|
||||
* Save the associations of a ManyToMany given the owner bean and the
|
||||
* propertyName of the ManyToMany collection.
|
||||
*/
|
||||
public void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
public void saveManyToManyAssociations(EntityBean ownerBean, String propertyName, Transaction t);
|
||||
|
||||
/**
|
||||
* Save an association (OneToMany, ManyToOne, OneToOne or ManyToMany).
|
||||
@@ -45,12 +45,12 @@ public interface Persister {
|
||||
* @param t
|
||||
* the transaction to use.
|
||||
*/
|
||||
public void saveAssociation(Object parentBean, String propertyName, Transaction t);
|
||||
public void saveAssociation(EntityBean parentBean, String propertyName, Transaction t);
|
||||
|
||||
/**
|
||||
* Delete the associations of a ManyToMany given the owner bean and the property name of the ManyToMany.
|
||||
*/
|
||||
public int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
public int deleteManyToManyAssociations(EntityBean ownerBean, String propertyName, Transaction t);
|
||||
|
||||
/**
|
||||
* Delete a bean given it's type and id value.
|
||||
@@ -63,7 +63,7 @@ public interface Persister {
|
||||
/**
|
||||
* Delete the bean.
|
||||
*/
|
||||
public void delete(Object entityBean, Transaction t);
|
||||
public void delete(EntityBean entityBean, Transaction t);
|
||||
|
||||
/**
|
||||
* Delete multiple beans given a collection of Id values.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
|
||||
/**
|
||||
@@ -41,22 +42,22 @@ public interface BeanCollectionHelp<T> {
|
||||
/**
|
||||
* Add a bean to the List Set or Map.
|
||||
*/
|
||||
public void add(BeanCollection<?> collection, Object bean);
|
||||
public void add(BeanCollection<?> collection, EntityBean bean);
|
||||
|
||||
/**
|
||||
* Create a lazy loading proxy for a List Set or Map.
|
||||
*/
|
||||
public BeanCollection<T> createReference(Object parentBean, String propertyName);
|
||||
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName);
|
||||
|
||||
/**
|
||||
* Refresh the List Set or Map.
|
||||
*/
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, Object parentBean);
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean);
|
||||
|
||||
/**
|
||||
* Apply the new refreshed BeanCollection to the appropriate property of the parent bean.
|
||||
*/
|
||||
public void refresh(BeanCollection<?> bc, Object parentBean);
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean);
|
||||
|
||||
/**
|
||||
* Write the collection out as json.
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
|
||||
/**
|
||||
* Utility methods for BeanCollections.
|
||||
*/
|
||||
public class BeanCollectionUtil {
|
||||
|
||||
/**
|
||||
* Return the details of the collection or map taking care to avoid
|
||||
* unnecessary fetching of the data.
|
||||
*/
|
||||
public static Collection<?> getActualEntries(Object o) {
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
if (o instanceof BeanCollection<?>) {
|
||||
BeanCollection<?> bc = (BeanCollection<?>) o;
|
||||
if (!bc.isPopulated()) {
|
||||
return null;
|
||||
}
|
||||
// For maps this is a collection of Map.Entry, otherwise it
|
||||
// returns a collection of beans
|
||||
return bc.getActualEntries();
|
||||
}
|
||||
|
||||
if (o instanceof Map<?, ?>) {
|
||||
// yes, we want the entrySet (to set the keys)
|
||||
return ((Map<?, ?>) o).entrySet();
|
||||
|
||||
} else if (o instanceof Collection<?>) {
|
||||
return ((Collection<?>) o);
|
||||
}
|
||||
throw new PersistenceException("expecting a Map or Collection but got [" + o.getClass().getName() + "]");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,600 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.cache.ServerCache;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.api.SpiTransaction;
|
||||
import com.avaje.ebeaninternal.api.TransactionEventTable.TableIUD;
|
||||
import com.avaje.ebeaninternal.server.cache.CachedBeanData;
|
||||
import com.avaje.ebeaninternal.server.cache.CachedBeanDataFromBean;
|
||||
import com.avaje.ebeaninternal.server.cache.CachedBeanDataToBean;
|
||||
import com.avaje.ebeaninternal.server.cache.CachedBeanDataUpdate;
|
||||
import com.avaje.ebeaninternal.server.cache.CachedManyIds;
|
||||
import com.avaje.ebeaninternal.server.core.CacheOptions;
|
||||
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
|
||||
import com.avaje.ebeaninternal.server.loadcontext.DLoadContext;
|
||||
import com.avaje.ebeaninternal.server.querydefn.NaturalKeyBindParam;
|
||||
import com.avaje.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
/**
|
||||
* Helper for BeanDescriptor that manages the bean, query and collection caches.
|
||||
*
|
||||
* @param <T> The entity bean type
|
||||
*/
|
||||
public final class BeanDescriptorCacheHelp<T> {
|
||||
|
||||
public static final Logger queryLog = LoggerFactory.getLogger("org.avaje.ebean.cache.QUERY");
|
||||
public static final Logger beanLog = LoggerFactory.getLogger("org.avaje.ebean.cache.BEAN");
|
||||
public static final Logger manyLog = LoggerFactory.getLogger("org.avaje.ebean.cache.COLL");
|
||||
public static final Logger natLog = LoggerFactory.getLogger("org.avaje.ebean.cache.NATKEY");
|
||||
|
||||
|
||||
private final BeanDescriptor<T> desc;
|
||||
|
||||
private final ServerCacheManager cacheManager;
|
||||
|
||||
private final CacheOptions cacheOptions;
|
||||
|
||||
/**
|
||||
* Flag indicating this bean has no relationships.
|
||||
*/
|
||||
private final boolean cacheSharableBeans;
|
||||
|
||||
private final Class<T> beanType;
|
||||
|
||||
private final String cacheName;
|
||||
|
||||
private final BeanPropertyAssocOne<?>[] propertiesOneImported;
|
||||
|
||||
private ServerCache beanCache;
|
||||
private ServerCache naturalKeyCache;
|
||||
private ServerCache queryCache;
|
||||
|
||||
public BeanDescriptorCacheHelp(BeanDescriptor<T> desc, ServerCacheManager cacheManager, CacheOptions cacheOptions,
|
||||
boolean cacheSharableBeans, BeanPropertyAssocOne<?>[] propertiesOneImported) {
|
||||
|
||||
this.desc = desc;
|
||||
this.beanType = desc.getBeanType();
|
||||
this.cacheName = beanType.getSimpleName();
|
||||
this.cacheManager = cacheManager;
|
||||
this.cacheOptions = cacheOptions;
|
||||
this.cacheSharableBeans = cacheSharableBeans;
|
||||
this.propertiesOneImported = propertiesOneImported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise the cache once the server has started.
|
||||
*/
|
||||
public void initialise() {
|
||||
if (cacheOptions.isUseNaturalKeyCache()) {
|
||||
this.naturalKeyCache = cacheManager.getNaturalKeyCache(beanType);
|
||||
}
|
||||
if (cacheOptions.isUseCache()) {
|
||||
this.beanCache = cacheManager.getBeanCache(beanType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the warming cache query (if defined) and load the cache.
|
||||
*/
|
||||
public void runCacheWarming(EbeanServer ebeanServer) {
|
||||
if (cacheOptions == null) {
|
||||
return;
|
||||
}
|
||||
String warmingQuery = cacheOptions.getWarmingQuery();
|
||||
if (warmingQuery != null && warmingQuery.trim().length() > 0) {
|
||||
Query<?> query = ebeanServer.createQuery(beanType, warmingQuery);
|
||||
query.setUseCache(true);
|
||||
query.setReadOnly(true);
|
||||
query.setLoadBeanCache(true);
|
||||
List<?> list = query.findList();
|
||||
if (beanLog.isInfoEnabled()) {
|
||||
beanLog.info("Loaded {} cache with [{}] beans", cacheName, list.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is currently query caching for this type of bean.
|
||||
*/
|
||||
public boolean isQueryCaching() {
|
||||
return queryCache != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there is currently bean caching for this type of bean.
|
||||
*/
|
||||
public boolean isBeanCaching() {
|
||||
return beanCache != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the persist request needs to notify the cache.
|
||||
*/
|
||||
public boolean isCacheNotify() {
|
||||
|
||||
if (isBeanCaching() || isQueryCaching()) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < propertiesOneImported.length; i++) {
|
||||
if (propertiesOneImported[i].getTargetDescriptor().isBeanCaching()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public CacheOptions getCacheOptions() {
|
||||
return cacheOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the query cache.
|
||||
*/
|
||||
public void queryCacheClear() {
|
||||
if (queryCache != null) {
|
||||
if (queryLog.isDebugEnabled()) {
|
||||
queryLog.debug(" CLEAR {}", cacheName);
|
||||
}
|
||||
queryCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a query result from the query cache.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BeanCollection<T> queryCacheGet(Object id) {
|
||||
if (queryCache == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (BeanCollection<T>) queryCache.get(id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a query result into the query cache.
|
||||
*/
|
||||
public void queryCachePut(Object id, BeanCollection<T> query) {
|
||||
if (queryCache == null) {
|
||||
queryCache = cacheManager.getQueryCache(beanType);
|
||||
}
|
||||
if (queryLog.isDebugEnabled()) {
|
||||
queryLog.debug(" PUT {} {}", cacheName, id);
|
||||
}
|
||||
queryCache.put(id, query);
|
||||
}
|
||||
|
||||
|
||||
public void manyPropRemove(Object parentId, String propertyName) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
if (manyLog.isDebugEnabled()) {
|
||||
manyLog.debug(" REMOVE {}({}).{}", cacheName, parentId, propertyName);
|
||||
}
|
||||
collectionIdsCache.remove(parentId);
|
||||
}
|
||||
|
||||
public void manyPropClear(String propertyName) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
if (manyLog.isDebugEnabled()) {
|
||||
manyLog.debug(" CLEAR {}(*).{} ", cacheName, propertyName);
|
||||
}
|
||||
collectionIdsCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CachedManyIds for a given bean many property. Returns null if not in the cache.
|
||||
*/
|
||||
public CachedManyIds manyPropGet(Object parentId, String propertyName) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
CachedManyIds entry = (CachedManyIds) collectionIdsCache.get(parentId);
|
||||
if (entry == null) {
|
||||
if (manyLog.isTraceEnabled()) {
|
||||
manyLog.trace(" GET {}({}).{} - cache miss", cacheName, parentId, propertyName);
|
||||
}
|
||||
} else if (manyLog.isDebugEnabled()) {
|
||||
manyLog.debug(" GET {}({}).{} - hit", cacheName, parentId, propertyName);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to load the bean collection from cache return true if successful.
|
||||
*/
|
||||
public boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId, Boolean readOnly) {
|
||||
|
||||
CachedManyIds entry = manyPropGet(parentId, many.getName());
|
||||
if (entry == null) {
|
||||
// not in cache so return unsuccessful
|
||||
return false;
|
||||
}
|
||||
|
||||
Object ownerBean = bc.getOwnerBean();
|
||||
EntityBeanIntercept ebi = ((EntityBean) ownerBean)._ebean_getIntercept();
|
||||
PersistenceContext persistenceContext = ebi.getPersistenceContext();
|
||||
|
||||
BeanDescriptor<?> targetDescriptor = many.getTargetDescriptor();
|
||||
|
||||
List<Object> idList = entry.getIdList();
|
||||
bc.checkEmptyLazyLoad();
|
||||
for (int i = 0; i < idList.size(); i++) {
|
||||
Object id = idList.get(i);
|
||||
Object refBean = targetDescriptor.createReference(readOnly, id);
|
||||
EntityBeanIntercept refEbi = ((EntityBean) refBean)._ebean_getIntercept();
|
||||
|
||||
many.add(bc, (EntityBean) refBean);
|
||||
persistenceContext.put(id, refBean);
|
||||
refEbi.setPersistenceContext(persistenceContext);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the beanCollection into the cache.
|
||||
*/
|
||||
public void manyPropPut(BeanPropertyAssocMany<?> many, Object details, Object parentId) {
|
||||
|
||||
BeanDescriptor<?> targetDescriptor = many.getTargetDescriptor();
|
||||
ArrayList<Object> idList = new ArrayList<Object>();
|
||||
|
||||
// get the underlying collection of beans (in the List, Set or Map)
|
||||
Collection<?> actualDetails = BeanCollectionUtil.getActualEntries(details);
|
||||
|
||||
for (Object bean : actualDetails) {
|
||||
// Collect the id values
|
||||
idList.add(targetDescriptor.getId((EntityBean) bean));
|
||||
}
|
||||
|
||||
CachedManyIds entry = new CachedManyIds(idList);
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, many.getName());
|
||||
if (manyLog.isDebugEnabled()) {
|
||||
manyLog.debug(" PUT {}({}).{} - ids:{}", cacheName, parentId, many.getName(), entry);
|
||||
}
|
||||
collectionIdsCache.put(parentId, entry);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public T naturalKeyLookup(SpiQuery<T> query, SpiTransaction t) {
|
||||
|
||||
if (!isNaturalKeyCaching(query.isUseBeanCache())) {
|
||||
// no natural key caching for this query
|
||||
return null;
|
||||
}
|
||||
|
||||
// check if it is a find by unique id (using the natural key)
|
||||
NaturalKeyBindParam keyBindParam = query.getNaturalKeyBindParam();
|
||||
if (keyBindParam == null || !isNaturalKey(keyBindParam.getName())) {
|
||||
// query is not appropriate
|
||||
return null;
|
||||
}
|
||||
|
||||
// try to lookup the id using the natural key
|
||||
Object id = naturalKeyCache.get(keyBindParam.getValue());
|
||||
if (natLog.isTraceEnabled()) {
|
||||
natLog.trace(" LOOKUP {}({}) - id:{}", cacheName, keyBindParam.getValue(), id);
|
||||
}
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// try looking up into the bean cache using the id
|
||||
T cacheBean = beanCacheGetInternal(id, query.isReadOnly());
|
||||
if (cacheBean != null) {
|
||||
setupContext(cacheBean, query, getPersistenceContext(t));
|
||||
}
|
||||
return cacheBean;
|
||||
}
|
||||
|
||||
private PersistenceContext getPersistenceContext(SpiTransaction t) {
|
||||
PersistenceContext context = null;
|
||||
if (t == null) {
|
||||
t = desc.getEbeanServer().getCurrentServerTransaction();
|
||||
}
|
||||
if (t != null) {
|
||||
context = t.getPersistenceContext();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
private boolean isNaturalKeyCaching(Boolean queryUseCache) {
|
||||
return naturalKeyCache != null && (queryUseCache == null || queryUseCache.booleanValue());
|
||||
}
|
||||
|
||||
private boolean isNaturalKey(String propName) {
|
||||
return propName != null && propName.equals(cacheOptions.getNaturalKey());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* For a bean built from the cache this sets up its persistence context for future lazy loading etc.
|
||||
*/
|
||||
private void setupContext(Object bean, SpiQuery<T> query, PersistenceContext context) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
}
|
||||
context.put(query.getId(), bean);
|
||||
|
||||
DLoadContext loadContext = new DLoadContext(desc.getEbeanServer(), desc, query.isReadOnly(), query);
|
||||
loadContext.setPersistenceContext(context);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) bean)._ebean_getIntercept();
|
||||
ebi.setPersistenceContext(context);
|
||||
loadContext.register(null, ebi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the beanCache creating it if necessary.
|
||||
*/
|
||||
private ServerCache getBeanCache() {
|
||||
if (beanCache == null) {
|
||||
beanCache = cacheManager.getBeanCache(beanType);
|
||||
}
|
||||
return beanCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the bean cache.
|
||||
*/
|
||||
public void beanCacheClear() {
|
||||
if (beanCache != null) {
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" CLEAR {}", cacheName);
|
||||
}
|
||||
beanCache.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a bean into the bean cache.
|
||||
*/
|
||||
public void beanCachePut(EntityBean bean) {
|
||||
|
||||
CachedBeanData beanData = CachedBeanDataFromBean.extract(desc, bean);
|
||||
|
||||
Object id = desc.getId(bean);
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" PUT {}({})", cacheName, id);
|
||||
}
|
||||
getBeanCache().put(id, beanData);
|
||||
|
||||
if (beanData.isNaturalKeyUpdate() && naturalKeyCache != null) {
|
||||
Object naturalKey = beanData.getNaturalKey();
|
||||
if (naturalKey != null) {
|
||||
if (natLog.isDebugEnabled()) {
|
||||
natLog.debug(" PUT {}({}, {})", cacheName, naturalKey, id);
|
||||
}
|
||||
naturalKeyCache.put(naturalKey, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CachedBeanData beanCacheGetData(Object id) {
|
||||
return (CachedBeanData) getBeanCache().get(id);
|
||||
}
|
||||
|
||||
public T beanCacheGet(SpiQuery<T> query, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(query.getId(), query.isReadOnly());
|
||||
if (bean != null) {
|
||||
setupContext(bean, query, context);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a bean from the bean cache.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private T beanCacheGetInternal(Object id, Boolean readOnly) {
|
||||
|
||||
CachedBeanData d = (CachedBeanData) getBeanCache().get(id);
|
||||
if (d == null) {
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" GET {}({}) - cache miss", cacheName, id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) {
|
||||
Object bean = d.getSharableBean();
|
||||
if (bean != null) {
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" GET {}({}) - hit shared bean", cacheName, id);
|
||||
}
|
||||
return (T) bean;
|
||||
}
|
||||
}
|
||||
|
||||
EntityBean bean = desc.createBean();
|
||||
desc.convertSetId(id, bean);
|
||||
if (Boolean.TRUE.equals(readOnly)) {
|
||||
bean._ebean_getIntercept().setReadOnly(true);
|
||||
}
|
||||
|
||||
CachedBeanDataToBean.load(desc, bean, d);
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" GET {}({}) - hit", cacheName, id);
|
||||
}
|
||||
return (T) bean;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a bean from the cache given its Id.
|
||||
*/
|
||||
public void beanCacheRemove(Object id) {
|
||||
if (beanCache != null) {
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" REMOVE {}({})", cacheName, id);
|
||||
}
|
||||
beanCache.remove(id);
|
||||
}
|
||||
for (int i = 0; i < propertiesOneImported.length; i++) {
|
||||
propertiesOneImported[i].cacheClear();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it managed to populate/load the bean from the cache.
|
||||
*/
|
||||
public boolean beanCacheLoad(EntityBean bean, EntityBeanIntercept ebi, Object id) {
|
||||
|
||||
CachedBeanData cacheData = (CachedBeanData) getBeanCache().get(id);
|
||||
if (cacheData == null) {
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" LOAD {}({}) - cache miss", cacheName, id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int lazyLoadProperty = ebi.getLazyLoadPropertyIndex();
|
||||
if (lazyLoadProperty > -1 && !cacheData.isLoaded(lazyLoadProperty)) {
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" LOAD {}({}) - cache miss on property", cacheName, id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CachedBeanDataToBean.load(desc, bean, cacheData);
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" LOAD {}({}) - hit", cacheName, id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a bean from the cache given its Id.
|
||||
*/
|
||||
public void handleDelete(Object id, PersistRequestBean<T> deleteRequest) {
|
||||
if (queryCache != null) {
|
||||
if (queryLog.isDebugEnabled()) {
|
||||
queryLog.debug(" CLEAR {}(*) - delete trigger", cacheName);
|
||||
}
|
||||
queryCache.clear();
|
||||
}
|
||||
if (beanCache != null) {
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" REMOVE {}({})", cacheName, id);
|
||||
}
|
||||
beanCache.remove(id);
|
||||
}
|
||||
for (int i = 0; i < propertiesOneImported.length; i++) {
|
||||
BeanPropertyAssocMany<?> many = propertiesOneImported[i].getRelationshipProperty();
|
||||
if (many != null) {
|
||||
propertiesOneImported[i].cacheDelete(true, deleteRequest.getEntityBean());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void handleInsert(Object id, PersistRequestBean<T> insertRequest) {
|
||||
if (queryCache != null) {
|
||||
if (queryLog.isDebugEnabled()) {
|
||||
queryLog.debug(" CLEAR {}(*) - insert trigger", cacheName);
|
||||
}
|
||||
queryCache.clear();
|
||||
}
|
||||
for (int i = 0; i < propertiesOneImported.length; i++) {
|
||||
propertiesOneImported[i].cacheDelete(false, insertRequest.getEntityBean());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached bean data.
|
||||
*/
|
||||
public void handleUpdate(Object id, PersistRequestBean<T> updateRequest) {
|
||||
|
||||
if (queryCache != null) {
|
||||
if (queryLog.isDebugEnabled()) {
|
||||
queryLog.debug(" CLEAR {}(*) - update trigger", cacheName);
|
||||
}
|
||||
queryCache.clear();
|
||||
}
|
||||
|
||||
List<BeanPropertyAssocMany<?>> manyCollections = updateRequest.getUpdatedManyCollections();
|
||||
if (manyCollections != null) {
|
||||
// clear the appropriate manyProp caches first
|
||||
for (int i = 0; i < manyCollections.size(); i++) {
|
||||
manyPropRemove(id, manyCollections.get(i).getName());
|
||||
}
|
||||
}
|
||||
|
||||
// check if the bean itself was updated
|
||||
if (!updateRequest.isUpdatedManysOnly()) {
|
||||
|
||||
// update the bean cache entry if it exists
|
||||
ServerCache cache = getBeanCache();
|
||||
CachedBeanData existingData = (CachedBeanData) cache.get(id);
|
||||
if (existingData != null) {
|
||||
|
||||
if (isCachedDataTooOld(existingData)) {
|
||||
// just remove the entry from the cache
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" REMOVE {}({}) - entry too old", cacheName, id);
|
||||
}
|
||||
cache.remove(id);
|
||||
|
||||
} else {
|
||||
// Update the cache data with the changes from our update
|
||||
CachedBeanData newData = CachedBeanDataUpdate.update(desc, existingData, updateRequest.getEntityBean());
|
||||
if (beanLog.isDebugEnabled()) {
|
||||
beanLog.debug(" UPDATE {}({})", cacheName, id);
|
||||
}
|
||||
cache.put(id, newData);
|
||||
if (newData.isNaturalKeyUpdate() && naturalKeyCache != null) {
|
||||
|
||||
Object oldKey = newData.getOldNaturalKey();
|
||||
Object newKey = newData.getNaturalKey();
|
||||
if (natLog.isDebugEnabled()) {
|
||||
natLog.debug(".. update {} PUT({}, {}) REMOVE({})", cacheName, newKey, id, oldKey);
|
||||
}
|
||||
|
||||
if (oldKey != null) {
|
||||
naturalKeyCache.remove(oldKey);
|
||||
}
|
||||
if (newKey != null) {
|
||||
naturalKeyCache.put(newKey, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manyCollections != null) {
|
||||
for (int i = 0; i < manyCollections.size(); i++) {
|
||||
BeanPropertyAssocMany<?> many = manyCollections.get(i);
|
||||
Object manyValue = many.getValue(updateRequest.getEntityBean());
|
||||
manyPropPut(many, manyValue, id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean isCachedDataTooOld(CachedBeanData existingData) {
|
||||
return cacheOptions.isTooOldInMillis(System.currentTimeMillis() - existingData.getWhenCreated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate parts of cache due to SqlUpdate or external modification etc.
|
||||
*/
|
||||
public void handleBulkUpdate(TableIUD tableIUD) {
|
||||
// inserts don't invalidate the bean cache
|
||||
if (tableIUD.isUpdateOrDelete()) {
|
||||
beanCacheClear();
|
||||
}
|
||||
// any change invalidates the query cache
|
||||
queryCacheClear();
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ import com.avaje.ebeaninternal.server.lib.util.Dnode;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflect;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectFactory;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectProperties;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
|
||||
import com.avaje.ebeaninternal.server.reflect.EnhanceBeanReflectFactory;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
@@ -221,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() {
|
||||
@@ -280,7 +281,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
List<BeanDescriptor<?>> list = getBeanDescriptors(tableIUD.getTableName());
|
||||
if (list != null) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
list.get(i).cacheNotify(tableIUD);
|
||||
list.get(i).cacheHandleBulkUpdate(tableIUD);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1298,43 +1299,34 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// abstract classes as well.
|
||||
|
||||
Class<?> beanType = desc.getBeanType();
|
||||
Class<?> factType = desc.getFactoryType();
|
||||
|
||||
BeanReflect beanReflect = reflectFactory.create(beanType, factType);
|
||||
BeanReflectProperties reflectProps = new BeanReflectProperties(beanType);
|
||||
|
||||
BeanReflect beanReflect = reflectFactory.create(beanType);
|
||||
desc.setBeanReflect(beanReflect);
|
||||
desc.setProperties(reflectProps.getProperties());
|
||||
|
||||
try {
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
String propName = prop.getName();
|
||||
Iterator<DeployBeanProperty> it = desc.propertiesAll();
|
||||
while (it.hasNext()) {
|
||||
DeployBeanProperty prop = it.next();
|
||||
String propName = prop.getName();
|
||||
|
||||
Integer pos = reflectProps.getPropertyIndex(propName);
|
||||
if (pos == null) {
|
||||
throw new IllegalStateException("Property "+propName+" not found in "+reflectProps);
|
||||
}
|
||||
|
||||
if (desc.isAbstract() || beanReflect.isVanillaOnly()) {
|
||||
// use reflection in the case of imported abstract class
|
||||
// with
|
||||
// inheritance. Refer Bug 166
|
||||
prop.setGetter(ReflectGetter.create(prop));
|
||||
prop.setSetter(ReflectSetter.create(prop));
|
||||
|
||||
} else {
|
||||
// use generated code for getting setting property values
|
||||
BeanReflectGetter getter = beanReflect.getGetter(propName);
|
||||
BeanReflectSetter setter = beanReflect.getSetter(propName);
|
||||
prop.setGetter(getter);
|
||||
prop.setSetter(setter);
|
||||
if (getter == null) {
|
||||
// should never happen
|
||||
String m = "BeanReflectGetter for " + prop.getFullBeanName() + " was not found?";
|
||||
throw new RuntimeException(m);
|
||||
}
|
||||
}
|
||||
BeanReflectGetter getter = beanReflect.getGetter(propName, pos.intValue());
|
||||
BeanReflectSetter setter = beanReflect.getSetter(propName, pos.intValue());
|
||||
prop.setGetter(getter);
|
||||
prop.setSetter(setter);
|
||||
prop.setPropertyIndex(pos.intValue());
|
||||
|
||||
if (getter == null) {
|
||||
String m = "BeanReflectGetter for " + prop.getFullBeanName() + " was not found?";
|
||||
throw new RuntimeException(m);
|
||||
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
Class<?> superClass = desc.getBeanType().getSuperclass();
|
||||
String msg = "Error with [" + desc.getFullName() + "] I believe it is not enhanced but it's superClass [" + superClass + "] is?"
|
||||
+ " (You are not allowed to mix enhancement in a single inheritance hierarchy)";
|
||||
throw new PersistenceException(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,13 +1337,15 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void setConcurrencyMode(DeployBeanDescriptor<?> desc) {
|
||||
|
||||
if (!desc.getConcurrencyMode().equals(ConcurrencyMode.ALL)) {
|
||||
if (desc.getConcurrencyMode() != null) {
|
||||
// concurrency mode explicitly set during deployment
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkForVersionProperties(desc)) {
|
||||
desc.setConcurrencyMode(ConcurrencyMode.VERSION);
|
||||
} else {
|
||||
desc.setConcurrencyMode(ConcurrencyMode.NONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,91 +1384,35 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
Class<?> beanClass = desc.getBeanType();
|
||||
|
||||
if (desc.isAbstract()) {
|
||||
if (hasEntityBeanInterface(beanClass)) {
|
||||
checkEnhanced(desc, beanClass);
|
||||
} else {
|
||||
checkSubclass(desc, beanClass);
|
||||
}
|
||||
return;
|
||||
if (!hasEntityBeanInterface(beanClass)) {
|
||||
throw new IllegalStateException("Bean "+beanClass+" is not enhanced?");
|
||||
}
|
||||
try {
|
||||
Object testBean = null;
|
||||
try {
|
||||
testBean = beanClass.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
// expected when no default constructor
|
||||
logger.debug("no default constructor on " + beanClass + " e:" + e);
|
||||
} catch (IllegalAccessException e) {
|
||||
// expected when no default constructor
|
||||
logger.debug("no default constructor on " + beanClass + " e:" + e);
|
||||
}
|
||||
if (testBean instanceof EntityBean == false) {
|
||||
checkSubclass(desc, beanClass);
|
||||
|
||||
} else {
|
||||
String className = beanClass.getName();
|
||||
try {
|
||||
// check that it really is enhanced (rather than mixed
|
||||
// enhancement)
|
||||
String marker = ((EntityBean) testBean)._ebean_getMarker();
|
||||
if (!marker.equals(className)) {
|
||||
String msg = "Error with [" + desc.getFullName() + "] It has not been enhanced but it's superClass ["
|
||||
+ beanClass.getSuperclass() + "] is?" + " (You are not allowed to mix enhancement in a single inheritance hierarchy)"
|
||||
+ " marker[" + marker + "] className[" + className + "]";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
} catch (AbstractMethodError e) {
|
||||
throw new PersistenceException("Old Ebean v1.0 enhancement detected in Ebean v1.1 - please do a clean enhancement.", e);
|
||||
}
|
||||
|
||||
checkEnhanced(desc, beanClass);
|
||||
}
|
||||
|
||||
} catch (PersistenceException ex) {
|
||||
throw ex;
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkEnhanced(DeployBeanDescriptor<?> desc, Class<?> beanClass) {
|
||||
// the bean already implements EntityBean
|
||||
checkInheritedClasses(true, beanClass);
|
||||
desc.setFactoryType(beanClass);
|
||||
enhancedClassCount++;
|
||||
}
|
||||
checkInheritedClasses(beanClass);
|
||||
|
||||
private void checkSubclass(DeployBeanDescriptor<?> desc, Class<?> beanClass) {
|
||||
|
||||
throw new PersistenceException("Entity type "+beanClass+" is not an enhanced entity bean. Subclassing is not longer supported in Ebean");
|
||||
if (!beanClass.getName().startsWith("com.avaje.ebean.meta")) {
|
||||
enhancedClassCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the inherited classes are the same as the entity bean (aka all
|
||||
* enhanced or all dynamically subclassed).
|
||||
*/
|
||||
private void checkInheritedClasses(boolean ensureEnhanced, Class<?> beanClass) {
|
||||
private void checkInheritedClasses(Class<?> beanClass) {
|
||||
Class<?> superclass = beanClass.getSuperclass();
|
||||
if (Object.class.equals(superclass)) {
|
||||
// we got to the top of the inheritance
|
||||
return;
|
||||
}
|
||||
boolean isClassEnhanced = EntityBean.class.isAssignableFrom(superclass);
|
||||
|
||||
if (ensureEnhanced != isClassEnhanced) {
|
||||
String msg;
|
||||
if (ensureEnhanced) {
|
||||
msg = "Class [" + superclass + "] is not enhanced and [" + beanClass + "] is - (you can not mix!!)";
|
||||
} else {
|
||||
msg = "Class [" + superclass + "] is enhanced and [" + beanClass + "] is not - (you can not mix!!)";
|
||||
}
|
||||
throw new IllegalStateException(msg);
|
||||
if (!EntityBean.class.isAssignableFrom(superclass)) {
|
||||
throw new IllegalStateException("Super type "+superclass+" is not enhanced?");
|
||||
}
|
||||
|
||||
|
||||
// recursively continue up the inheritance hierarchy
|
||||
checkInheritedClasses(ensureEnhanced, superclass);
|
||||
checkInheritedClasses(superclass);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,6 @@ public interface BeanDescriptorMap {
|
||||
*/
|
||||
public EncryptKey getEncryptKey(String tableName, String columnName);
|
||||
|
||||
public IdBinder createIdBinder(BeanProperty[] uids);
|
||||
public IdBinder createIdBinder(BeanProperty id);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,16 +16,4 @@ public class BeanEmbeddedMeta {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if at least one property is a version property.
|
||||
*/
|
||||
public boolean isEmbeddedVersion() {
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
if (properties[i].isVersion()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.StringFormatter;
|
||||
import com.avaje.ebean.text.StringParser;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
@@ -95,7 +96,7 @@ public final class BeanFkeyProperty implements ElPropertyValue {
|
||||
/**
|
||||
* Returns null as not an AssocOne.
|
||||
*/
|
||||
public Object[] getAssocOneIdValues(Object value) {
|
||||
public Object[] getAssocOneIdValues(EntityBean value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ public final class BeanFkeyProperty implements ElPropertyValue {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public void elSetReference(Object bean) {
|
||||
public void elSetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
@@ -167,15 +168,15 @@ public final class BeanFkeyProperty implements ElPropertyValue {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public void elSetValue(Object bean, Object value, boolean populate, boolean reference) {
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetValue(Object bean) {
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
throw new RuntimeException("ElPropertyDeploy only - not implemented");
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanList;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
|
||||
@@ -35,11 +36,11 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
public void setLoader(BeanCollectionLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal add bypassing any modify listening.
|
||||
*/
|
||||
public void add(BeanCollection<?> collection, Object bean) {
|
||||
public void add(BeanCollection<?> collection, EntityBean bean) {
|
||||
collection.internalAdd(bean);
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
public void addBean(Object bean) {
|
||||
public void addBean(EntityBean bean) {
|
||||
list.add(bean);
|
||||
}
|
||||
}
|
||||
@@ -90,20 +91,20 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
return beanList;
|
||||
}
|
||||
|
||||
public BeanCollection<T> createReference(Object parentBean, String propertyName) {
|
||||
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
|
||||
|
||||
BeanList<T> beanList = new BeanList<T>(loader, parentBean, propertyName);
|
||||
beanList.setModifyListening(many.getModifyListenMode());
|
||||
return beanList;
|
||||
}
|
||||
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, Object parentBean) {
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
|
||||
BeanList<?> newBeanList = (BeanList<?>) server.findList(query, t);
|
||||
refresh(newBeanList, parentBean);
|
||||
}
|
||||
|
||||
public void refresh(BeanCollection<?> bc, Object parentBean) {
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
|
||||
BeanList<?> newBeanList = (BeanList<?>) bc;
|
||||
|
||||
@@ -152,7 +153,7 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
ctx.appendComma();
|
||||
}
|
||||
Object detailBean = list.get(j);
|
||||
targetDescriptor.jsonWrite(ctx, detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanMap;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
|
||||
@@ -93,7 +94,7 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
public void addBean(Object bean) {
|
||||
public void addBean(EntityBean bean) {
|
||||
Object keyValue = beanProperty.getValue(bean);
|
||||
map.put(keyValue, bean);
|
||||
}
|
||||
@@ -111,18 +112,15 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
return beanMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Internal add bypassing any modify listening.
|
||||
*/
|
||||
public void add(BeanCollection<?> collection, Object bean) {
|
||||
public void add(BeanCollection<?> collection, EntityBean bean) {
|
||||
|
||||
Object keyValue = beanProperty.getValueIntercept(bean);
|
||||
|
||||
((BeanMap<?,?>) collection).internalPut(keyValue, bean);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public BeanCollection<T> createReference(Object parentBean, String propertyName) {
|
||||
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
|
||||
|
||||
BeanMap beanMap = new BeanMap(loader, parentBean, propertyName);
|
||||
if (many != null) {
|
||||
@@ -131,12 +129,12 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
return beanMap;
|
||||
}
|
||||
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, Object parentBean) {
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
|
||||
refresh(newBeanMap, parentBean);
|
||||
}
|
||||
|
||||
public void refresh(BeanCollection<?> bc, Object parentBean) {
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
|
||||
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
|
||||
Map<?, ?> current = (Map<?, ?>) many.getValue(parentBean);
|
||||
@@ -187,7 +185,7 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
}
|
||||
//FIXME: json write map key ...
|
||||
Object detailBean = entry.getValue();
|
||||
targetDescriptor.jsonWrite(ctx, detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.avaje.ebeaninternal.server.text.json.ReadJsonContext;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
|
||||
/**
|
||||
* Description of a property of a bean. Includes its deployment information such
|
||||
@@ -141,6 +140,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
*/
|
||||
final String name;
|
||||
|
||||
final int propertyIndex;
|
||||
|
||||
/**
|
||||
* The reflected field.
|
||||
*/
|
||||
@@ -249,8 +250,6 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
final DbEncryptFunction dbEncryptFunction;
|
||||
|
||||
final boolean dynamicSubclassWithInheritance;
|
||||
|
||||
int deployOrder;
|
||||
|
||||
final boolean jsonSerialize;
|
||||
@@ -265,11 +264,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
if (descriptor != null) {
|
||||
this.dynamicSubclassWithInheritance = (descriptor.isDynamicSubclass() && descriptor.hasInheritance());
|
||||
} else {
|
||||
this.dynamicSubclassWithInheritance = false;
|
||||
}
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
|
||||
this.unidirectionalShadow = deploy.isUndirectionalShadow();
|
||||
this.localEncrypted = deploy.isLocalEncrypted();
|
||||
this.dbEncrypted = deploy.isDbEncrypted();
|
||||
@@ -363,7 +359,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
this.descriptor = source.descriptor;
|
||||
this.name = InternString.intern(source.getName());
|
||||
this.dynamicSubclassWithInheritance = source.dynamicSubclassWithInheritance;
|
||||
this.propertyIndex = source.propertyIndex;
|
||||
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
this.sqlFormulaJoin = InternString.intern(override.getSqlFormulaJoin());
|
||||
@@ -473,14 +469,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return formula;
|
||||
}
|
||||
|
||||
public boolean hasChanged(Object bean, Object oldValues) {
|
||||
Object value = getValue(bean);
|
||||
Object oldVal = getValue(oldValues);
|
||||
|
||||
return !ValueUtil.areEqual(value, oldVal);
|
||||
}
|
||||
|
||||
public void copyProperty(Object sourceBean, Object destBean) {
|
||||
public void copyProperty(EntityBean sourceBean, EntityBean destBean) {
|
||||
Object value = getValue(sourceBean);
|
||||
setValue(destBean, value);
|
||||
}
|
||||
@@ -561,7 +550,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return owningType.isAssignableFrom(type);
|
||||
}
|
||||
|
||||
public Object readSetOwning(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSetOwning(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
|
||||
try {
|
||||
Object value = scalarType.read(ctx.getDataReader());
|
||||
@@ -599,7 +588,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return scalarType.read(ctx.getDataReader());
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
|
||||
try {
|
||||
Object value = scalarType.read(ctx.getDataReader());
|
||||
@@ -690,15 +679,9 @@ public class BeanProperty implements ElPropertyValue {
|
||||
* Set the value of the property without interception or
|
||||
* PropertyChangeSupport.
|
||||
*/
|
||||
public void setValue(Object bean, Object value) {
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
setter.set(bean, value);
|
||||
} else {
|
||||
Object[] args = new Object[1];
|
||||
args[0] = value;
|
||||
writeMethod.invoke(bean, args);
|
||||
}
|
||||
setter.set(bean, value);
|
||||
} catch (Exception ex) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().getName();
|
||||
String msg = "set " + name + " on [" + descriptor + "] arg[" + value + "] type[" + beanType
|
||||
@@ -710,15 +693,9 @@ public class BeanProperty implements ElPropertyValue {
|
||||
/**
|
||||
* Set the value of the property.
|
||||
*/
|
||||
public void setValueIntercept(Object bean, Object value) {
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
setter.setIntercept(bean, value);
|
||||
} else {
|
||||
Object[] args = new Object[1];
|
||||
args[0] = value;
|
||||
writeMethod.invoke(bean, args);
|
||||
}
|
||||
setter.setIntercept(bean, value);
|
||||
} catch (Exception ex) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().getName();
|
||||
String msg = "setIntercept " + name + " on [" + descriptor + "] arg[" + value + "] type[" + beanType
|
||||
@@ -729,34 +706,20 @@ public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
private static Object[] NO_ARGS = new Object[0];
|
||||
|
||||
/**
|
||||
* Return the property value taking inheritance into account.
|
||||
*/
|
||||
public Object getValueWithInheritance(Object bean) {
|
||||
if (dynamicSubclassWithInheritance) {
|
||||
return descriptor.getBeanPropertyWithInheritance(bean, name);
|
||||
}
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
public Object getCacheDataValue(Object bean){
|
||||
public Object getCacheDataValue(EntityBean bean){
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
public void setCacheDataValue(Object bean, Object cacheData, Object oldValues, boolean readOnly){
|
||||
public void setCacheDataValue(EntityBean bean, Object cacheData){
|
||||
setValue(bean, cacheData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the property method.
|
||||
*/
|
||||
public Object getValue(Object bean) {
|
||||
public Object getValue(EntityBean bean) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
return getter.get(bean);
|
||||
} else {
|
||||
return readMethod.invoke(bean, NO_ARGS);
|
||||
}
|
||||
return getter.get(bean);
|
||||
} catch (Exception ex) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().getName();
|
||||
String msg = "get " + name + " on [" + descriptor + "] type[" + beanType + "] threw error.";
|
||||
@@ -777,13 +740,9 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
}
|
||||
|
||||
public Object getValueIntercept(Object bean) {
|
||||
public Object getValueIntercept(EntityBean bean) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
return getter.getIntercept(bean);
|
||||
} else {
|
||||
return readMethod.invoke(bean, NO_ARGS);
|
||||
}
|
||||
return getter.getIntercept(bean);
|
||||
} catch (Exception ex) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().getName();
|
||||
String msg = "getIntercept " + name + " on [" + descriptor + "] type[" + beanType + "] threw error.";
|
||||
@@ -798,24 +757,21 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return convertToLogicalType(value);
|
||||
}
|
||||
|
||||
public void elSetReference(Object bean) {
|
||||
throw new RuntimeException("Should not be called");
|
||||
}
|
||||
|
||||
public void elSetValue(Object bean, Object value, boolean populate, boolean reference) {
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate) {
|
||||
if (bean != null) {
|
||||
setValueIntercept(bean, value);
|
||||
// Not using setValueIntercept at this stage
|
||||
setValue(bean, value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object elGetValue(Object bean) {
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
if (bean == null) {
|
||||
return null;
|
||||
}
|
||||
return getValueIntercept(bean);
|
||||
}
|
||||
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
throw new RuntimeException("Not expected to call this");
|
||||
}
|
||||
|
||||
@@ -826,6 +782,13 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the position of this property in the enhanced bean.
|
||||
*/
|
||||
public int getPropertyIndex() {
|
||||
return propertyIndex;
|
||||
}
|
||||
|
||||
public String getElName() {
|
||||
return name;
|
||||
}
|
||||
@@ -851,7 +814,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object[] getAssocOneIdValues(Object bean) {
|
||||
public Object[] getAssocOneIdValues(EntityBean bean) {
|
||||
// Returns null as not an AssocOne.
|
||||
return null;
|
||||
}
|
||||
@@ -1177,7 +1140,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void jsonWrite(WriteJsonContext ctx, Object bean) {
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
if(!jsonSerialize){
|
||||
return;
|
||||
}
|
||||
@@ -1189,7 +1152,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, Object bean) {
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean) {
|
||||
if(!jsonDeserialize){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -216,14 +216,12 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty {
|
||||
/**
|
||||
* Return true if the unique id properties are all not null for this bean.
|
||||
*/
|
||||
public boolean hasId(Object bean) {
|
||||
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<T> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
@@ -148,7 +149,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
/**
|
||||
* Add the bean to the appropriate collection on the parent bean.
|
||||
*/
|
||||
public void addBeanToCollectionWithCreate(Object parentBean, Object detailBean) {
|
||||
public void addBeanToCollectionWithCreate(EntityBean parentBean, EntityBean detailBean) {
|
||||
BeanCollection<?> bc = (BeanCollection<?>)super.getValue(parentBean);
|
||||
if (bc == null) {
|
||||
bc = (BeanCollection<?>)help.createEmpty(false);
|
||||
@@ -157,23 +158,35 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
help.add(bc, detailBean);
|
||||
}
|
||||
|
||||
public boolean isEmptyBeanCollection(EntityBean bean) {
|
||||
Object val = getValue(bean);
|
||||
if (val == null) {
|
||||
return true;
|
||||
}
|
||||
if (val instanceof BeanCollection<?>) {
|
||||
// if empty and not been cleared or elements removed
|
||||
return ((BeanCollection<?>)val).isEmptyAndUntouched();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(Object bean) {
|
||||
public Object getValue(EntityBean bean) {
|
||||
return super.getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueIntercept(Object bean) {
|
||||
public Object getValueIntercept(EntityBean bean) {
|
||||
return super.getValueIntercept(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Object bean, Object value) {
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueIntercept(Object bean, Object value) {
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
super.setValueIntercept(bean, value);
|
||||
}
|
||||
|
||||
@@ -324,7 +337,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -342,21 +355,21 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void add(BeanCollection<?> collection, Object bean) {
|
||||
public void add(BeanCollection<?> collection, EntityBean bean) {
|
||||
help.add(collection, bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the appropriate list set or map.
|
||||
*/
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, Object parentBean) {
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
help.refresh(server, query, t, parentBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the refreshed BeanCollection to the property of the parentBean.
|
||||
*/
|
||||
public void refresh(BeanCollection<?> bc, Object parentBean) {
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
help.refresh(bc, parentBean);
|
||||
}
|
||||
|
||||
@@ -364,7 +377,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
* Return the Id values from the given bean.
|
||||
*/
|
||||
@Override
|
||||
public Object[] getAssocOneIdValues(Object bean) {
|
||||
public Object[] getAssocOneIdValues(EntityBean bean) {
|
||||
return targetDescriptor.getIdBinder().getIdValues(bean);
|
||||
}
|
||||
|
||||
@@ -435,7 +448,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
* Set the join properties from the parent bean to the child bean.
|
||||
* This is only valid for OneToMany and NOT valid for ManyToMany.
|
||||
*/
|
||||
public void setJoinValuesToChild(Object parent, Object child, Object mapKeyValue) {
|
||||
public void setJoinValuesToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
|
||||
if (mapKeyProperty != null){
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
@@ -468,7 +481,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
public BeanCollection<?> createReferenceIfNull(Object parentBean) {
|
||||
public BeanCollection<?> createReferenceIfNull(EntityBean parentBean) {
|
||||
|
||||
Object v = getValue(parentBean);
|
||||
if (v instanceof BeanCollection<?>){
|
||||
@@ -479,7 +492,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public BeanCollection<?> createReference(Object parentBean) {
|
||||
public BeanCollection<?> createReference(EntityBean parentBean) {
|
||||
|
||||
BeanCollection<?> ref = help.createReference(parentBean, name);
|
||||
setValue(parentBean, ref);
|
||||
@@ -494,7 +507,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return help.getBeanCollectionAdd(bc, mapKey);
|
||||
}
|
||||
|
||||
public Object getParentId(Object parentBean) {
|
||||
public Object getParentId(EntityBean parentBean) {
|
||||
return descriptor.getId(parentBean);
|
||||
}
|
||||
|
||||
@@ -506,7 +519,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
for (int i=0; i < parentIds.size(); i++) {
|
||||
for (int y = 0; y < exportedProperties.length; y++) {
|
||||
Object compId = parentIds.get(i);
|
||||
expandedList.add(exportedProperties[y].getValue(compId));
|
||||
expandedList.add(exportedProperties[y].getValue((EntityBean)compId));
|
||||
}
|
||||
}
|
||||
return expandedList;
|
||||
@@ -518,8 +531,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
sqlUpd.addParameter(parentId);
|
||||
return;
|
||||
}
|
||||
EntityBean parent = (EntityBean)parentId;
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
Object embVal = exportedProperties[i].getValue(parentId);
|
||||
Object embVal = exportedProperties[i].getValue(parent);
|
||||
sqlUpd.addParameter(embVal);
|
||||
}
|
||||
}
|
||||
@@ -531,8 +545,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
} else {
|
||||
|
||||
EntityBean parent = (EntityBean)parentId;
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
Object embVal = exportedProperties[i].getValue(parentId);
|
||||
Object embVal = exportedProperties[i].getValue(parent);
|
||||
q.setParameter(pos++, embVal);
|
||||
}
|
||||
}
|
||||
@@ -574,7 +589,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void setPredicates(SpiQuery<?> query, Object parentBean) {
|
||||
public void setPredicates(SpiQuery<?> query, EntityBean parentBean) {
|
||||
|
||||
if (manyToMany){
|
||||
// for ManyToMany lazy loading we need to include a
|
||||
@@ -585,8 +600,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
if (embeddedExportedProperties) {
|
||||
// use the EmbeddedId object instead of the parentBean
|
||||
BeanProperty[] uids = descriptor.propertiesId();
|
||||
parentBean = uids[0].getValue(parentBean);
|
||||
BeanProperty idProp = descriptor.getIdProperty();
|
||||
parentBean = (EntityBean)idProp.getValue(parentBean);
|
||||
}
|
||||
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
@@ -618,13 +633,13 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
*/
|
||||
private ExportedProperty[] createExported() {
|
||||
|
||||
BeanProperty[] uids = descriptor.propertiesId();
|
||||
BeanProperty idProp = descriptor.getIdProperty();
|
||||
|
||||
ArrayList<ExportedProperty> list = new ArrayList<ExportedProperty>();
|
||||
|
||||
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 {
|
||||
@@ -638,8 +653,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -741,7 +756,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
|
||||
public IntersectionRow buildManyDeleteChildren(Object parentBean, ArrayList<Object> excludeDetailIds) {
|
||||
public IntersectionRow buildManyDeleteChildren(EntityBean parentBean, ArrayList<Object> excludeDetailIds) {
|
||||
|
||||
IntersectionRow row = new IntersectionRow(tableJoin.getTable());
|
||||
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
|
||||
@@ -751,14 +766,14 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return row;
|
||||
}
|
||||
|
||||
public IntersectionRow buildManyToManyDeleteChildren(Object parentBean) {
|
||||
public IntersectionRow buildManyToManyDeleteChildren(EntityBean parentBean) {
|
||||
|
||||
IntersectionRow row = new IntersectionRow(intersectionJoin.getTable());
|
||||
buildExport(row, parentBean);
|
||||
return row;
|
||||
}
|
||||
|
||||
public IntersectionRow buildManyToManyMapBean(Object parent, Object other) {
|
||||
public IntersectionRow buildManyToManyMapBean(EntityBean parent, EntityBean other) {
|
||||
|
||||
IntersectionRow row = new IntersectionRow(intersectionJoin.getTable());
|
||||
|
||||
@@ -767,11 +782,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return row;
|
||||
}
|
||||
|
||||
private void buildExport(IntersectionRow row, Object parentBean) {
|
||||
private void buildExport(IntersectionRow row, EntityBean parentBean) {
|
||||
|
||||
if (embeddedExportedProperties) {
|
||||
BeanProperty[] uids = descriptor.propertiesId();
|
||||
parentBean = 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);
|
||||
@@ -785,7 +800,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
* Set the predicates for lazy loading of the association.
|
||||
* Handles predicates for both OneToMany and ManyToMany.
|
||||
*/
|
||||
private void buildImport(IntersectionRow row, Object otherBean) {
|
||||
private void buildImport(IntersectionRow row, EntityBean otherBean) {
|
||||
|
||||
importedId.buildImport(row, otherBean);
|
||||
}
|
||||
@@ -793,12 +808,12 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
/**
|
||||
* Return true if the otherBean has an Id value.
|
||||
*/
|
||||
public boolean hasImportedId(Object otherBean) {
|
||||
public boolean hasImportedId(EntityBean otherBean) {
|
||||
|
||||
return null != targetDescriptor.getId(otherBean);
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, Object bean) {
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
if(!this.jsonSerialize){
|
||||
return;
|
||||
}
|
||||
@@ -819,7 +834,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, Object bean){
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
if(!this.jsonDeserialize){
|
||||
return;
|
||||
}
|
||||
@@ -836,7 +851,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
// probably empty array
|
||||
break;
|
||||
}
|
||||
Object detailBean = detailBeanState.getBean();
|
||||
EntityBean detailBean = (EntityBean)detailBeanState.getBean();
|
||||
add.addBean(detailBean);
|
||||
|
||||
if (bean != null && childMasterProperty != null){
|
||||
@@ -844,15 +859,12 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
childMasterProperty.setValue(detailBean, bean);
|
||||
detailBeanState.setLoaded(childMasterProperty.getName());
|
||||
}
|
||||
|
||||
detailBeanState.setLoadedState();
|
||||
|
||||
|
||||
if (!ctx.readArrayNext()){
|
||||
break;
|
||||
}
|
||||
} while(true);
|
||||
|
||||
setValue(bean, collection);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
private final boolean oneToOneExported;
|
||||
|
||||
private final boolean embeddedVersion;
|
||||
|
||||
private final boolean importedPrimaryKey;
|
||||
|
||||
private final LocalHelp localHelp;
|
||||
@@ -78,11 +76,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
// Overriding of the columns and use table alias of owning BeanDescriptor
|
||||
BeanEmbeddedMeta overrideMeta = BeanEmbeddedMetaFactory.create(owner, deploy, descriptor);
|
||||
embeddedProps = overrideMeta.getProperties();
|
||||
if (id) {
|
||||
embeddedVersion = false;
|
||||
} else {
|
||||
embeddedVersion = overrideMeta.isEmbeddedVersion();
|
||||
}
|
||||
embeddedPropsMap = new HashMap<String, BeanProperty>();
|
||||
for (int i = 0; i < embeddedProps.length; i++) {
|
||||
embeddedPropsMap.put(embeddedProps[i].getName(), embeddedProps[i]);
|
||||
@@ -91,7 +84,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
} else {
|
||||
embeddedProps = null;
|
||||
embeddedPropsMap = null;
|
||||
embeddedVersion = false;
|
||||
}
|
||||
localHelp = createHelp(embedded, oneToOneExported);
|
||||
}
|
||||
@@ -126,22 +118,22 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
public void cacheClear() {
|
||||
if (targetDescriptor.isBeanCaching() && relationshipProperty != null) {
|
||||
targetDescriptor.cacheClearCachedManyIds(relationshipProperty.getName());
|
||||
targetDescriptor.cacheManyPropClear(relationshipProperty.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void cacheDelete(boolean clearOnNull, Object bean) {
|
||||
public void cacheDelete(boolean clearOnNull, EntityBean bean) {
|
||||
if (targetDescriptor.isBeanCaching() && relationshipProperty != null) {
|
||||
Object assocBean = getValue(bean);
|
||||
if (assocBean != null) {
|
||||
Object parentId = targetDescriptor.getId(assocBean);
|
||||
Object parentId = targetDescriptor.getId((EntityBean)assocBean);
|
||||
if (parentId != null) {
|
||||
targetDescriptor.cacheRemoveCachedManyIds(parentId, relationshipProperty.getName());
|
||||
targetDescriptor.cacheManyPropRemove(parentId, relationshipProperty.getName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (clearOnNull) {
|
||||
targetDescriptor.cacheClearCachedManyIds(relationshipProperty.getName());
|
||||
targetDescriptor.cacheManyPropClear(relationshipProperty.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -249,8 +241,9 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
} else {
|
||||
int pos = 1;
|
||||
EntityBean parent = (EntityBean)parentId;
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
Object embVal = exportedProperties[i].getValue(parentId);
|
||||
Object embVal = exportedProperties[i].getValue(parent);
|
||||
q.setParameter(pos++, embVal);
|
||||
}
|
||||
}
|
||||
@@ -270,41 +263,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasChangedEmbedded(Object bean, Object oldValues) {
|
||||
|
||||
Object embValue = getValue(oldValues);
|
||||
if (embValue instanceof EntityBean) {
|
||||
// the embedded bean .. has its own old values
|
||||
return ((EntityBean) embValue)._ebean_getIntercept().isNewOrDirty();
|
||||
}
|
||||
if (embValue == null) {
|
||||
return getValue(bean) != null;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasChanged(Object bean, Object oldValues) {
|
||||
if (embedded) {
|
||||
return hasChangedEmbedded(bean, oldValues);
|
||||
}
|
||||
Object value = getValue(bean);
|
||||
Object oldVal = getValue(oldValues);
|
||||
if (oneToOneExported) {
|
||||
// FKey on other side
|
||||
return false;
|
||||
} else {
|
||||
if (value == null) {
|
||||
return oldVal != null;
|
||||
} else if (oldValues == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return importedId.hasChanged(value, oldVal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return meta data for the deployment of the embedded bean specific to this
|
||||
* property.
|
||||
@@ -342,13 +300,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return oneToOneExported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the associated bean has version properties.
|
||||
*/
|
||||
public boolean isEmbeddedVersion() {
|
||||
return embeddedVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* If true this bean maps to the primary key.
|
||||
*/
|
||||
@@ -364,7 +315,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return getPropertyType();
|
||||
}
|
||||
|
||||
public Object getCacheDataValue(Object bean){
|
||||
public Object getCacheDataValue(EntityBean bean){
|
||||
if (embedded) {
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
@@ -372,24 +323,19 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
if (ap == null){
|
||||
return null;
|
||||
} else {
|
||||
return targetDescriptor.getId(ap);
|
||||
return targetDescriptor.getId((EntityBean)ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setCacheDataValue(Object bean, Object cacheData, Object oldValues, boolean readOnly){
|
||||
@Override
|
||||
public void setCacheDataValue(EntityBean bean, Object cacheData){
|
||||
if (cacheData != null) {
|
||||
if (embedded){
|
||||
throw new RuntimeException();
|
||||
} else {
|
||||
T ref = targetDescriptor.createReference(Boolean.FALSE, cacheData, null);
|
||||
T ref = targetDescriptor.createReference(Boolean.FALSE, cacheData);
|
||||
setValue(bean, ref);
|
||||
if (oldValues != null){
|
||||
setValue(oldValues, ref);
|
||||
}
|
||||
if (readOnly){
|
||||
((EntityBean)ref)._ebean_intercept().setReadOnly(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -398,7 +344,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
* Return the Id values from the given bean.
|
||||
*/
|
||||
@Override
|
||||
public Object[] getAssocOneIdValues(Object bean) {
|
||||
public Object[] getAssocOneIdValues(EntityBean bean) {
|
||||
return targetDescriptor.getIdBinder().getIdValues(bean);
|
||||
}
|
||||
|
||||
@@ -451,15 +397,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return targetDescriptor.createEntityBean();
|
||||
}
|
||||
|
||||
public void elSetReference(Object bean) {
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value != null) {
|
||||
((EntityBean) value)._ebean_getIntercept().setReference();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
value = targetDescriptor.createEntityBean();
|
||||
@@ -495,13 +434,13 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
*/
|
||||
private ExportedProperty[] createExported() {
|
||||
|
||||
BeanProperty[] uids = descriptor.propertiesId();
|
||||
BeanProperty idProp = descriptor.getIdProperty();
|
||||
|
||||
ArrayList<ExportedProperty> list = new ArrayList<ExportedProperty>();
|
||||
|
||||
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 {
|
||||
@@ -515,8 +454,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
@@ -565,7 +504,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
boolean assignable = (type == null || owningType.isAssignableFrom(type));
|
||||
return localHelp.readSet(ctx, bean, assignable);
|
||||
}
|
||||
@@ -579,6 +518,24 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
// pass in null for the bean so any data read is ignored
|
||||
return localHelp.read(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
if (value instanceof EntityBean) {
|
||||
EntityBean embedded = (EntityBean)value;
|
||||
embedded._ebean_getIntercept().setEmbeddedOwner(bean, propertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
super.setValueIntercept(bean, value);
|
||||
if (value instanceof EntityBean) {
|
||||
EntityBean embedded = (EntityBean)value;
|
||||
embedded._ebean_getIntercept().setEmbeddedOwner(bean, propertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadIgnore(DbReadContext ctx) {
|
||||
@@ -615,7 +572,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
|
||||
abstract Object read(DbReadContext ctx) throws SQLException;
|
||||
|
||||
abstract Object readSet(DbReadContext ctx, Object bean, boolean assignAble) throws SQLException;
|
||||
abstract Object readSet(DbReadContext ctx, EntityBean bean, boolean assignAble) throws SQLException;
|
||||
|
||||
abstract void appendSelect(DbSqlContext ctx, boolean subQuery);
|
||||
|
||||
@@ -632,7 +589,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
Object readSet(DbReadContext ctx, Object bean, boolean assignable) throws SQLException {
|
||||
Object readSet(DbReadContext ctx, EntityBean bean, boolean assignable) throws SQLException {
|
||||
Object dbVal = read(ctx);
|
||||
if (bean != null && assignable) {
|
||||
// set back to the parent bean
|
||||
@@ -694,7 +651,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
Object readSet(DbReadContext ctx, Object bean, boolean assignable) throws SQLException {
|
||||
Object readSet(DbReadContext ctx, EntityBean bean, boolean assignable) throws SQLException {
|
||||
Object val = read(ctx);
|
||||
if (bean != null && assignable) {
|
||||
setValue(bean, val);
|
||||
@@ -733,16 +690,13 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
return existing;
|
||||
}
|
||||
|
||||
// parent always null for this case (but here to document)
|
||||
Object parent = null;
|
||||
|
||||
Boolean readOnly = ctx.isReadOnly();
|
||||
Object ref;
|
||||
if (targetInheritInfo != null) {
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
ref = rowDescriptor.createReference(readOnly, id, parent);
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
ref = rowDescriptor.createReference(readOnly, id);
|
||||
} else {
|
||||
ref = targetDescriptor.createReference(readOnly, id, parent);
|
||||
ref = targetDescriptor.createReference(readOnly, id);
|
||||
}
|
||||
|
||||
Object existingBean = ctx.getPersistenceContext().putIfAbsent(id, ref);
|
||||
@@ -802,7 +756,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
* Read and set a Reference bean.
|
||||
*/
|
||||
@Override
|
||||
Object readSet(DbReadContext ctx, Object bean, boolean assignable) throws SQLException {
|
||||
Object readSet(DbReadContext ctx, EntityBean bean, boolean assignable) throws SQLException {
|
||||
|
||||
Object dbVal = read(ctx);
|
||||
if (bean != null && assignable) {
|
||||
@@ -828,8 +782,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
Object parent = null;
|
||||
Object ref = targetDescriptor.createReference(ctx.isReadOnly(), id, parent);
|
||||
Object ref = targetDescriptor.createReference(ctx.isReadOnly(), id);
|
||||
|
||||
EntityBeanIntercept ebi = ((EntityBean) ref)._ebean_getIntercept();
|
||||
if (Boolean.TRUE.equals(ctx.isReadOnly())) {
|
||||
@@ -846,8 +799,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
@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);
|
||||
@@ -867,7 +819,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonWrite(WriteJsonContext ctx, Object bean) {
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null){
|
||||
@@ -878,20 +830,29 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> {
|
||||
// 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, value);
|
||||
refDesc.jsonWrite(ctx, (EntityBean)value);
|
||||
ctx.endAssocOne();
|
||||
ctx.popParentBean();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void jsonRead(ReadJsonContext ctx, Object bean){
|
||||
|
||||
T assocBean = targetDescriptor.jsonReadBean(ctx, name);
|
||||
setValue(bean, assocBean);
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
|
||||
@@ -89,7 +90,7 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
* Get the underlying compound type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object getValueUnderlying(Object bean) {
|
||||
public Object getValueUnderlying(EntityBean bean) {
|
||||
|
||||
Object value = getValue(bean);
|
||||
if (typeConverter != null){
|
||||
@@ -97,27 +98,7 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(Object bean) {
|
||||
return super.getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValueIntercept(Object bean) {
|
||||
return super.getValueIntercept(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Object bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValueIntercept(Object bean, Object value) {
|
||||
super.setValueIntercept(bean, value);
|
||||
}
|
||||
|
||||
|
||||
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
|
||||
|
||||
if (chain == null) {
|
||||
@@ -154,7 +135,7 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
|
||||
boolean assignable = (type == null || owningType.isAssignableFrom(type));
|
||||
|
||||
@@ -192,17 +173,17 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public void jsonWrite(WriteJsonContext ctx, Object bean) {
|
||||
public void jsonWrite(WriteJsonContext ctx, EntityBean bean) {
|
||||
|
||||
Object valueObject = getValueIntercept(bean);
|
||||
compoundType.jsonWrite(ctx, valueObject, name);
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJsonContext ctx, Object bean){
|
||||
public void jsonRead(ReadJsonContext ctx, EntityBean bean){
|
||||
|
||||
Object objValue = compoundType.jsonRead(ctx);
|
||||
setValue(bean, objValue);
|
||||
|
||||
@@ -73,7 +73,7 @@ public class BeanPropertyCompoundRoot {
|
||||
* Set the value of the property without interception or
|
||||
* PropertyChangeSupport.
|
||||
*/
|
||||
public void setRootValue(Object bean, Object value) {
|
||||
public void setRootValue(EntityBean bean, Object value) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
setter.set(bean, value);
|
||||
@@ -92,7 +92,7 @@ public class BeanPropertyCompoundRoot {
|
||||
/**
|
||||
* Set the value of the property.
|
||||
*/
|
||||
public void setRootValueIntercept(Object bean, Object value) {
|
||||
public void setRootValueIntercept(EntityBean bean, Object value) {
|
||||
try {
|
||||
if (bean instanceof EntityBean) {
|
||||
setter.setIntercept(bean, value);
|
||||
|
||||
+14
-17
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
|
||||
@@ -30,20 +31,21 @@ public class BeanPropertyCompoundScalar extends BeanProperty {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object getValue(Object valueObject) {
|
||||
if (typeConverter != null){
|
||||
valueObject = typeConverter.unwrapValue(valueObject);
|
||||
public Object getValue(EntityBean valueObject) {
|
||||
Object val = valueObject;
|
||||
if (typeConverter != null){
|
||||
val = typeConverter.unwrapValue(val);
|
||||
}
|
||||
return ctProperty.getValue(valueObject);
|
||||
return ctProperty.getValue(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(Object bean, Object value) {
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
setValueInCompound(bean, value, false);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setValueInCompound(Object bean, Object value, boolean intercept) {
|
||||
public void setValueInCompound(EntityBean bean, Object value, boolean intercept) {
|
||||
|
||||
Object compoundValue = ctProperty.setValue(bean, value);
|
||||
|
||||
@@ -65,7 +67,7 @@ public class BeanPropertyCompoundScalar extends BeanProperty {
|
||||
* No interception on embedded scalar values inside a CVO.
|
||||
*/
|
||||
@Override
|
||||
public void setValueIntercept(Object bean, Object value) {
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
setValueInCompound(bean, value, true);
|
||||
}
|
||||
|
||||
@@ -73,28 +75,23 @@ public class BeanPropertyCompoundScalar extends BeanProperty {
|
||||
* No interception on embedded scalar values inside a CVO.
|
||||
*/
|
||||
@Override
|
||||
public Object getValueIntercept(Object bean) {
|
||||
public Object getValueIntercept(EntityBean bean) {
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object elGetValue(Object bean) {
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
return getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elSetReference(Object bean) {
|
||||
super.elSetReference(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void elSetValue(Object 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.avaje.ebean.Transaction;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.common.BeanSet;
|
||||
import com.avaje.ebeaninternal.server.text.json.WriteJsonContext;
|
||||
|
||||
@@ -72,15 +73,12 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
this.set = set;
|
||||
}
|
||||
|
||||
public void addBean(Object bean) {
|
||||
public void addBean(EntityBean bean) {
|
||||
set.add(bean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal add bypassing any modify listening.
|
||||
*/
|
||||
public void add(BeanCollection<?> collection, Object bean) {
|
||||
public void add(BeanCollection<?> collection, EntityBean bean) {
|
||||
collection.internalAdd(bean);
|
||||
}
|
||||
|
||||
@@ -95,20 +93,20 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
return beanSet;
|
||||
}
|
||||
|
||||
public BeanCollection<T> createReference(Object parentBean, String propertyName) {
|
||||
public BeanCollection<T> createReference(EntityBean parentBean, String propertyName) {
|
||||
|
||||
BeanSet<T> beanSet = new BeanSet<T>(loader, parentBean, propertyName);
|
||||
beanSet.setModifyListening(many.getModifyListenMode());
|
||||
return beanSet;
|
||||
}
|
||||
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, Object parentBean) {
|
||||
public void refresh(EbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
|
||||
|
||||
BeanSet<?> newBeanSet = (BeanSet<?>)server.findSet(query, t);
|
||||
refresh(newBeanSet, parentBean);
|
||||
}
|
||||
|
||||
public void refresh(BeanCollection<?> bc, Object parentBean) {
|
||||
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
|
||||
|
||||
BeanSet<?> newBeanSet = (BeanSet<?>)bc;
|
||||
|
||||
@@ -158,7 +156,7 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
if (count++ > 0){
|
||||
ctx.appendComma();
|
||||
}
|
||||
targetDescriptor.jsonWrite(ctx, detailBean);
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)detailBean);
|
||||
}
|
||||
ctx.endAssocMany();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.avaje.ebean.event.BeanPersistListener;
|
||||
public class ChainedBeanPersistListener<T> implements BeanPersistListener<T> {
|
||||
|
||||
private final List<BeanPersistListener<T>> list;
|
||||
|
||||
private final BeanPersistListener<T>[] chain;
|
||||
|
||||
/**
|
||||
|
||||
@@ -127,7 +127,7 @@ public class DRawSqlSelect {
|
||||
sqlTree.setSummary(desc.getName());
|
||||
|
||||
LinkedHashSet<String> includedProps = new LinkedHashSet<String>();
|
||||
SqlTreeProperties selectProps = new SqlTreeProperties();
|
||||
SqlTreeProperties selectProps = new SqlTreeProperties(desc);
|
||||
|
||||
for (int i = 0; i < selectColumns.length; i++) {
|
||||
|
||||
@@ -156,7 +156,6 @@ public class DRawSqlSelect {
|
||||
}
|
||||
}
|
||||
|
||||
selectProps.setIncludedProperties(includedProps);
|
||||
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, null, withId);
|
||||
sqlTree.setRootNode(sqlRoot);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
import java.util.Map;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.EntityBeanIntercept;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
@@ -72,12 +73,12 @@ public interface DbReadContext {
|
||||
/**
|
||||
* Set back the bean that has just been loaded with its id.
|
||||
*/
|
||||
public void setLoadedBean(Object loadedBean, Object id, Object lazyLoadParentId);
|
||||
public void setLoadedBean(EntityBean loadedBean, Object id, Object lazyLoadParentId);
|
||||
|
||||
/**
|
||||
* Set back the 'detail' bean that has just been loaded.
|
||||
*/
|
||||
public void setLoadedManyBean(Object loadedBean);
|
||||
public void setLoadedManyBean(EntityBean loadedBean);
|
||||
|
||||
/**
|
||||
* Return the query mode.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
|
||||
/**
|
||||
@@ -32,7 +33,7 @@ public class ExportedProperty {
|
||||
/**
|
||||
* Return the property value from the bean.
|
||||
*/
|
||||
public Object getValue(Object bean){
|
||||
public Object getValue(EntityBean bean){
|
||||
return property.getValue(bean);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.HashMap;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
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.parse.DeployInheritInfo;
|
||||
@@ -223,7 +224,7 @@ public class InheritInfo {
|
||||
/**
|
||||
* Create an EntityBean for this type.
|
||||
*/
|
||||
public Object createBean() {
|
||||
public EntityBean createBean() {
|
||||
return descriptor.createBean();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectGetter;
|
||||
|
||||
/**
|
||||
* For abstract classes that hold the id property we need to
|
||||
* use reflection to get the id values some times.
|
||||
* <p>
|
||||
* This provides the BeanReflectGetter objects to do that.
|
||||
* </p>
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class ReflectGetter {
|
||||
|
||||
/**
|
||||
* Create a reflection based BeanReflectGetter for getting the
|
||||
* id from abstract inheritance hierarchy object.
|
||||
*/
|
||||
public static BeanReflectGetter create(DeployBeanProperty prop) {
|
||||
|
||||
if (!prop.isId()){
|
||||
// not expecting this to ever be used/called
|
||||
return new NonIdGetter(prop.getFullBeanName());
|
||||
|
||||
} else {
|
||||
String property = prop.getFullBeanName();
|
||||
Method readMethod = prop.getReadMethod();
|
||||
if (readMethod == null){
|
||||
String m = "Abstract class with no readMethod for "+property;
|
||||
throw new RuntimeException(m);
|
||||
}
|
||||
return new IdGetter(property, readMethod);
|
||||
}
|
||||
}
|
||||
|
||||
public static class IdGetter implements BeanReflectGetter {
|
||||
|
||||
public static final Object[] NO_ARGS = new Object[0];
|
||||
|
||||
private final Method readMethod;
|
||||
private final String property;
|
||||
|
||||
public IdGetter(String property, Method readMethod) {
|
||||
this.property = property;
|
||||
this.readMethod = readMethod;
|
||||
}
|
||||
|
||||
public Object get(Object bean) {
|
||||
try {
|
||||
return readMethod.invoke(bean, NO_ARGS);
|
||||
} catch (Exception e) {
|
||||
String m = "Error on ["+property+"] using readMethod "+readMethod;
|
||||
throw new RuntimeException(m, e);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getIntercept(Object bean) {
|
||||
return get(bean);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NonIdGetter implements BeanReflectGetter {
|
||||
|
||||
private final String property;
|
||||
|
||||
public NonIdGetter(String property) {
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public Object get(Object bean) {
|
||||
|
||||
String m = "Not expecting this method to be called on ["+property
|
||||
+"] as it is a NON ID property on an abstract class";
|
||||
throw new RuntimeException(m);
|
||||
}
|
||||
|
||||
public Object getIntercept(Object bean) {
|
||||
return get(bean);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.reflect.BeanReflectSetter;
|
||||
|
||||
/**
|
||||
* A place holder for BeanReflectSetter that should never be called.
|
||||
* <p>
|
||||
* This is for properties of classes that are abstract and at the root
|
||||
* of an inheritance hierarchy.
|
||||
* </p>
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class ReflectSetter {
|
||||
|
||||
/**
|
||||
* Creates place holder objects that should never be called.
|
||||
*/
|
||||
public static BeanReflectSetter create(DeployBeanProperty prop) {
|
||||
|
||||
String fullName = prop.getFullBeanName();
|
||||
Method writeMethod = prop.getWriteMethod();
|
||||
return new RefCalled(fullName, writeMethod);
|
||||
}
|
||||
|
||||
static class RefCalled implements BeanReflectSetter {
|
||||
|
||||
final String fullName;
|
||||
final Method writeMethod;
|
||||
|
||||
RefCalled(String fullName, Method writeMethod) {
|
||||
this.fullName = fullName;
|
||||
this.writeMethod = writeMethod;
|
||||
}
|
||||
public void set(Object bean, Object value) {
|
||||
Object[] a = new Object[1];
|
||||
a[0] = value;
|
||||
try {
|
||||
writeMethod.invoke(bean, a);
|
||||
} catch (Exception e) {
|
||||
String beanType = bean == null ? "null" : bean.getClass().toString();
|
||||
String msg = "Error setting value on "+fullName+" value["+value+"] on type["+beanType+"]";
|
||||
throw new RuntimeException(msg, e);
|
||||
}
|
||||
}
|
||||
public void setIntercept(Object bean, Object value) {
|
||||
String msg = "Not expecting setIntercept to be called. Refer Bug 368";
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
|
||||
@@ -103,7 +104,7 @@ public final class TableJoin {
|
||||
}
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, Object bean, Class<?> type) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean, Class<?> type) throws SQLException {
|
||||
for (int i = 0, x = properties.length; i < x; i++) {
|
||||
properties[i].readSet(ctx, bean, type);
|
||||
}
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
@@ -17,7 +18,7 @@ public class GeneratedCounter implements GeneratedProperty {
|
||||
/**
|
||||
* Always returns a 1.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
Integer i = Integer.valueOf(1);
|
||||
return BasicTypeConverter.convert(i, numberType);
|
||||
}
|
||||
@@ -25,7 +26,7 @@ public class GeneratedCounter implements GeneratedProperty {
|
||||
/**
|
||||
* Increments the current value by one.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
Number currVal = (Number) prop.getValue(bean);
|
||||
Integer nextVal = Integer.valueOf(currVal.intValue() + 1);
|
||||
return BasicTypeConverter.convert(nextVal, numberType);
|
||||
@@ -38,6 +39,11 @@ public class GeneratedCounter implements GeneratedProperty {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert setting initial counter value to 1.
|
||||
*/
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -14,14 +15,14 @@ public class GeneratedCounterInteger implements GeneratedProperty {
|
||||
/**
|
||||
* Always returns a 1.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return Integer.valueOf(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the current value by one.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
Integer i = (Integer) prop.getValue(bean);
|
||||
return Integer.valueOf(i.intValue() + 1);
|
||||
}
|
||||
@@ -32,6 +33,11 @@ public class GeneratedCounterInteger implements GeneratedProperty {
|
||||
public boolean includeInUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert setting initial counter value to 1.
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -14,14 +15,14 @@ public class GeneratedCounterLong implements GeneratedProperty {
|
||||
/**
|
||||
* Always returns a 1.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return Long.valueOf(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the current value by one.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
Long i = (Long) prop.getValue(bean);
|
||||
return Long.valueOf(i.longValue() + 1);
|
||||
}
|
||||
@@ -33,6 +34,11 @@ public class GeneratedCounterLong implements GeneratedProperty {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert setting initial counter value to 1.
|
||||
*/
|
||||
|
||||
+8
-2
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -12,14 +13,14 @@ public class GeneratedInsertDate implements GeneratedProperty {
|
||||
/**
|
||||
* Return the current time as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Just returns the beans original insert timestamp value.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return prop.getValue(bean);
|
||||
}
|
||||
|
||||
@@ -30,6 +31,11 @@ public class GeneratedInsertDate implements GeneratedProperty {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true.
|
||||
*/
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -10,14 +11,14 @@ public class GeneratedInsertLong implements GeneratedProperty {
|
||||
/**
|
||||
* Return the current time as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return Long.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Just returns the beans original insert timestamp value.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return prop.getValue(bean);
|
||||
}
|
||||
|
||||
@@ -28,6 +29,11 @@ public class GeneratedInsertLong implements GeneratedProperty {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true.
|
||||
*/
|
||||
|
||||
+8
-2
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -12,14 +13,14 @@ public class GeneratedInsertTimestamp implements GeneratedProperty {
|
||||
/**
|
||||
* Return the current time as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Just returns the beans original insert timestamp value.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return prop.getValue(bean);
|
||||
}
|
||||
|
||||
@@ -29,6 +30,11 @@ public class GeneratedInsertTimestamp implements GeneratedProperty {
|
||||
public boolean includeInUpdate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true.
|
||||
|
||||
+9
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -11,12 +12,12 @@ public interface GeneratedProperty {
|
||||
/**
|
||||
* Get the generated insert value for a specific property of a bean.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean);
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean);
|
||||
|
||||
/**
|
||||
* Get the generated update value for a specific property of a bean.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean);
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean);
|
||||
|
||||
/**
|
||||
* Return true if this should always be includes in an update statement.
|
||||
@@ -25,6 +26,12 @@ public interface GeneratedProperty {
|
||||
* </p>
|
||||
*/
|
||||
public boolean includeInUpdate();
|
||||
|
||||
/**
|
||||
* Return true if the property should be included in an update even if
|
||||
* it is not loaded (ie. Last Updated Timestamp).
|
||||
*/
|
||||
public boolean includeInAllUpdates();
|
||||
|
||||
/**
|
||||
* Return true if this should be included in insert statements.
|
||||
|
||||
+8
-2
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -13,14 +14,14 @@ public class GeneratedUpdateDate implements GeneratedProperty {
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Date(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@@ -30,6 +31,11 @@ public class GeneratedUpdateDate implements GeneratedProperty {
|
||||
public boolean includeInUpdate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert.
|
||||
|
||||
+8
-2
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -10,14 +11,14 @@ public class GeneratedUpdateLong implements GeneratedProperty {
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return Long.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return Long.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@@ -28,6 +29,11 @@ public class GeneratedUpdateLong implements GeneratedProperty {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert.
|
||||
*/
|
||||
|
||||
+8
-2
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
/**
|
||||
@@ -12,14 +13,14 @@ public class GeneratedUpdateTimestamp implements GeneratedProperty {
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getInsertValue(BeanProperty prop, Object bean) {
|
||||
public Object getInsertValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return now as a Timestamp.
|
||||
*/
|
||||
public Object getUpdateValue(BeanProperty prop, Object bean) {
|
||||
public Object getUpdateValue(BeanProperty prop, EntityBean bean) {
|
||||
return new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@@ -30,6 +31,11 @@ public class GeneratedUpdateTimestamp implements GeneratedProperty {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeInAllUpdates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Include this in every insert.
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -42,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.
|
||||
*/
|
||||
@@ -81,7 +88,7 @@ public interface IdBinder {
|
||||
/**
|
||||
* Return the id values for a given bean.
|
||||
*/
|
||||
public Object[] getIdValues(Object bean);
|
||||
public Object[] getIdValues(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Build a string of the logical expressions.
|
||||
@@ -129,7 +136,7 @@ public interface IdBinder {
|
||||
* Read the id value from the result set and set it to the bean also returning
|
||||
* it.
|
||||
*/
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException;
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* Ignore the appropriate number of scalar properties for this id.
|
||||
@@ -152,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.
|
||||
* <p>
|
||||
@@ -168,6 +170,6 @@ public interface IdBinder {
|
||||
* If the bean is not null, then the value is set to the bean.
|
||||
* </p>
|
||||
*/
|
||||
public Object convertSetId(Object idValue, Object bean);
|
||||
public Object convertSetId(Object idValue, EntityBean bean);
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -21,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<String> 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<String> 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(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(Object bean) {
|
||||
bean = embIdProperty.getValue(bean);
|
||||
Object[] bindvalues = new Object[props.length];
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
bindvalues[i] = props[i].getValue(bean);
|
||||
}
|
||||
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(value);
|
||||
}
|
||||
return bindvalues;
|
||||
}
|
||||
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
Object embFieldValue = props[i].getValue(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(value);
|
||||
props[i].bind(dataBind, embFieldValue);
|
||||
}
|
||||
}
|
||||
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
|
||||
Object 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(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();
|
||||
}
|
||||
|
||||
Object 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, Object 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, Object bean) {
|
||||
|
||||
// can not cast/convert if it is embedded
|
||||
if (bean != null) {
|
||||
// support PropertyChangeSupport
|
||||
embIdProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
|
||||
return idValue;
|
||||
}
|
||||
return idValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -20,8 +22,6 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
|
||||
private static final String bindIdSql = "";
|
||||
|
||||
private static final BeanProperty[] properties = new BeanProperty[0];
|
||||
|
||||
public IdBinderEmpty() {
|
||||
|
||||
}
|
||||
@@ -41,6 +41,11 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanProperty getBeanProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getIdProperty() {
|
||||
return null;
|
||||
}
|
||||
@@ -58,10 +63,6 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
return "";
|
||||
}
|
||||
|
||||
public BeanProperty[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
return bindIdSql;
|
||||
}
|
||||
@@ -90,7 +91,7 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object[] getIdValues(Object bean) {
|
||||
public Object[] getIdValues(EntityBean bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -109,7 +110,7 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
public void loadIgnore(DbReadContext ctx) {
|
||||
}
|
||||
|
||||
public Object readSet(DbReadContext ctx, Object bean) throws SQLException {
|
||||
public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -120,7 +121,7 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
|
||||
}
|
||||
|
||||
public Object convertSetId(Object idValue, Object bean) {
|
||||
public Object convertSetId(Object idValue, EntityBean bean) {
|
||||
return idValue;
|
||||
}
|
||||
|
||||
@@ -129,7 +130,6 @@ public final class IdBinderEmpty implements IdBinder {
|
||||
}
|
||||
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.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.
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*/
|
||||
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<String> 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(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(Object 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<String, ?> uidMap = (Map<String, ?>) 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<String,Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
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<String,Object> map = (Map<String,Object>)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, Object bean) throws SQLException {
|
||||
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
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<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
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<String, ?> uidMap = (Map<String, ?>) 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<String, ?> uidMap = (Map<String, ?>) 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, Object 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<String,Object> newMap = new LinkedHashMap<String, Object>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
@@ -24,8 +26,6 @@ public final class IdBinderSimple implements IdBinder {
|
||||
|
||||
private final String bindIdSql;
|
||||
|
||||
private final BeanProperty[] properties;
|
||||
|
||||
private final Class<?> expectedType;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@@ -35,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()+" = ? ");
|
||||
}
|
||||
|
||||
@@ -44,32 +42,37 @@ public final class IdBinderSimple implements IdBinder {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
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();
|
||||
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();
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildSelectExpressionChain(String prefix, List<String> 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();
|
||||
}
|
||||
|
||||
@@ -87,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(Object 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, Object 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, Object bean) {
|
||||
|
||||
if (!idValue.getClass().equals(expectedType)){
|
||||
idValue = scalarType.toBeanType(idValue);
|
||||
}
|
||||
|
||||
if (bean != null) {
|
||||
// support PropertyChangeSupport
|
||||
idProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
|
||||
return idValue;
|
||||
}
|
||||
return idValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
|
||||
@@ -48,22 +49,17 @@ public interface ImportedId {
|
||||
/**
|
||||
* Append to the DML statement to the where clause.
|
||||
*/
|
||||
public void dmlWhere(GenerateDmlRequest request, Object bean);
|
||||
|
||||
/**
|
||||
* Return true if the id value has changed.
|
||||
*/
|
||||
public boolean hasChanged(Object bean, Object oldValues);
|
||||
public void dmlWhere(GenerateDmlRequest request, EntityBean bean);
|
||||
|
||||
/**
|
||||
* Bind the value from the bean.
|
||||
*/
|
||||
public Object bind(BindableRequest request, Object bean, boolean bindNull) throws SQLException;
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* For inserting into ManyToMany intersection.
|
||||
*/
|
||||
public void buildImport(IntersectionRow row, Object other);
|
||||
public void buildImport(IntersectionRow row, EntityBean other);
|
||||
|
||||
/**
|
||||
* Used to derive a missing concatenated key from multiple imported keys.
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.sql.SQLException;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanFkeyProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
@@ -68,7 +69,7 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
}
|
||||
}
|
||||
|
||||
public void dmlWhere(GenerateDmlRequest request, Object bean){
|
||||
public void dmlWhere(GenerateDmlRequest request, EntityBean bean){
|
||||
|
||||
Object embeddedId = null;
|
||||
if (bean != null) {
|
||||
@@ -82,10 +83,10 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
EntityBean embedded = (EntityBean)embeddedId;
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (imported[i].owner.isDbUpdatable()) {
|
||||
Object value = imported[i].foreignProperty.getValue(embeddedId);
|
||||
Object value = imported[i].foreignProperty.getValue(embedded);
|
||||
if (value == null){
|
||||
request.appendColumnIsNull(imported[i].localDbColumn);
|
||||
} else {
|
||||
@@ -96,14 +97,7 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChanged(Object bean, Object oldValues) {
|
||||
Object id = foreignAssocOne.getValue(bean);
|
||||
Object oldId = foreignAssocOne.getValue(oldValues);
|
||||
|
||||
return !ValueUtil.areEqual(id, oldId);
|
||||
}
|
||||
|
||||
public Object bind(BindableRequest request, Object bean, boolean bindNull) throws SQLException {
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
Object embeddedId = null;
|
||||
|
||||
@@ -114,15 +108,16 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
if (embeddedId == null){
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (imported[i].owner.isUpdateable()) {
|
||||
request.bind(null, imported[i].foreignProperty, imported[i].localDbColumn, true);
|
||||
request.bind(null, imported[i].foreignProperty, imported[i].localDbColumn);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
EntityBean embedded = (EntityBean)embeddedId;
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (imported[i].owner.isUpdateable()) {
|
||||
Object scalarValue = imported[i].foreignProperty.getValue(embeddedId);
|
||||
request.bind(scalarValue, imported[i].foreignProperty, imported[i].localDbColumn, true);
|
||||
Object scalarValue = imported[i].foreignProperty.getValue(embedded);
|
||||
request.bind(scalarValue, imported[i].foreignProperty, imported[i].localDbColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,9 +125,9 @@ public class ImportedIdEmbedded implements ImportedId {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void buildImport(IntersectionRow row, Object other){
|
||||
public void buildImport(IntersectionRow row, EntityBean other){
|
||||
|
||||
Object embeddedId = foreignAssocOne.getValue(other);
|
||||
EntityBean embeddedId = (EntityBean)foreignAssocOne.getValue(other);
|
||||
if (embeddedId == null){
|
||||
String msg = "Foreign Key value null?";
|
||||
throw new PersistenceException(msg);
|
||||
|
||||
@@ -2,13 +2,13 @@ package com.avaje.ebeaninternal.server.deploy.id;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
|
||||
import com.avaje.ebeaninternal.server.persist.dmlbind.BindableRequest;
|
||||
import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
|
||||
/**
|
||||
* Imported concatenated id that is not embedded.
|
||||
@@ -55,7 +55,7 @@ public class ImportedIdMultiple implements ImportedId {
|
||||
}
|
||||
}
|
||||
|
||||
public void dmlWhere(GenerateDmlRequest request, Object bean){
|
||||
public void dmlWhere(GenerateDmlRequest request, EntityBean bean){
|
||||
if (bean == null){
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
request.appendColumnIsNull(imported[i].localDbColumn);
|
||||
@@ -72,32 +72,19 @@ public class ImportedIdMultiple implements ImportedId {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChanged(Object bean, Object oldValues) {
|
||||
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
Object id = imported[i].foreignProperty.getValue(bean);
|
||||
Object oldId = imported[i].foreignProperty.getValue(oldValues);
|
||||
if (!ValueUtil.areEqual(id, oldId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public Object bind(BindableRequest request, Object bean, boolean bindNull) throws SQLException {
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
if (imported[i].owner.isUpdateable()) {
|
||||
Object scalarValue = imported[i].foreignProperty.getValue(bean);
|
||||
request.bind(scalarValue, imported[i].foreignProperty, imported[i].localDbColumn, true);
|
||||
request.bind(scalarValue, imported[i].foreignProperty, imported[i].localDbColumn);
|
||||
}
|
||||
}
|
||||
// hmmm, not worrying about this just yet
|
||||
return null;
|
||||
}
|
||||
|
||||
public void buildImport(IntersectionRow row, Object other){
|
||||
public void buildImport(IntersectionRow row, EntityBean other){
|
||||
|
||||
for (int i = 0; i < imported.length; i++) {
|
||||
Object scalarValue = imported[i].foreignProperty.getValue(other);
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.core.InternString;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanFkeyProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -15,7 +16,6 @@ import com.avaje.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import com.avaje.ebeaninternal.server.deploy.IntersectionRow;
|
||||
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
|
||||
import com.avaje.ebeaninternal.server.persist.dmlbind.BindableRequest;
|
||||
import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
|
||||
/**
|
||||
* Single scalar imported id.
|
||||
@@ -90,11 +90,11 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
return localDbColumn;
|
||||
}
|
||||
|
||||
private Object getIdValue(Object bean) {
|
||||
return foreignProperty.getValueWithInheritance(bean);
|
||||
}
|
||||
private Object getIdValue(EntityBean bean) {
|
||||
return foreignProperty.getValue(bean);
|
||||
}
|
||||
|
||||
public void buildImport(IntersectionRow row, Object other){
|
||||
public void buildImport(IntersectionRow row, EntityBean other){
|
||||
|
||||
Object value = getIdValue(other);
|
||||
if (value == null){
|
||||
@@ -114,7 +114,7 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
request.appendColumn(localDbColumn);
|
||||
}
|
||||
|
||||
public void dmlWhere(GenerateDmlRequest request, Object bean){
|
||||
public void dmlWhere(GenerateDmlRequest request, EntityBean bean){
|
||||
|
||||
if (owner.isDbUpdatable()){
|
||||
Object value = null;
|
||||
@@ -129,25 +129,13 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasChanged(Object bean, Object oldValues) {
|
||||
|
||||
Object id = getIdValue(bean);
|
||||
|
||||
if (oldValues != null){
|
||||
Object oldId = getIdValue(oldValues);
|
||||
return !ValueUtil.areEqual(id, oldId);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Object bind(BindableRequest request, Object bean, boolean bindNull) throws SQLException {
|
||||
public Object bind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
Object value = null;
|
||||
if (bean != null){
|
||||
value = getIdValue(bean);
|
||||
}
|
||||
request.bind(value, foreignProperty, localDbColumn, bindNull);
|
||||
request.bind(value, foreignProperty, localDbColumn);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
+12
-25
@@ -62,11 +62,6 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
private LinkedHashMap<String, DeployBeanProperty> propMap = new LinkedHashMap<String, DeployBeanProperty>();
|
||||
|
||||
/**
|
||||
* The type of bean this describes.
|
||||
*/
|
||||
private final Class<T> beanType;
|
||||
|
||||
private EntityType entityType;
|
||||
|
||||
private final Map<String, DeployNamedQuery> namedQueries = new LinkedHashMap<String, DeployNamedQuery>();
|
||||
@@ -104,7 +99,7 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* The concurrency mode for beans of this type.
|
||||
*/
|
||||
private ConcurrencyMode concurrencyMode = ConcurrencyMode.ALL;
|
||||
private ConcurrencyMode concurrencyMode;
|
||||
|
||||
private boolean updateChangesOnly;
|
||||
|
||||
@@ -131,11 +126,12 @@ public class DeployBeanDescriptor<T> {
|
||||
* faster than reflection at this stage.
|
||||
*/
|
||||
private BeanReflect beanReflect;
|
||||
private String[] properties;
|
||||
|
||||
/**
|
||||
* The EntityBean type used to create new EntityBeans.
|
||||
*/
|
||||
private Class<?> factoryType;
|
||||
private Class<T> beanType;
|
||||
|
||||
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
|
||||
private List<BeanPersistListener<T>> persistListeners = new ArrayList<BeanPersistListener<T>>();
|
||||
@@ -298,6 +294,14 @@ public class DeployBeanDescriptor<T> {
|
||||
return namedUpdates;
|
||||
}
|
||||
|
||||
public String[] getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(String[] props) {
|
||||
this.properties = props;
|
||||
}
|
||||
|
||||
public BeanReflect getBeanReflect() {
|
||||
return beanReflect;
|
||||
}
|
||||
@@ -309,23 +313,6 @@ public class DeployBeanDescriptor<T> {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class type this BeanDescriptor describes.
|
||||
*/
|
||||
public Class<?> getFactoryType() {
|
||||
return factoryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the class used to create new EntityBean instances.
|
||||
* <p>
|
||||
* Normally this would be a subclass dynamically generated for this bean.
|
||||
* </p>
|
||||
*/
|
||||
public void setFactoryType(Class<?> factoryType) {
|
||||
this.factoryType = factoryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the BeanReflect used to create new instances of an EntityBean. This
|
||||
* could use reflection or code generation to do this.
|
||||
@@ -350,7 +337,7 @@ public class DeployBeanDescriptor<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the reference options.
|
||||
* Return the cache options.
|
||||
*/
|
||||
public CacheOptions getCacheOptions() {
|
||||
return cacheOptions;
|
||||
|
||||
@@ -198,6 +198,8 @@ public class DeployBeanProperty {
|
||||
*/
|
||||
private Method writeMethod;
|
||||
|
||||
private int propertyIndex;
|
||||
|
||||
private BeanReflectGetter getter;
|
||||
|
||||
private BeanReflectSetter setter;
|
||||
@@ -410,6 +412,14 @@ public class DeployBeanProperty {
|
||||
this.scalarType = scalarType;
|
||||
}
|
||||
|
||||
public int getPropertyIndex() {
|
||||
return propertyIndex;
|
||||
}
|
||||
|
||||
public void setPropertyIndex(int propertyIndex) {
|
||||
this.propertyIndex = propertyIndex;
|
||||
}
|
||||
|
||||
public BeanReflectGetter getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
+305
-305
@@ -5,6 +5,9 @@ import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
|
||||
@@ -20,347 +23,344 @@ import com.avaje.ebeaninternal.server.deploy.TableJoin;
|
||||
*/
|
||||
public class DeployBeanPropertyLists {
|
||||
|
||||
private BeanProperty derivedFirstVersionProp;
|
||||
private static final Logger logger = LoggerFactory.getLogger(DeployBeanPropertyLists.class);
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
private BeanProperty versionProperty;
|
||||
|
||||
private final LinkedHashMap<String, BeanProperty> propertyMap;
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final ArrayList<BeanProperty> ids = new ArrayList<BeanProperty>();
|
||||
private final LinkedHashMap<String, BeanProperty> propertyMap;
|
||||
|
||||
private final ArrayList<BeanProperty> version = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> ids = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> local = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> local = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> manys = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> nonManys = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> manys = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> nonManys = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> ones = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> ones = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> onesExported = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> onesExported = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> onesImported = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> onesImported = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> embedded = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> embedded = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> baseScalar = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> baseScalar = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanPropertyCompound> baseCompound = new ArrayList<BeanPropertyCompound>();
|
||||
private final ArrayList<BeanPropertyCompound> baseCompound = new ArrayList<BeanPropertyCompound>();
|
||||
|
||||
private final ArrayList<BeanProperty> transients = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> transients = new ArrayList<BeanProperty>();
|
||||
|
||||
private final ArrayList<BeanProperty> nonTransients = new ArrayList<BeanProperty>();
|
||||
private final ArrayList<BeanProperty> nonTransients = new ArrayList<BeanProperty>();
|
||||
|
||||
private final TableJoin[] tableJoins;
|
||||
private final TableJoin[] tableJoins;
|
||||
|
||||
private final BeanPropertyAssocOne<?> unidirectional;
|
||||
private final BeanPropertyAssocOne<?> unidirectional;
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
|
||||
this.desc = desc;
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
|
||||
this.desc = desc;
|
||||
|
||||
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
|
||||
if (deployUnidirectional == null) {
|
||||
unidirectional = null;
|
||||
DeployBeanPropertyAssocOne<?> deployUnidirectional = deploy.getUnidirectional();
|
||||
if (deployUnidirectional == null) {
|
||||
unidirectional = null;
|
||||
} else {
|
||||
unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
|
||||
}
|
||||
|
||||
this.propertyMap = new LinkedHashMap<String, BeanProperty>();
|
||||
|
||||
Iterator<DeployBeanProperty> deployIt = deploy.propertiesAll();
|
||||
while (deployIt.hasNext()) {
|
||||
DeployBeanProperty deployProp = deployIt.next();
|
||||
BeanProperty beanProp = createBeanProperty(owner, deployProp);
|
||||
propertyMap.put(beanProp.getName(), beanProp);
|
||||
}
|
||||
|
||||
Iterator<BeanProperty> it = propertyMap.values().iterator();
|
||||
|
||||
int order = 0;
|
||||
while (it.hasNext()) {
|
||||
BeanProperty prop = it.next();
|
||||
prop.setDeployOrder(order++);
|
||||
allocateToList(prop);
|
||||
}
|
||||
|
||||
List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
|
||||
tableJoins = new TableJoin[deployTableJoins.size()];
|
||||
for (int i = 0; i < deployTableJoins.size(); i++) {
|
||||
tableJoins[i] = new TableJoin(deployTableJoins.get(i), propertyMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unidirectional.
|
||||
*/
|
||||
public BeanPropertyAssocOne<?> getUnidirectional() {
|
||||
return unidirectional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the property to a list.
|
||||
*/
|
||||
private void allocateToList(BeanProperty prop) {
|
||||
if (prop.isTransient()) {
|
||||
transients.add(prop);
|
||||
return;
|
||||
}
|
||||
if (prop.isId()) {
|
||||
ids.add(prop);
|
||||
return;
|
||||
} else {
|
||||
nonTransients.add(prop);
|
||||
}
|
||||
|
||||
if (desc.getInheritInfo() != null && prop.isLocal()) {
|
||||
local.add(prop);
|
||||
}
|
||||
|
||||
if (prop instanceof BeanPropertyAssocMany<?>) {
|
||||
manys.add(prop);
|
||||
|
||||
} else {
|
||||
nonManys.add(prop);
|
||||
if (prop instanceof BeanPropertyAssocOne<?>) {
|
||||
if (prop.isEmbedded()) {
|
||||
embedded.add(prop);
|
||||
} else {
|
||||
unidirectional = new BeanPropertyAssocOne(owner, desc, deployUnidirectional);
|
||||
ones.add(prop);
|
||||
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
|
||||
if (assocOne.isOneToOneExported()) {
|
||||
onesExported.add(prop);
|
||||
} else {
|
||||
onesImported.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
this.propertyMap = new LinkedHashMap<String, BeanProperty>();
|
||||
|
||||
Iterator<DeployBeanProperty> deployIt = deploy.propertiesAll();
|
||||
while (deployIt.hasNext()) {
|
||||
DeployBeanProperty deployProp = deployIt.next();
|
||||
BeanProperty beanProp = createBeanProperty(owner, deployProp);
|
||||
propertyMap.put(beanProp.getName(), beanProp);
|
||||
} else {
|
||||
// its a "base" property...
|
||||
if (prop.isVersion()) {
|
||||
if (versionProperty == null) {
|
||||
versionProperty = prop;
|
||||
} else {
|
||||
logger.warn("Multiple @Version properties - property " + prop.getFullBeanName()
|
||||
+ " not treated as a version property");
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<BeanProperty> it = propertyMap.values().iterator();
|
||||
|
||||
int order = 0;
|
||||
while (it.hasNext()) {
|
||||
BeanProperty prop = it.next();
|
||||
prop.setDeployOrder(order++);
|
||||
allocateToList(prop);
|
||||
}
|
||||
|
||||
List<DeployTableJoin> deployTableJoins = deploy.getTableJoins();
|
||||
tableJoins = new TableJoin[deployTableJoins.size()];
|
||||
for (int i = 0; i < deployTableJoins.size(); i++) {
|
||||
tableJoins[i] = new TableJoin(deployTableJoins.get(i), propertyMap);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unidirectional.
|
||||
*/
|
||||
public BeanPropertyAssocOne<?> getUnidirectional() {
|
||||
return unidirectional;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the property to a list.
|
||||
*/
|
||||
private void allocateToList(BeanProperty prop) {
|
||||
if (prop.isTransient()) {
|
||||
transients.add(prop);
|
||||
return;
|
||||
}
|
||||
if (prop.isId()) {
|
||||
ids.add(prop);
|
||||
return;
|
||||
if (prop instanceof BeanPropertyCompound) {
|
||||
baseCompound.add((BeanPropertyCompound) prop);
|
||||
} else {
|
||||
nonTransients.add(prop);
|
||||
baseScalar.add(prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (desc.getInheritInfo() != null && prop.isLocal()) {
|
||||
local.add(prop);
|
||||
public LinkedHashMap<String, BeanProperty> getPropertyMap() {
|
||||
return propertyMap;
|
||||
}
|
||||
|
||||
public TableJoin[] getTableJoin() {
|
||||
return tableJoins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base scalar properties (excludes Id and secondary table
|
||||
* properties).
|
||||
*/
|
||||
public BeanProperty[] getBaseScalar() {
|
||||
return (BeanProperty[]) baseScalar.toArray(new BeanProperty[baseScalar.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyCompound[] getBaseCompound() {
|
||||
return (BeanPropertyCompound[]) baseCompound.toArray(new BeanPropertyCompound[baseCompound.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() {
|
||||
return (BeanProperty[]) nonTransients.toArray(new BeanProperty[nonTransients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getTransients() {
|
||||
return (BeanProperty[]) transients.toArray(new BeanProperty[transients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty getVersionProperty() {
|
||||
return versionProperty;
|
||||
}
|
||||
|
||||
public BeanProperty[] getLocal() {
|
||||
return (BeanProperty[]) local.toArray(new BeanProperty[local.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getEmbedded() {
|
||||
return (BeanPropertyAssocOne[]) embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExported() {
|
||||
return (BeanPropertyAssocOne[]) onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImported() {
|
||||
return (BeanPropertyAssocOne[]) onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOnes() {
|
||||
return (BeanPropertyAssocOne[]) ones.toArray(new BeanPropertyAssocOne[ones.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
|
||||
return getOne(false, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedDelete() {
|
||||
return getOne(false, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedSave() {
|
||||
return getOne(true, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedDelete() {
|
||||
return getOne(true, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonMany() {
|
||||
return (BeanProperty[]) nonManys.toArray(new BeanProperty[nonManys.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getMany() {
|
||||
return (BeanPropertyAssocMany[]) manys.toArray(new BeanPropertyAssocMany[manys.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManySave() {
|
||||
return getMany(Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyDelete() {
|
||||
return getMany(Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyToMany() {
|
||||
return getMany2Many();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode used to determine which BeanPropertyAssoc to include.
|
||||
*/
|
||||
private enum Mode {
|
||||
Save, Delete, Validate;
|
||||
}
|
||||
|
||||
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
|
||||
ArrayList<BeanPropertyAssocOne<?>> list = new ArrayList<BeanPropertyAssocOne<?>>();
|
||||
for (int i = 0; i < ones.size(); i++) {
|
||||
BeanPropertyAssocOne<?> prop = (BeanPropertyAssocOne<?>) ones.get(i);
|
||||
if (imported != prop.isOneToOneExported()) {
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Validate:
|
||||
if (prop.getCascadeInfo().isValidate()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prop instanceof BeanPropertyAssocMany<?>) {
|
||||
manys.add(prop);
|
||||
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
|
||||
}
|
||||
|
||||
} else {
|
||||
nonManys.add(prop);
|
||||
if (prop instanceof BeanPropertyAssocOne<?>) {
|
||||
if (prop.isEmbedded()) {
|
||||
embedded.add(prop);
|
||||
} else {
|
||||
ones.add(prop);
|
||||
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>) prop;
|
||||
if (assocOne.isOneToOneExported()) {
|
||||
onesExported.add(prop);
|
||||
} else {
|
||||
onesImported.add(prop);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// its a "base" property...
|
||||
if (prop.isVersion()) {
|
||||
version.add(prop);
|
||||
if (derivedFirstVersionProp == null) {
|
||||
derivedFirstVersionProp = prop;
|
||||
}
|
||||
}
|
||||
if (prop instanceof BeanPropertyCompound) {
|
||||
baseCompound.add((BeanPropertyCompound) prop);
|
||||
} else {
|
||||
baseScalar.add(prop);
|
||||
}
|
||||
}
|
||||
private BeanPropertyAssocMany<?>[] getMany2Many() {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
|
||||
if (prop.isManyToMany()) {
|
||||
list.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
|
||||
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave() || prop.isManyToMany()
|
||||
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// Note ManyToMany always included as we always 'save'
|
||||
// the relationship via insert/delete of intersection table
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete() || ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Validate:
|
||||
if (prop.getCascadeInfo().isValidate()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public BeanProperty getFirstVersion() {
|
||||
return derivedFirstVersionProp;
|
||||
}
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, BeanProperty> getPropertyMap() {
|
||||
return propertyMap;
|
||||
}
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private BeanProperty createBeanProperty(BeanDescriptorMap owner, DeployBeanProperty deployProp) {
|
||||
|
||||
public TableJoin[] getTableJoin() {
|
||||
return tableJoins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base scalar properties (excludes Id and secondary table
|
||||
* properties).
|
||||
*/
|
||||
public BeanProperty[] getBaseScalar() {
|
||||
return (BeanProperty[]) baseScalar.toArray(new BeanProperty[baseScalar.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyCompound[] getBaseCompound() {
|
||||
return (BeanPropertyCompound[]) baseCompound.toArray(new BeanPropertyCompound[baseCompound.size()]);
|
||||
if (deployProp instanceof DeployBeanPropertyAssocOne) {
|
||||
return new BeanPropertyAssocOne(owner, desc, (DeployBeanPropertyAssocOne) deployProp);
|
||||
}
|
||||
|
||||
public BeanProperty getNaturalKey() {
|
||||
String naturalKey = desc.getCacheOptions().getNaturalKey();
|
||||
if (naturalKey != null){
|
||||
return propertyMap.get(naturalKey);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public BeanProperty[] getId() {
|
||||
return (BeanProperty[]) ids.toArray(new BeanProperty[ids.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonTransients() {
|
||||
return (BeanProperty[]) nonTransients.toArray(new BeanProperty[nonTransients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getTransients() {
|
||||
return (BeanProperty[]) transients.toArray(new BeanProperty[transients.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getVersion() {
|
||||
return (BeanProperty[]) version.toArray(new BeanProperty[version.size()]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getLocal() {
|
||||
return (BeanProperty[]) local.toArray(new BeanProperty[local.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getEmbedded() {
|
||||
return (BeanPropertyAssocOne[]) embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExported() {
|
||||
return (BeanPropertyAssocOne[]) onesExported.toArray(new BeanPropertyAssocOne[onesExported.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImported() {
|
||||
return (BeanPropertyAssocOne[]) onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOnes() {
|
||||
return (BeanPropertyAssocOne[]) ones.toArray(new BeanPropertyAssocOne[ones.size()]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
|
||||
return getOne(false, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedDelete() {
|
||||
return getOne(false, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedSave() {
|
||||
return getOne(true, Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImportedDelete() {
|
||||
return getOne(true, Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonMany() {
|
||||
return (BeanProperty[]) nonManys.toArray(new BeanProperty[nonManys.size()]);
|
||||
if (deployProp instanceof DeployBeanPropertySimpleCollection<?>) {
|
||||
return new BeanPropertySimpleCollection(owner, desc, (DeployBeanPropertySimpleCollection) deployProp);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getMany() {
|
||||
return (BeanPropertyAssocMany[]) manys.toArray(new BeanPropertyAssocMany[manys.size()]);
|
||||
if (deployProp instanceof DeployBeanPropertyAssocMany) {
|
||||
return new BeanPropertyAssocMany(owner, desc, (DeployBeanPropertyAssocMany) deployProp);
|
||||
}
|
||||
|
||||
if (deployProp instanceof DeployBeanPropertyCompound) {
|
||||
return new BeanPropertyCompound(owner, desc, (DeployBeanPropertyCompound) deployProp);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManySave() {
|
||||
return getMany(Mode.Save);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyDelete() {
|
||||
return getMany(Mode.Delete);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManyToMany() {
|
||||
return getMany2Many();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode used to determine which BeanPropertyAssoc to include.
|
||||
*/
|
||||
private enum Mode {
|
||||
Save, Delete, Validate;
|
||||
}
|
||||
|
||||
private BeanPropertyAssocOne<?>[] getOne(boolean imported, Mode mode) {
|
||||
ArrayList<BeanPropertyAssocOne<?>> list = new ArrayList<BeanPropertyAssocOne<?>>();
|
||||
for (int i = 0; i < ones.size(); i++) {
|
||||
BeanPropertyAssocOne<?> prop = (BeanPropertyAssocOne<?>) ones.get(i);
|
||||
if (imported != prop.isOneToOneExported()) {
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Validate:
|
||||
if (prop.getCascadeInfo().isValidate()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany2Many() {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
|
||||
if (prop.isManyToMany()) {
|
||||
list.add(prop);
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
|
||||
ArrayList<BeanPropertyAssocMany<?>> list = new ArrayList<BeanPropertyAssocMany<?>>();
|
||||
for (int i = 0; i < manys.size(); i++) {
|
||||
BeanPropertyAssocMany<?> prop = (BeanPropertyAssocMany<?>) manys.get(i);
|
||||
|
||||
switch (mode) {
|
||||
case Save:
|
||||
if (prop.getCascadeInfo().isSave() || prop.isManyToMany()
|
||||
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// Note ManyToMany always included as we always 'save'
|
||||
// the relationship via insert/delete of intersection table
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Delete:
|
||||
if (prop.getCascadeInfo().isDelete()
|
||||
|| ModifyListenMode.REMOVALS.equals(prop.getModifyListenMode())) {
|
||||
// REMOVALS means including PrivateOwned relationships
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
case Validate:
|
||||
if (prop.getCascadeInfo().isValidate()) {
|
||||
list.add(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private BeanProperty createBeanProperty(BeanDescriptorMap owner, DeployBeanProperty deployProp) {
|
||||
|
||||
if (deployProp instanceof DeployBeanPropertyAssocOne) {
|
||||
|
||||
return new BeanPropertyAssocOne(owner, desc, (DeployBeanPropertyAssocOne) deployProp);
|
||||
}
|
||||
if (deployProp instanceof DeployBeanPropertySimpleCollection<?>) {
|
||||
|
||||
return new BeanPropertySimpleCollection(owner, desc, (DeployBeanPropertySimpleCollection)deployProp);
|
||||
}
|
||||
if (deployProp instanceof DeployBeanPropertyAssocMany) {
|
||||
|
||||
return new BeanPropertyAssocMany(owner, desc, (DeployBeanPropertyAssocMany) deployProp);
|
||||
}
|
||||
if (deployProp instanceof DeployBeanPropertyCompound) {
|
||||
|
||||
return new BeanPropertyCompound(owner, desc, (DeployBeanPropertyCompound) deployProp);
|
||||
}
|
||||
|
||||
return new BeanProperty(owner, desc, deployProp);
|
||||
}
|
||||
return new BeanProperty(owner, desc, deployProp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import javax.persistence.Table;
|
||||
import javax.persistence.UniqueConstraint;
|
||||
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.annotation.CacheTuning;
|
||||
import com.avaje.ebean.annotation.EntityConcurrencyMode;
|
||||
import com.avaje.ebean.annotation.NamedUpdate;
|
||||
import com.avaje.ebean.annotation.NamedUpdates;
|
||||
@@ -55,10 +56,8 @@ public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
Entity entity = cls.getAnnotation(Entity.class);
|
||||
if (entity != null) {
|
||||
// checkDefaultConstructor();
|
||||
if (entity.name().equals("")) {
|
||||
descriptor.setName(cls.getSimpleName());
|
||||
|
||||
} else {
|
||||
descriptor.setName(entity.name());
|
||||
}
|
||||
@@ -110,8 +109,9 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
|
||||
CacheStrategy cacheStrategy = cls.getAnnotation(CacheStrategy.class);
|
||||
if (cacheStrategy != null) {
|
||||
readCacheStrategy(cacheStrategy);
|
||||
CacheTuning cacheTuning = cls.getAnnotation(CacheTuning.class);
|
||||
if (cacheStrategy != null || cacheTuning != null) {
|
||||
readCacheStrategy(cacheStrategy, cacheTuning);
|
||||
}
|
||||
|
||||
EntityConcurrencyMode entityConcurrencyMode = cls.getAnnotation(EntityConcurrencyMode.class);
|
||||
@@ -120,18 +120,24 @@ public class AnnotationClass extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void readCacheStrategy(CacheStrategy cacheStrategy) {
|
||||
private void readCacheStrategy(CacheStrategy cacheStrategy, CacheTuning cacheTuning) {
|
||||
|
||||
CacheOptions cacheOptions = descriptor.getCacheOptions();
|
||||
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
|
||||
cacheOptions.setReadOnly(cacheStrategy.readOnly());
|
||||
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
|
||||
if (cacheStrategy.naturalKey().length() > 0) {
|
||||
String propName = cacheStrategy.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
|
||||
if (beanProperty != null) {
|
||||
beanProperty.setNaturalKey(true);
|
||||
cacheOptions.setNaturalKey(propName);
|
||||
if (cacheTuning != null) {
|
||||
cacheOptions.setMaxSecsToLive(cacheTuning.maxSecsToLive());
|
||||
cacheOptions.setMaxIdleSecs(cacheTuning.maxIdleSecs());
|
||||
}
|
||||
if (cacheStrategy != null) {
|
||||
cacheOptions.setUseCache(cacheStrategy.useBeanCache());
|
||||
cacheOptions.setReadOnly(cacheStrategy.readOnly());
|
||||
cacheOptions.setWarmingQuery(cacheStrategy.warmingQuery());
|
||||
if (cacheStrategy.naturalKey().length() > 0) {
|
||||
String propName = cacheStrategy.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = descriptor.getBeanProperty(propName);
|
||||
if (beanProperty != null) {
|
||||
beanProperty.setNaturalKey(true);
|
||||
cacheOptions.setNaturalKey(propName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.avaje.ebeaninternal.server.el;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Comparator based on a ElGetValue.
|
||||
*/
|
||||
@@ -21,15 +23,15 @@ public final class ElComparatorProperty<T> implements Comparator<T>, ElComparato
|
||||
|
||||
public int compare(T o1, T o2) {
|
||||
|
||||
Object val1 = elGetValue.elGetValue(o1);
|
||||
Object val2 = elGetValue.elGetValue(o2);
|
||||
Object val1 = elGetValue.elGetValue((EntityBean)o1);
|
||||
Object val2 = elGetValue.elGetValue((EntityBean)o2);
|
||||
|
||||
return compareValues(val1, val2);
|
||||
}
|
||||
|
||||
public int compareValue(Object value, T o2) {
|
||||
|
||||
Object val2 = elGetValue.elGetValue(o2);
|
||||
Object val2 = elGetValue.elGetValue((EntityBean)o2);
|
||||
|
||||
return compareValues(value, val2);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
|
||||
/**
|
||||
* Contains the various ElMatcher implementations.
|
||||
@@ -26,7 +28,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return pattern.matcher(v).matches();
|
||||
}
|
||||
}
|
||||
@@ -53,7 +55,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return value.equalsIgnoreCase(v);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +75,7 @@ class ElMatchBuilder {
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return charMatch.startsWith(v);
|
||||
}
|
||||
}
|
||||
@@ -93,7 +95,7 @@ class ElMatchBuilder {
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return charMatch.endsWith(v);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +106,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return value.startsWith(v);
|
||||
}
|
||||
}
|
||||
@@ -115,7 +117,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
String v = (String)elGetValue.elGetValue(bean);
|
||||
String v = (String)elGetValue.elGetValue((EntityBean)bean);
|
||||
return value.endsWith(v);
|
||||
}
|
||||
}
|
||||
@@ -129,7 +131,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
return (null == elGetValue.elGetValue(bean));
|
||||
return (null == elGetValue.elGetValue((EntityBean)bean));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +144,7 @@ class ElMatchBuilder {
|
||||
}
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
return (null != elGetValue.elGetValue(bean));
|
||||
return (null != elGetValue.elGetValue((EntityBean)bean));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +175,7 @@ class ElMatchBuilder {
|
||||
|
||||
public boolean isMatch(T bean) {
|
||||
|
||||
Object value = elGetValue.elGetValue(bean);
|
||||
Object value = elGetValue.elGetValue((EntityBean)bean);
|
||||
if (value == null){
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
return lastElPropertyValue.isLocalEncrypted();
|
||||
}
|
||||
|
||||
public Object[] getAssocOneIdValues(Object bean) {
|
||||
public Object[] getAssocOneIdValues(EntityBean bean) {
|
||||
// Don't navigate the object graph as bean
|
||||
// is assumed to be the appropriate type
|
||||
return lastElPropertyValue.getAssocOneIdValues(bean);
|
||||
@@ -231,10 +231,10 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
return lastElPropertyValue.elConvertType(value);
|
||||
}
|
||||
|
||||
public Object elGetValue(Object bean) {
|
||||
public Object elGetValue(EntityBean bean) {
|
||||
|
||||
for (int i = 0; i < chain.length; i++) {
|
||||
bean = chain[i].elGetValue(bean);
|
||||
bean = (EntityBean)chain[i].elGetValue(bean);
|
||||
if (bean == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -243,24 +243,22 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public Object elGetReference(Object bean) {
|
||||
public Object elGetReference(EntityBean bean) {
|
||||
|
||||
Object prevBean = bean;
|
||||
EntityBean prevBean = bean;
|
||||
for (int i = 0; i < last; i++) {
|
||||
// always return non null prevBean
|
||||
prevBean = chain[i].elGetReference(prevBean);
|
||||
prevBean = (EntityBean)chain[i].elGetReference(prevBean);
|
||||
}
|
||||
// try the last step in the chain
|
||||
bean = chain[last].elGetValue(prevBean);
|
||||
|
||||
return bean;
|
||||
return chain[last].elGetValue(prevBean);
|
||||
}
|
||||
|
||||
|
||||
public void elSetLoaded(Object bean) {
|
||||
public void elSetLoaded(EntityBean bean) {
|
||||
|
||||
for (int i = 0; i < last; i++) {
|
||||
bean = chain[i].elGetValue(bean);
|
||||
bean = (EntityBean)chain[i].elGetValue(bean);
|
||||
if (bean == null){
|
||||
break;
|
||||
}
|
||||
@@ -270,31 +268,18 @@ public class ElPropertyChain implements ElPropertyValue {
|
||||
}
|
||||
}
|
||||
|
||||
public void elSetReference(Object bean) {
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate) {
|
||||
|
||||
for (int i = 0; i < last; i++) {
|
||||
bean = chain[i].elGetValue(bean);
|
||||
if (bean == null){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bean != null){
|
||||
((EntityBean)bean)._ebean_getIntercept().setReference();
|
||||
}
|
||||
}
|
||||
|
||||
public void elSetValue(Object bean, Object value, boolean populate, boolean reference){
|
||||
|
||||
Object prevBean = bean;
|
||||
EntityBean prevBean = bean;
|
||||
if (populate){
|
||||
for (int i = 0; i < last; i++) {
|
||||
// always return non null prevBean
|
||||
prevBean = chain[i].elGetReference(prevBean);
|
||||
prevBean = (EntityBean)chain[i].elGetReference(prevBean);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < last; i++) {
|
||||
// always return non null prevBean
|
||||
prevBean = chain[i].elGetValue(prevBean);
|
||||
prevBean = (EntityBean)chain[i].elGetValue(prevBean);
|
||||
if (prevBean == null){
|
||||
break;
|
||||
}
|
||||
@@ -304,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.el;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.StringFormatter;
|
||||
import com.avaje.ebean.text.StringParser;
|
||||
|
||||
@@ -14,7 +15,7 @@ public interface ElPropertyValue extends ElPropertyDeploy {
|
||||
/**
|
||||
* Return the Id values for the given bean value.
|
||||
*/
|
||||
public Object[] getAssocOneIdValues(Object bean);
|
||||
public Object[] getAssocOneIdValues(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Return the Id expression string.
|
||||
@@ -89,13 +90,13 @@ public interface ElPropertyValue extends ElPropertyDeploy {
|
||||
/**
|
||||
* Return the value from a given entity bean.
|
||||
*/
|
||||
public Object elGetValue(Object bean);
|
||||
public Object elGetValue(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Return the value ensuring objects prior to the top scalar property are
|
||||
* automatically populated.
|
||||
*/
|
||||
public Object elGetReference(Object bean);
|
||||
public Object elGetReference(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Set a value given a root level bean.
|
||||
@@ -103,12 +104,7 @@ public interface ElPropertyValue extends ElPropertyDeploy {
|
||||
* If populate then
|
||||
* </p>
|
||||
*/
|
||||
public void elSetValue(Object bean, Object value, boolean populate, boolean reference);
|
||||
|
||||
/**
|
||||
* Make the owning bean of this property a reference (as in not new/dirty).
|
||||
*/
|
||||
public void elSetReference(Object bean);
|
||||
public void elSetValue(EntityBean bean, Object value, boolean populate);
|
||||
|
||||
/**
|
||||
* Convert the value to the expected type.
|
||||
|
||||
+4
-2
@@ -5,6 +5,7 @@ import java.util.Iterator;
|
||||
|
||||
import com.avaje.ebean.ExampleExpression;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
@@ -43,7 +44,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
/**
|
||||
* The example bean containing the properties.
|
||||
*/
|
||||
private final Object entity;
|
||||
private final EntityBean entity;
|
||||
|
||||
/**
|
||||
* Set to true to use case insensitive expressions.
|
||||
@@ -66,6 +67,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
*/
|
||||
private ArrayList<SpiExpression> list;
|
||||
|
||||
|
||||
/**
|
||||
* Construct the query by example expression.
|
||||
*
|
||||
@@ -76,7 +78,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
* @param likeType
|
||||
* the type of Like wild card used
|
||||
*/
|
||||
public DefaultExampleExpression(Object entity, boolean caseInsensitive, LikeType likeType) {
|
||||
public DefaultExampleExpression(EntityBean entity, boolean caseInsensitive, LikeType likeType) {
|
||||
this.entity = entity;
|
||||
this.caseInsensitive = caseInsensitive;
|
||||
this.likeType = likeType;
|
||||
|
||||
+12
-3
@@ -11,6 +11,7 @@ import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionFactory;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
|
||||
@@ -21,6 +22,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
private static final Object[] EMPTY_ARRAY = new Object[] {};
|
||||
|
||||
|
||||
public DefaultExpressionFactory() {
|
||||
}
|
||||
|
||||
@@ -128,11 +130,18 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new NullExpression(propertyName, true);
|
||||
}
|
||||
|
||||
private EntityBean checkEntityBean(Object bean) {
|
||||
if (bean == null || (bean instanceof EntityBean == false)) {
|
||||
throw new IllegalStateException("Expecting an EntityBean");
|
||||
}
|
||||
return (EntityBean)bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive {@link #exampleLike(Object)}
|
||||
*/
|
||||
public ExampleExpression iexampleLike(Object example) {
|
||||
return new DefaultExampleExpression(example, true, LikeType.RAW);
|
||||
return new DefaultExampleExpression(checkEntityBean(example), true, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,14 +149,14 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
* LikeType.RAW (you need to add you own wildcards % and _).
|
||||
*/
|
||||
public ExampleExpression exampleLike(Object example) {
|
||||
return new DefaultExampleExpression(example, false, LikeType.RAW);
|
||||
return new DefaultExampleExpression(checkEntityBean(example), false, LikeType.RAW);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
public ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
|
||||
return new DefaultExampleExpression(example, caseInsensitive, likeType);
|
||||
return new DefaultExampleExpression(checkEntityBean(example), caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
@@ -36,7 +37,7 @@ class InExpression extends AbstractExpression {
|
||||
|
||||
} else {
|
||||
// extract the id values from the bean
|
||||
Object[] ids = prop.getAssocOneIdValues(values[i]);
|
||||
Object[] ids = prop.getAssocOneIdValues((EntityBean)values[i]);
|
||||
if (ids != null) {
|
||||
for (int j = 0; j < ids.length; j++) {
|
||||
request.addBindValue(ids[j]);
|
||||
|
||||
@@ -14,7 +14,6 @@ import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PagingList;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryListener;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
@@ -375,19 +374,10 @@ abstract class JunctionExpression<T> implements Junction<T>, SpiExpression, Expr
|
||||
return exprList.select(properties);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setBackgroundFetchAfter(int backgroundFetchAfter) {
|
||||
return exprList.setBackgroundFetchAfter(backgroundFetchAfter);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setFirstRow(int firstRow) {
|
||||
return exprList.setFirstRow(firstRow);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public com.avaje.ebean.Query<T> setListener(QueryListener<T> queryListener) {
|
||||
return exprList.setListener(queryListener);
|
||||
}
|
||||
|
||||
public com.avaje.ebean.Query<T> setMapKey(String mapKey) {
|
||||
return exprList.setMapKey(mapKey);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user