@@ -330,13 +330,25 @@ public abstract class AbstractCRUDDAO<E extends Identifiable> | |||
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<E extends Identifiable> | |||
)).addOrder(order), 0, getFinderMaxResults()); | |||
} | |||
@Transactional(readOnly=true) | |||
@Override public List<E> 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<E> findByFieldLikeAndNewerThan(String likeField, String likeValue, Long mtime) { | |||
DetachedCriteria criteria = criteria().add(and( | |||
@@ -28,6 +28,7 @@ public interface DAO<E extends Identifiable> { | |||
List<E> findByFieldLike(String field, String value); | |||
List<E> findByFieldEqualAndFieldLike(String eqField, Object eqValue, String likeField, String likeValue); | |||
List<E> findByFieldEqualAndFieldLike(String eqField, Object eqValue, String likeField, String likeValue, Order order); | |||
List<E> findByFieldEqualAndFieldNotEqual(String eqField, Object eqValue, String neField, String neValue); | |||
List<E> findByFieldIn(String field, Object[] values); | |||
List<E> findByFieldIn(String field, Collection<?> values); | |||
@@ -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<Class<? extends Identifiable>> excludes) { | |||
public void deleteDependencies (Identifiable thing, | |||
final Collection<Class<? extends Identifiable>> excludeDepClasses, | |||
final Collection<String> 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())); | |||
} | |||
} | |||
} | |||
); | |||