You are here: Object Lifecycle > Working With Structured Objects > Deleting Structured Objects

Deleting Structured Objects

As we have already seen, we call delete() on objects to get rid of them.

StructuredExample.java: deleteFlat
private static void deleteFlat(ObjectContainer container)  {
    ObjectSet result = container.query(new Predicate<Car>()  {
      public boolean match(Car car)  {
        return car.getModel().equals("Ferrari");
      }
    });
    Car found = (Car) result.next();
    container.delete(found);
    result = container.queryByExample(new Car(null));
    listResult(result);
  }

Fine, the car is gone. What about the pilots?

StructuredExample.java: retrieveAllPilotsQBE
private static void retrieveAllPilotsQBE(ObjectContainer container)  {
    Pilot proto = new Pilot(null, 0);
    ObjectSet result = container.queryByExample(proto);
    listResult(result);
  }

Ok, this is no real surprise - we don't expect a pilot to vanish when his car is disposed of in real life, too. But what if we want an object's children to be thrown away on deletion, too?

Recursive Deletion

The problem of recursive deletion (and its solution, too) is quite similar to the update problem. Let's configure db4o to delete a car's pilot, too, when the car is deleted.

StructuredExample.java: deleteDeepPart1
private static Configuration deleteDeepPart1()  {
    Configuration configuration = Db4o.newConfiguration();
    configuration.objectClass("com.db4o.f1.chapter2.Car")
        .cascadeOnDelete(true);
    return configuration;
  }

StructuredExample.java: deleteDeepPart2
private static void deleteDeepPart2(ObjectContainer container)  {
    ObjectSet result = container.query(new Predicate<Car>()  {
      public boolean match(Car car)  {
        return car.getModel().equals("BMW");
      }
    });
    Car found = (Car) result.next();
    container.delete(found);
    result = container.query(new Predicate<Car>()  {
      public boolean match(Car car)  {
        return true;
      }
    });
    listResult(result);
  }

 

Cascade on delete configuration only affects the direct children of the deleted object. For example, if Pilot class will have a field idBook of Class IdBook, IdBook instances won't be deleted if the configuration above will be used. In order to delete IdBook instances you will need to enable cascadeOnDelete for Pilot class.

Again: Note that all configuration must take place before the ObjectContainer is opened.

Another way to organize cascaded deletion is using callbacks. The callbacks allow you to specify explicitly, which objects are to be deleted.

Recursive Deletion Revisited

But wait - what happens if the children of a removed object are still referenced by other objects?

StructuredExample.java: deleteDeepRevisited
private static void deleteDeepRevisited(ObjectContainer container)  {
    ObjectSet result = container.query(new Predicate<Pilot>()  {
      public boolean match(Pilot pilot)  {
        return pilot.getName().equals("Michael Schumacher");
      }
    });
    Pilot pilot = (Pilot) result.next();
    Car car1 = new Car("Ferrari");
    Car car2 = new Car("BMW");
    car1.setPilot(pilot);
    car2.setPilot(pilot);
    container.store(car1);
    container.store(car2);
    container.delete(car2);
    result = container.query(new Predicate<Car>()  {
      public boolean match(Car car)  {
        return true;
      }
    });
    listResult(result);
  }

StructuredExample.java: retrieveAllPilots
private static void retrieveAllPilots(ObjectContainer container)  {
    ObjectSet result = container.queryByExample(Pilot.class);
    listResult(result);
  }

Currently db4o does not check whether objects to be deleted are referenced anywhere else, so please be very careful when using this feature.However it is fairly easy to implement referential checking on deletion using deleting() callback. See Callbacks chapter for more information.

Download example code:

Java