mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 23:56:36 +00:00
#1447 - Delete query ... should honour cascading delete if defined
See also PR #1445 with the failing test case
This commit is contained in:
@@ -1384,7 +1384,18 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
request.markNotQueryOnly();
|
||||
return request.delete();
|
||||
if (request.isDeleteByStatement()) {
|
||||
return request.delete();
|
||||
} else {
|
||||
// escalate to fetch the ids of the beans to delete due
|
||||
// to cascading deletes or l2 caching etc
|
||||
List<Object> ids = request.findIds();
|
||||
if (ids.isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return persister.deleteByIds(request.getBeanDescriptor(), ids, request.getTransaction(), false);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
|
||||
@@ -116,6 +116,11 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeleteByStatement() {
|
||||
return beanDescriptor.isDeleteByStatement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMultiValueIdSupported() {
|
||||
return beanDescriptor.isMultiValueIdSupported();
|
||||
|
||||
@@ -63,6 +63,11 @@ public interface Persister {
|
||||
*/
|
||||
int deleteMany(Class<?> beanType, Collection<?> ids, Transaction transaction, boolean permanent);
|
||||
|
||||
/**
|
||||
* Delete multiple beans when escalated from a delete query.
|
||||
*/
|
||||
int deleteByIds(BeanDescriptor<?> descriptor, List<Object> idList, Transaction transaction, boolean permanent);
|
||||
|
||||
/**
|
||||
* Execute the Update.
|
||||
*/
|
||||
|
||||
@@ -171,4 +171,9 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
|
||||
* Set profile location for "find all" if not set.
|
||||
*/
|
||||
void profileLocationAll();
|
||||
|
||||
/**
|
||||
* Return true if delete by statement is allowed for this type given cascade rules etc.
|
||||
*/
|
||||
boolean isDeleteByStatement();
|
||||
}
|
||||
|
||||
@@ -680,6 +680,12 @@ public final class DefaultPersister implements Persister {
|
||||
return delete(descriptor, id, null, transaction, deleteMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteByIds(BeanDescriptor<?> descriptor, List<Object> idList, Transaction transaction, boolean permanent) {
|
||||
DeleteMode deleteMode = (permanent || !descriptor.isSoftDelete()) ? DeleteMode.HARD : DeleteMode.SOFT;
|
||||
return delete(descriptor, null, idList, transaction, deleteMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete by Id or a List of Id's.
|
||||
*/
|
||||
@@ -739,18 +745,20 @@ public final class DefaultPersister implements Persister {
|
||||
// OneToMany's with delete cascade
|
||||
BeanPropertyAssocMany<?>[] manys = descriptor.propertiesManyDelete();
|
||||
for (BeanPropertyAssocMany<?> many : manys) {
|
||||
BeanDescriptor<?> targetDesc = many.getTargetDescriptor();
|
||||
// only cascade soft deletes when supported by target
|
||||
if (deleteMode.isHard() || targetDesc.isSoftDelete()) {
|
||||
if (deleteMode.isHard() && targetDesc.isDeleteByStatement()) {
|
||||
// we can just delete children with a single statement
|
||||
SqlUpdate sqlDelete = many.deleteByParentId(id, idList);
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
} else {
|
||||
// we need to fetch the Id's to delete (recurse or notify L2 cache)
|
||||
List<Object> childIds = many.findIdsByParentId(id, idList, t, null);
|
||||
if (!childIds.isEmpty()) {
|
||||
delete(targetDesc, null, childIds, t, deleteMode);
|
||||
if (!many.isManyToMany()) {
|
||||
BeanDescriptor<?> targetDesc = many.getTargetDescriptor();
|
||||
// only cascade soft deletes when supported by target
|
||||
if (deleteMode.isHard() || targetDesc.isSoftDelete()) {
|
||||
if (deleteMode.isHard() && targetDesc.isDeleteByStatement()) {
|
||||
// we can just delete children with a single statement
|
||||
SqlUpdate sqlDelete = many.deleteByParentId(id, idList);
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
} else {
|
||||
// we need to fetch the Id's to delete (recurse or notify L2 cache)
|
||||
List<Object> childIds = many.findIdsByParentId(id, idList, t, null);
|
||||
if (!childIds.isEmpty()) {
|
||||
delete(targetDesc, null, childIds, t, deleteMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user