mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#461 - ENH: Add @Draftable support - @DraftDirty
This commit is contained in:
@@ -61,6 +61,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
private final boolean dirty;
|
||||
|
||||
private final boolean publish;
|
||||
|
||||
private ConcurrencyMode concurrencyMode;
|
||||
|
||||
/**
|
||||
@@ -119,10 +121,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
private boolean requestUpdateAllLoadedProps;
|
||||
|
||||
private boolean publish;
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type, boolean saveRecurse) {
|
||||
PersistExecute persistExecute, PersistRequest.Type type, boolean saveRecurse, boolean publish) {
|
||||
|
||||
super(server, t, persistExecute);
|
||||
this.entityBean = (EntityBean) bean;
|
||||
@@ -134,7 +134,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
this.parentBean = parentBean;
|
||||
this.controller = beanDescriptor.getPersistController();
|
||||
this.type = type;
|
||||
|
||||
|
||||
if (saveRecurse) {
|
||||
this.persistCascade = t.isPersistCascade();
|
||||
}
|
||||
@@ -149,6 +149,10 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
beanDescriptor.checkMutableProperties(intercept);
|
||||
}
|
||||
this.concurrencyMode = beanDescriptor.getConcurrencyMode(intercept);
|
||||
this.publish = publish;
|
||||
if (!publish && beanDescriptor.isDraftable()) {
|
||||
beanDescriptor.setDraftDirty(entityBean, true);
|
||||
}
|
||||
this.dirty = intercept.isDirty();
|
||||
}
|
||||
|
||||
@@ -245,17 +249,17 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
public void notifyCache() {
|
||||
if (notifyCache) {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
beanDescriptor.cacheHandleInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
beanDescriptor.cacheHandleUpdate(idValue, this);
|
||||
break;
|
||||
case DELETE:
|
||||
// Bean deleted from cache early via postDelete()
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid type " + type);
|
||||
case INSERT:
|
||||
beanDescriptor.cacheHandleInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
beanDescriptor.cacheHandleUpdate(idValue, this);
|
||||
break;
|
||||
case DELETE:
|
||||
// Bean deleted from cache early via postDelete()
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid type " + type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,24 +453,24 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
@Override
|
||||
public int executeNow() {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
persistExecute.executeInsertBean(this);
|
||||
return -1;
|
||||
case INSERT:
|
||||
persistExecute.executeInsertBean(this);
|
||||
return -1;
|
||||
|
||||
case UPDATE:
|
||||
if (beanPersistListener != null) {
|
||||
// store the updated properties for sending later
|
||||
updatedProperties = getUpdatedProperties();
|
||||
}
|
||||
persistExecute.executeUpdateBean(this);
|
||||
return -1;
|
||||
case UPDATE:
|
||||
if (beanPersistListener != null) {
|
||||
// store the updated properties for sending later
|
||||
updatedProperties = getUpdatedProperties();
|
||||
}
|
||||
persistExecute.executeUpdateBean(this);
|
||||
return -1;
|
||||
|
||||
case DELETE:
|
||||
persistExecute.executeDeleteBean(this);
|
||||
return -1;
|
||||
case DELETE:
|
||||
persistExecute.executeDeleteBean(this);
|
||||
return -1;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Invalid type " + type);
|
||||
default:
|
||||
throw new RuntimeException("Invalid type " + type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,8 +519,12 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
throw new OptimisticLockException(m, null, bean);
|
||||
}
|
||||
switch (type) {
|
||||
case DELETE: postDelete(); break;
|
||||
case UPDATE: postUpdate(); break;
|
||||
case DELETE:
|
||||
postDelete();
|
||||
break;
|
||||
case UPDATE:
|
||||
postUpdate();
|
||||
break;
|
||||
default: // do nothing
|
||||
}
|
||||
}
|
||||
@@ -573,35 +581,36 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
private void controllerPost() {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void logSummary() {
|
||||
|
||||
String draft = (beanDescriptor.isDraftable() && !publish) ? " draft[true]" : "";
|
||||
String name = beanDescriptor.getName();
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
transaction.logSummary("Inserted [" + name + "] [" + idValue + "]");
|
||||
break;
|
||||
case UPDATE:
|
||||
transaction.logSummary("Updated [" + name + "] [" + idValue + "]");
|
||||
break;
|
||||
case DELETE:
|
||||
transaction.logSummary("Deleted [" + name + "] [" + idValue + "]");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case INSERT:
|
||||
transaction.logSummary("Inserted [" + name + "] [" + idValue + "]" + draft);
|
||||
break;
|
||||
case UPDATE:
|
||||
transaction.logSummary("Updated [" + name + "] [" + idValue + "]" + draft);
|
||||
break;
|
||||
case DELETE:
|
||||
transaction.logSummary("Deleted [" + name + "] [" + idValue + "]");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,7 +731,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
/**
|
||||
* Determine if all loaded properties should be used for an update.
|
||||
* <p>
|
||||
* Takes into account transaction setting and JDBC batch.
|
||||
* Takes into account transaction setting and JDBC batch.
|
||||
* </p>
|
||||
*/
|
||||
public boolean determineUpdateAllLoadedProperties() {
|
||||
@@ -739,13 +748,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
return requestUpdateAllLoadedProps;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a persist request for a 'publish' action.
|
||||
*/
|
||||
public void setPublish() {
|
||||
publish = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this request is a 'publish' action.
|
||||
*/
|
||||
|
||||
@@ -158,6 +158,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
|
||||
private final boolean draftableElement;
|
||||
|
||||
private final BeanProperty draftDirty;
|
||||
|
||||
/**
|
||||
* Map of BeanProperty Linked so as to preserve order.
|
||||
*/
|
||||
@@ -393,6 +395,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
|
||||
this.idProperty = listHelper.getId();
|
||||
this.versionProperty = listHelper.getVersionProperty();
|
||||
this.draftDirty = listHelper.getDraftDirty();
|
||||
this.propMap = listHelper.getPropertyMap();
|
||||
this.propertiesTransient = listHelper.getTransients();
|
||||
this.propertiesNonTransient = listHelper.getNonTransients();
|
||||
@@ -833,6 +836,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
return draftHelp.publish(draftBean, liveBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the draft dirty boolean property or null if there is not one assigned to this bean type.
|
||||
*/
|
||||
public BeanProperty getDraftDirty() {
|
||||
return draftDirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean caching on or off.
|
||||
*/
|
||||
@@ -1918,6 +1928,19 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
return draftableElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there is a @DraftDirty property set it's value on the bean.
|
||||
*/
|
||||
public void setDraftDirty(EntityBean entityBean, boolean value) {
|
||||
if (draftDirty != null) {
|
||||
// check to see if the dirty property has already
|
||||
// been set and if so do not set the value
|
||||
if (!entityBean._ebean_getIntercept().isChangedProperty(draftDirty.getPropertyIndex())) {
|
||||
draftDirty.setValueIntercept(entityBean, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this entity bean has history support.
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,8 @@ public class DeployBeanPropertyLists {
|
||||
|
||||
private BeanProperty versionProperty;
|
||||
|
||||
private BeanProperty draftDirty;
|
||||
|
||||
private final BeanDescriptor<?> desc;
|
||||
|
||||
private final LinkedHashMap<String, BeanProperty> propertyMap;
|
||||
@@ -175,6 +177,8 @@ public class DeployBeanPropertyLists {
|
||||
logger.warn("Multiple @Version properties - property " + prop.getFullBeanName()
|
||||
+ " not treated as a version property");
|
||||
}
|
||||
} else if (prop.isDraftDirty()) {
|
||||
draftDirty = prop;
|
||||
}
|
||||
if (prop instanceof BeanPropertyCompound) {
|
||||
baseCompound.add((BeanPropertyCompound) prop);
|
||||
@@ -285,6 +289,10 @@ public class DeployBeanPropertyLists {
|
||||
return getMany2Many();
|
||||
}
|
||||
|
||||
public BeanProperty getDraftDirty() {
|
||||
return draftDirty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mode used to determine which BeanPropertyAssoc to include.
|
||||
*/
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -132,14 +133,14 @@ public final class DefaultPersister implements Persister {
|
||||
query.asDraft();
|
||||
|
||||
Class<T> beanType = query.getBeanType();
|
||||
List<T> draftBeans = server.findList(query, transaction);
|
||||
BeanDescriptor<T> desc = server.getBeanDescriptor(beanType);
|
||||
|
||||
if (draftBeans.isEmpty()) {
|
||||
throw new IllegalArgumentException("No draft beans found to publish");
|
||||
}
|
||||
List<T> draftBeans = server.findList(query, transaction);
|
||||
PUB.debug("publish [{}] count[{}]", desc.getName(), draftBeans.size());
|
||||
|
||||
PUB.debug("publish [{}] count:{}", desc.getName(), draftBeans.size());
|
||||
if (draftBeans.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// get the list of Id's
|
||||
List<Object> idList = new ArrayList<Object>();
|
||||
@@ -156,6 +157,11 @@ public final class DefaultPersister implements Persister {
|
||||
|
||||
BeanManager<T> mgr = beanDescriptorManager.getBeanManager(beanType);
|
||||
|
||||
// collect a list of draft beans that have had their
|
||||
// dirty status set back to false by the publish
|
||||
List<T> draftUpdates = new ArrayList<T>();
|
||||
BeanProperty draftDirty = desc.getDraftDirty();
|
||||
|
||||
for (T draftBean: draftBeans) {
|
||||
Object draftID = desc.getBeanId(draftBean);
|
||||
T existingLiveBean = liveBeans.get(draftID);
|
||||
@@ -164,23 +170,45 @@ public final class DefaultPersister implements Persister {
|
||||
livePublish.add(liveBean);
|
||||
|
||||
Type persistType = (existingLiveBean == null) ? Type.INSERT : Type.UPDATE;
|
||||
PersistRequestBean<T> request = createRequest(liveBean, transaction, null, mgr, persistType, true);
|
||||
request.setPublish();
|
||||
|
||||
PUB.trace("publish [{}] id[{}]", desc.getName(), draftID);
|
||||
PUB.trace("publish bean [{}] id[{}] type[{}]", desc.getName(), draftID, persistType);
|
||||
|
||||
PersistRequestBean<T> request = createRequest(liveBean, transaction, null, mgr, persistType, true, true);
|
||||
if (persistType == Type.INSERT) {
|
||||
insert(request);
|
||||
} else {
|
||||
update(request);
|
||||
}
|
||||
|
||||
PUB.debug("publish complete for type:{}", desc.getName());
|
||||
unsetDraftDirtyProperty(draftUpdates, draftDirty, draftBean);
|
||||
}
|
||||
|
||||
if (!draftUpdates.isEmpty()) {
|
||||
// update the dirty status on the drafts that have been published
|
||||
PUB.debug("publish - update dirty status on [{}] drafts", draftUpdates.size());
|
||||
for (T draftUpdate : draftUpdates) {
|
||||
update(createRequest(draftUpdate, transaction, null, mgr, Type.UPDATE, false, false));
|
||||
}
|
||||
}
|
||||
|
||||
PUB.debug("publish - complete for [{}]", desc.getName());
|
||||
|
||||
return livePublish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the draft dirty state to false and add to the draftUpdates list.
|
||||
*/
|
||||
private <T> void unsetDraftDirtyProperty(List<T> draftUpdates, BeanProperty draftDirty, T draftBean) {
|
||||
|
||||
if (draftDirty != null) {
|
||||
EntityBean draftEntityBean = (EntityBean)draftBean;
|
||||
draftDirty.setValueIntercept(draftEntityBean, false);
|
||||
if (draftEntityBean._ebean_getIntercept().isDirty()) {
|
||||
draftUpdates.add(draftBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively delete the bean. This calls back to the EbeanServer.
|
||||
*/
|
||||
@@ -258,9 +286,6 @@ public final class DefaultPersister implements Persister {
|
||||
|
||||
// determine insert or update taking into account stateless updates
|
||||
PersistRequestBean<?> request = createRequestRecurse(bean, t, parentBean, insertMode, publish);
|
||||
if (publish) {
|
||||
request.setPublish();
|
||||
}
|
||||
|
||||
if (request.isReference()) {
|
||||
// its a reference...
|
||||
@@ -1261,7 +1286,7 @@ public final class DefaultPersister implements Persister {
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(bean.getClass()));
|
||||
}
|
||||
return createRequest(bean, t, null, mgr, type, false);
|
||||
return createRequest(bean, t, null, mgr, type, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1284,7 +1309,7 @@ public final class DefaultPersister implements Persister {
|
||||
// determine Insert or Update based on bean state and insert flag
|
||||
type = desc.isInsertMode(entityBean._ebean_getIntercept(), insertMode) ? Type.INSERT : Type.UPDATE;
|
||||
}
|
||||
return createRequest(bean, t, parentBean, mgr, type, true);
|
||||
return createRequest(bean, t, parentBean, mgr, type, true, publish);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1292,9 +1317,10 @@ public final class DefaultPersister implements Persister {
|
||||
* perform an insert, update or delete.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private <T> PersistRequestBean<T> createRequest(T bean, Transaction t, Object parentBean, BeanManager<?> mgr, PersistRequest.Type type, boolean saveRecurse) {
|
||||
private <T> PersistRequestBean<T> createRequest(T bean, Transaction t, Object parentBean, BeanManager<?> mgr,
|
||||
PersistRequest.Type type, boolean saveRecurse, boolean publish) {
|
||||
|
||||
return new PersistRequestBean(server, bean, parentBean, mgr, (SpiTransaction) t, persistExecute, type, saveRecurse);
|
||||
return new PersistRequestBean(server, bean, parentBean, mgr, (SpiTransaction) t, persistExecute, type, saveRecurse, publish);
|
||||
}
|
||||
|
||||
private String errNotRegistered(Class<?> beanClass) {
|
||||
|
||||
@@ -415,6 +415,9 @@ public class CQueryEngine {
|
||||
if (query.isAutoTuned()) {
|
||||
msg.append("tuned[true] ");
|
||||
}
|
||||
if (query.isAsDraft()) {
|
||||
msg.append(" draft[true] ");
|
||||
}
|
||||
if (originKey != null) {
|
||||
msg.append("origin[").append(originKey).append("] ");
|
||||
}
|
||||
@@ -458,6 +461,9 @@ public class CQueryEngine {
|
||||
if (query.isAutoTuned()) {
|
||||
msg.append("tuned[true] ");
|
||||
}
|
||||
if (query.isAsDraft()) {
|
||||
msg.append(" draft[true] ");
|
||||
}
|
||||
if (originKey != null) {
|
||||
msg.append("origin[").append(originKey).append("] ");
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ public class CQueryFetchIds {
|
||||
* Return a summary description of this query.
|
||||
*/
|
||||
public String getSummary() {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
StringBuilder sb = new StringBuilder(80);
|
||||
sb.append("FindIds exeMicros[").append(executionTimeMicros)
|
||||
.append("] rows[").append(rowCount)
|
||||
|
||||
Reference in New Issue
Block a user