#118 - ENH: Add support for for Soft Deletes (Logical Deletion) ...

This commit is contained in:
Robin Bygrave
2015-12-02 21:38:34 +13:00
parent 0ad52cf6a7
commit f39a684c8e
16 changed files with 469 additions and 118 deletions
@@ -22,6 +22,7 @@ import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.ScalarType;
import com.avaje.ebeaninternal.server.type.ScalarTypeBoolean;
import com.avaje.ebeaninternal.util.ValueUtil;
import com.fasterxml.jackson.core.JsonToken;
import org.slf4j.Logger;
@@ -231,7 +232,9 @@ public class BeanProperty implements ElPropertyValue {
final boolean softDelete;
final Object softDeleteValue;
final String softDeleteDbSet;
final String softDeleteDbPredicate;
final boolean indexed;
@@ -262,9 +265,6 @@ public class BeanProperty implements ElPropertyValue {
this.draftDirty = deploy.isDraftDirty();
this.draftOnly = deploy.isDraftOnly();
this.draftReset = deploy.isDraftReset();
this.softDelete = deploy.isSoftDelete();
this.softDeleteValue = deploy.getSoftDeleteValue();
this.secondaryTable = deploy.isSecondaryTable();
if (secondaryTable) {
this.secondaryTableJoin = new TableJoin(deploy.getSecondaryTableJoin());
@@ -308,6 +308,16 @@ public class BeanProperty implements ElPropertyValue {
this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), false, null);
this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(), dbEncrypted, dbColumn);
this.softDelete = deploy.isSoftDelete();
if (softDelete) {
ScalarTypeBoolean.BooleanBase boolType = (ScalarTypeBoolean.BooleanBase)scalarType;
this.softDeleteDbSet = dbColumn+"="+boolType.getDbTrueLiteral();
this.softDeleteDbPredicate = dbColumn+"="+boolType.getDbFalseLiteral();
} else {
this.softDeleteDbSet = null;
this.softDeleteDbPredicate = null;
}
this.jsonSerialize = deploy.isJsonSerialize();
this.jsonDeserialize = deploy.isJsonDeserialize();
}
@@ -352,7 +362,8 @@ public class BeanProperty implements ElPropertyValue {
this.draftOnly = source.draftOnly;
this.draftReset = source.draftReset;
this.softDelete = source.softDelete;
this.softDeleteValue = source.softDeleteValue;
this.softDeleteDbSet = source.softDeleteDbSet;
this.softDeleteDbPredicate = source.softDeleteDbPredicate;
this.fetchEager = source.fetchEager;
this.unidirectionalShadow = source.unidirectionalShadow;
this.discriminator = source.discriminator;
@@ -624,22 +635,26 @@ public class BeanProperty implements ElPropertyValue {
}
}
/**
* Return the DB literal expression to set the deleted state to true.
*/
public String getSoftDeleteDbSet() {
return dbColumn +"=true";
return softDeleteDbSet;
}
/**
* Return the DB literal predicate used to filter out soft deleted rows from a query.
*/
public String getSoftDeleteDbPredicate(String tableAlias) {
return tableAlias+"."+dbColumn+"=false";
return tableAlias+"."+softDeleteDbPredicate;
}
/**
* Set the soft delete property value on the bean without invoking lazy loading.
*/
public void setSoftDeleteValue(EntityBean bean) {
setValue(bean, softDeleteValue);
// assumes boolean deleted true being set which is ok limitation for now
setValue(bean, true);
bean._ebean_getIntercept().setChangedProperty(propertyIndex);
}
@@ -1,6 +1,7 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.annotation.CreatedTimestamp;
import com.avaje.ebean.annotation.SoftDelete;
import com.avaje.ebean.annotation.UpdatedTimestamp;
import com.avaje.ebean.annotation.WhenCreated;
import com.avaje.ebean.annotation.WhenModified;
@@ -190,7 +191,6 @@ public class DeployBeanProperty {
private boolean draftReset;
private boolean softDelete;
private String softDeleteValue = "";
public DeployBeanProperty(DeployBeanDescriptor<?> desc, Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
this.desc = desc;
@@ -224,6 +224,8 @@ public class DeployBeanProperty {
return AUDITCOLUMN_ORDER;
} else if (field.getAnnotation(Version.class) != null) {
return VERSIONCOLUMN_ORDER;
} else if (field.getAnnotation(SoftDelete.class) != null) {
return VERSIONCOLUMN_ORDER;
}
return 0;
}
@@ -876,42 +878,12 @@ public class DeployBeanProperty {
return draftReset;
}
public void setSoftDelete(String softDeleteValue) {
public void setSoftDelete() {
this.softDelete = true;
this.softDeleteValue = softDeleteValue;
}
public boolean isSoftDelete() {
return softDelete;
}
public Object getSoftDeleteValue() {
return !softDelete ? null : "".equals(softDeleteValue) ? defaultSoftDeleteValue() : parseSoftDeleteValue();
}
private Object parseSoftDeleteValue() {
if (Boolean.class.equals(propertyType) || boolean.class.equals(propertyType)) {
return Boolean.parseBoolean(softDeleteValue);
}
if (Integer.class.equals(propertyType) || int.class.equals(propertyType)) {
return Integer.parseInt(softDeleteValue);
}
if (Short.class.equals(propertyType) || short.class.equals(propertyType)) {
return Short.parseShort(softDeleteValue);
}
throw new IllegalStateException("@SoftDelete on ["+getFullBeanName()+"] mapped to unsupported type propertyType["+propertyType+"]");
}
private Object defaultSoftDeleteValue() {
if (Boolean.class.equals(propertyType) || boolean.class.equals(propertyType)) {
return Boolean.TRUE;
}
if (Integer.class.equals(propertyType) || int.class.equals(propertyType)) {
return Integer.valueOf(1);
}
if (Short.class.equals(propertyType) || short.class.equals(propertyType)) {
return Short.valueOf("1");
}
throw new IllegalStateException("@SoftDelete on ["+getFullBeanName()+"] mapped to unsupported type propertyType["+propertyType+"]");
}
}
@@ -160,7 +160,7 @@ public class AnnotationFields extends AnnotationParser {
}
SoftDelete softDelete = get(prop, SoftDelete.class);
if (softDelete != null) {
prop.setSoftDelete(softDelete.value());
prop.setSoftDelete();
}
DbJson dbJson = get(prop, DbJson.class);