@Override
 protected Object retrieveEntity(PersistentEntity pe, Serializable key) {
   List<Criterion> criteria = new ArrayList<Criterion>(1);
   criteria.add(new IdEquals(key));
   return IteratorUtil.singleOrNull(
       new Neo4jQuery(session, pe, this).executeQuery(pe, new Conjunction(criteria)).iterator());
 }
 @Override
 protected List<Object> retrieveAllEntities(PersistentEntity pe, Iterable<Serializable> keys) {
   List<Criterion> criterions = new ArrayList<Criterion>(1);
   criterions.add(new In("id", IteratorUtil.asCollection(keys)));
   Junction junction = new Conjunction(criterions);
   return new Neo4jQuery(session, pe, this).executeQuery(pe, junction);
 }
 @Override
 protected List<Serializable> persistEntities(
     PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objs) {
   List<Serializable> result = new ArrayList<Serializable>();
   for (Object obj : objs) {
     result.add(persistEntity(pe, obj));
   }
   return result;
 }
  @Override
  protected void deleteEntities(
      PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects) {
    List<EntityAccess> entityAccesses = new ArrayList<EntityAccess>();
    List<Object> ids = new ArrayList<Object>();
    Map<PersistentEntity, Collection<Object>> cascades =
        new HashMap<PersistentEntity, Collection<Object>>();

    for (Object obj : objects) {
      EntityAccess entityAccess = createEntityAccess(pe, obj);
      if (cancelDelete(pe, entityAccess)) {
        return;
      }
      entityAccesses.add(entityAccess);
      ids.add(entityAccess.getIdentifier());

      // populate cascades
      for (Association association : pe.getAssociations()) {
        Object property = entityAccess.getProperty(association.getName());
        if (association.isOwningSide()
            && association.doesCascade(CascadeType.REMOVE)
            && (property != null)) {

          PersistentEntity associatedEntity = association.getAssociatedEntity();

          Collection<Object> cascadesForPersistentEntity = cascades.get(associatedEntity);
          if (cascadesForPersistentEntity == null) {
            cascadesForPersistentEntity = new ArrayList<Object>();
            cascades.put(associatedEntity, cascadesForPersistentEntity);
          }

          if (association instanceof ToOne) {
            cascadesForPersistentEntity.add(property);
          } else {
            cascadesForPersistentEntity.addAll((Collection<?>) property);
          }
        }
      }
    }

    for (Map.Entry<PersistentEntity, Collection<Object>> entry : cascades.entrySet()) {
      deleteEntities(entry.getKey(), entry.getValue());
    }

    getCypherEngine()
        .execute(
            String.format(
                "MATCH (n:%s) WHERE n.__id__ in {ids} OPTIONAL MATCH (n)-[r]-() DELETE r,n",
                ((GraphPersistentEntity) pe).getLabel()),
            Collections.singletonMap("ids", ids));

    for (EntityAccess entityAccess : entityAccesses) {
      firePostDeleteEvent(pe, entityAccess);
    }
  }