mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
FIX: improved support for @DbForeignKey(noConstraint = true) (#1527)
* FIX: improved support for DbForeignKey(noConstraint = true) * FIX: Tests for mariadb and sqlserver * FIX: SqlServer was still incorrect * FIX: not ommit property for formula * Update BeanDescriptor.java (typo fix) fix typo column (no code change!)
This commit is contained in:
committed by
Rob Bygrave
parent
3c6a52da31
commit
ce403e72a7
@@ -829,7 +829,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
if (lazyLoadFailure) {
|
||||
// failed when batch lazy loaded by another bean in the batch
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
}
|
||||
|
||||
if (lazyLoadProperty == -1) {
|
||||
|
||||
@@ -168,13 +168,8 @@ public class LoadBeanRequest extends LoadRequest {
|
||||
// necessary but allow processing to continue until it is accessed by client code
|
||||
Object id = desc.getId(ebi.getOwner());
|
||||
if (!loadedIds.contains(id)) {
|
||||
if (desc.isSoftDelete()) {
|
||||
// assume this is logically deleted (hence not found)
|
||||
desc.setSoftDeleteValue(ebi.getOwner());
|
||||
} else {
|
||||
logger.info("Lazy loading unsuccessful for type:" + desc.getName() + " id:" + id + " - expecting when bean has been deleted");
|
||||
ebi.setLazyLoadFailure(id);
|
||||
}
|
||||
// assume this is logically deleted (hence not found)
|
||||
desc.markAsDeleted(ebi.getOwner());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.Formula;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -496,7 +497,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
DeployBeanPropertyLists listHelper = new DeployBeanPropertyLists(owner, this, deploy);
|
||||
|
||||
this.softDeleteProperty = listHelper.getSoftDeleteProperty();
|
||||
this.softDelete = (softDeleteProperty != null);
|
||||
// if formula is set, the property is virtual only (there is no column in db) the formula must evaluate to true,
|
||||
// if there is a join to a deleted bean. Example: '@Formula(select = "${ta}.user_id is null")'
|
||||
// this is required to support markAsDelete on beans that may have no FK constraint.
|
||||
this.softDelete = (softDeleteProperty != null && !softDeleteProperty.isFormula());
|
||||
this.idProperty = listHelper.getId();
|
||||
this.versionProperty = listHelper.getVersionProperty();
|
||||
this.unmappedJson = listHelper.getUnmappedJson();
|
||||
@@ -2920,6 +2924,20 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
return softDeleteProperty.getSoftDeleteDbPredicate(tableAlias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markAsDeleted(EntityBean bean) {
|
||||
if (softDeleteProperty == null) {
|
||||
Object id = getId(bean);
|
||||
logger.info("(Lazy) loading unsuccessful for type:{} id:{} - expecting when bean has been deleted", getName(), id);
|
||||
bean._ebean_getIntercept().setLazyLoadFailure(id);
|
||||
} else {
|
||||
setSoftDeleteValue(bean);
|
||||
bean._ebean_getIntercept().setLoaded();
|
||||
setAllLoaded(bean);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if this entity type is draftable.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
public interface STreePropertyAssocOne extends STreePropertyAssoc {
|
||||
@@ -13,4 +14,14 @@ public interface STreePropertyAssocOne extends STreePropertyAssoc {
|
||||
* Return the scalar type of the associated id property.
|
||||
*/
|
||||
ScalarType<?> getIdScalarType();
|
||||
|
||||
/**
|
||||
* Returns true, if this relation has a foreign key.
|
||||
*/
|
||||
boolean hasForeignKey();
|
||||
|
||||
/**
|
||||
* Return the property value as an entity bean from the parent.
|
||||
*/
|
||||
public EntityBean getValueAsEntityBean(EntityBean parentBean);
|
||||
}
|
||||
|
||||
@@ -132,5 +132,13 @@ public interface STreeType {
|
||||
*/
|
||||
void inheritanceLoad(SqlBeanLoad sqlBeanLoad, STreeProperty property, DbReadContext ctx);
|
||||
|
||||
/**
|
||||
* Mark the bean as deleted by setting the softDelete property to true.
|
||||
*
|
||||
* This works also, if there is only a virtual softDelete property computed by a formula.
|
||||
*
|
||||
* If there is no softdelete property, it sets the lazyLoadFailure flag in EBI.
|
||||
*/
|
||||
void markAsDeleted(EntityBean bean);
|
||||
|
||||
}
|
||||
|
||||
@@ -498,8 +498,11 @@ public final class SqlTreeBuilder {
|
||||
|
||||
for (STreePropertyAssocOne propertyAssocOne : desc.propsOne()) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
if (queryProps != null && queryProps.isIncludedBeanJoin(propertyAssocOne.getName())) {
|
||||
// if it is a joined bean... then don't add the property
|
||||
if (queryProps != null
|
||||
&& queryProps.isIncludedBeanJoin(propertyAssocOne.getName())
|
||||
&& propertyAssocOne.hasForeignKey()
|
||||
&& !propertyAssocOne.isFormula()) {
|
||||
// if it is a joined bean with FK constraint... then don't add the property
|
||||
// as it will have its own entire Node in the SqlTree
|
||||
} else {
|
||||
selectProps.add(propertyAssocOne);
|
||||
|
||||
@@ -266,6 +266,14 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (id == null) {
|
||||
// bean must be null...
|
||||
localBean = null;
|
||||
|
||||
// ... but there may exist as reference bean in parent which has to be marked as deleted.
|
||||
if (parentBean != null && nodeBeanProp instanceof STreePropertyAssocOne) {
|
||||
contextBean = ((STreePropertyAssocOne)nodeBeanProp).getValueAsEntityBean(parentBean);
|
||||
if (contextBean != null) {
|
||||
desc.markAsDeleted(contextBean);
|
||||
}
|
||||
}
|
||||
} else if (!temporalVersions) {
|
||||
// check the PersistenceContext to see if the bean already exists
|
||||
contextBean = (EntityBean) localDesc.contextPutIfAbsent(persistenceContext, id, localBean);
|
||||
|
||||
Reference in New Issue
Block a user