diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/dao/AbstractCRUDDAO.java b/wizard-server/src/main/java/org/cobbzilla/wizard/dao/AbstractCRUDDAO.java index 6c3db92..973a9d4 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/dao/AbstractCRUDDAO.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/dao/AbstractCRUDDAO.java @@ -330,13 +330,25 @@ public abstract class AbstractCRUDDAO return count; } - public int bulkDelete(String field, Object value) { + public int bulkDeleteAndNotUuid(String field, Object value) { return bulkDelete(field, value, true); } + + public int bulkDelete(String field, Object value) { return bulkDelete(field, value, false); } + + public static final String EX_UUID = "__exclude_uuid__"; + + private int bulkDelete(String field, Object value, boolean notUuid) { final Session session = getHibernateTemplate().getSessionFactory().getCurrentSession(); final Query query; + final String deleteSql = "DELETE FROM " + getEntityClass().getSimpleName() + " WHERE "; if (value == null) { - query = session.createQuery("DELETE FROM "+getEntityClass().getSimpleName()+" WHERE "+field+" IS NULL"); + query = session.createQuery(deleteSql + field + " IS NULL"); + + } else if (notUuid) { + query = session.createQuery(deleteSql + field + " = :" + field + " AND uuid != :" + EX_UUID) + .setParameter(field, value) + .setParameter(EX_UUID, value); } else { - query = session.createQuery("DELETE FROM "+getEntityClass().getSimpleName()+" WHERE "+field+" = :"+field) + query = session.createQuery(deleteSql + field + " = :" + field) .setParameter(field, value); } final int count = query.executeUpdate(); @@ -432,6 +444,15 @@ public abstract class AbstractCRUDDAO )).addOrder(order), 0, getFinderMaxResults()); } + @Transactional(readOnly=true) + @Override public List findByFieldEqualAndFieldNotEqual(String eqField, Object eqValue, String neField, String neValue) { + final Criterion expr1 = eqValue == null ? isNull(eqField) : eq(eqField, eqValue); + return list(criteria().add(and( + expr1, + ne(neField, neValue) + )).addOrder(getDefaultSortOrder()), 0, getFinderMaxResults()); + } + @Transactional(readOnly=true) public List findByFieldLikeAndNewerThan(String likeField, String likeValue, Long mtime) { DetachedCriteria criteria = criteria().add(and( diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/dao/DAO.java b/wizard-server/src/main/java/org/cobbzilla/wizard/dao/DAO.java index d483016..86d35d8 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/dao/DAO.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/dao/DAO.java @@ -28,6 +28,7 @@ public interface DAO { List findByFieldLike(String field, String value); List findByFieldEqualAndFieldLike(String eqField, Object eqValue, String likeField, String likeValue); List findByFieldEqualAndFieldLike(String eqField, Object eqValue, String likeField, String likeValue, Order order); + List findByFieldEqualAndFieldNotEqual(String eqField, Object eqValue, String neField, String neValue); List findByFieldIn(String field, Object[] values); List findByFieldIn(String field, Collection values); diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/server/config/PgRestServerConfiguration.java b/wizard-server/src/main/java/org/cobbzilla/wizard/server/config/PgRestServerConfiguration.java index 394658a..af1d1bc 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/server/config/PgRestServerConfiguration.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/server/config/PgRestServerConfiguration.java @@ -38,6 +38,7 @@ import static org.cobbzilla.util.daemon.ZillaRuntime.*; import static org.cobbzilla.util.http.URIUtil.getHost; import static org.cobbzilla.util.http.URIUtil.getPort; import static org.cobbzilla.util.io.FileUtil.*; +import static org.cobbzilla.util.reflect.ReflectionUtil.forName; import static org.cobbzilla.util.security.ShaUtil.sha256_hex; import static org.cobbzilla.util.string.StringUtil.camelCaseToSnakeCase; import static org.cobbzilla.util.string.StringUtil.checkSafeShellArg; @@ -356,20 +357,34 @@ public class PgRestServerConfiguration extends RestServerConfiguration implement return dependencyDAOCache.computeIfAbsent(entityClass, c -> getDependencyRefs(c, getDependencies(c))); } - public void deleteDependencies (Identifiable thing) { deleteDependencies(thing, null); } + public void deleteDependencies (Identifiable thing) { deleteDependencies(thing, null, null); } - public void deleteDependencies (Identifiable thing, Collection> excludes) { + public void deleteDependencies (Identifiable thing, + final Collection> excludeDepClasses, + final Collection excludeDepFields) { dependencyRefs(thing.getClass()).forEach( dep -> { - if (excludes != null && excludes.stream().anyMatch(depClass -> depClass.getName().equals(dep.getEntity()))) { - log.debug("deleteDependencies("+thing+"): excluding: "+dep); + if (excludeDepClasses != null && excludeDepClasses.stream().anyMatch(depClass -> depClass.getName().equals(dep.getEntity()))) { + log.debug("deleteDependencies("+thing+"): excluding by dep class: "+dep); + return; + } + if (excludeDepFields != null && excludeDepFields.stream().anyMatch(depField -> depField.equals(dep.getField()))) { + log.debug("deleteDependencies("+thing+"): excluding by dep field: "+dep); return; } final DAO dao = getDaoForEntityClass(dep.getEntity()); if (dao instanceof AbstractCRUDDAO) { - ((AbstractCRUDDAO) dao).bulkDelete(dep.getField(), thing.getUuid()); + if (forName(dep.getEntity()).isAssignableFrom(thing.getClass())) { + ((AbstractCRUDDAO) dao).bulkDeleteAndNotUuid(dep.getField(), thing.getUuid()); + } else { + ((AbstractCRUDDAO) dao).bulkDelete(dep.getField(), thing.getUuid()); + } } else { - dao.delete(dao.findByField(dep.getField(), thing.getUuid())); + if (forName(dep.getEntity()).isAssignableFrom(thing.getClass())) { + dao.delete(dao.findByFieldEqualAndFieldNotEqual(dep.getField(), thing.getUuid(), Identifiable.UUID, thing.getUuid())); + } else { + dao.delete(dao.findByField(dep.getField(), thing.getUuid())); + } } } );