6. Inheritance


So far we have always been working with the concrete (i.e. most specific type of an object. What about subclassing and interfaces?

To explore this, we will differentiate between different kinds of sensors.

package com.db4o.f1.chapter4;
import java.util.*;
public class SensorReadout {
    private Date time;
    private Car car;
    private String description;
    protected SensorReadout(Date time,Car car,String description) {
        this.time=time;
        this.car=car;
        this.description=description;
    }
    public Car getCar() {
        return car;
    }
    public Date getTime() {
        return time;
    }
    public String getDescription() {
        return description;
    }
    public String toString() {
        return car+" : "+time+" : "+description;
    }
}


package com.db4o.f1.chapter4;
import java.util.*;

public class TemperatureSensorReadout extends SensorReadout {
    private double temperature;
    
    public TemperatureSensorReadout(
            Date time,Car car,
            String description,double temperature) {
        super(time,car,description);
        this.temperature=temperature;
    }
    
    public double getTemperature() {
        return temperature;
    }
    public String toString() {
        return super.toString()+" temp : "+temperature;
    }
}


package com.db4o.f1.chapter4;
import java.util.*;

public class PressureSensorReadout extends SensorReadout {
    private double pressure;
    
    public PressureSensorReadout(
            Date time,Car car,
            String description,double pressure) {
        super(time,car,description);
        this.pressure=pressure;
    }
    
    public double getPressure() {
        return pressure;
    }
    
    public String toString() {
        return super.toString()+" pressure : "+pressure;
    }
}


Our car's snapshot mechanism is changed accordingly.

package com.db4o.f1.chapter4;
import java.util.*;
public class Car {
    private String model;
    private Pilot pilot;
    private List history;
    public Car(String model) {
        this.model=model;
        this.pilot=null;
        this.history=new ArrayList();
    }
    public Pilot getPilot() {
        return pilot;
    }
    public void setPilot(Pilot pilot) {
        this.pilot=pilot;
    }
    public String getModel() {
        return model;
    }
    public SensorReadout[] getHistory() {
        return (SensorReadout[])history.toArray(new SensorReadout[history.size()]);
    }
    
    public void snapshot() {        
        history.add(new TemperatureSensorReadout(
                new Date(),this,"oil",pollOilTemperature()));
        history.add(new TemperatureSensorReadout(
                new Date(),this,"water",pollWaterTemperature()));
        history.add(new PressureSensorReadout(
                new Date(),this,"oil",pollOilPressure()));
    }
    protected double pollOilTemperature() {
        return 0.1*history.size();
    }
    protected double pollWaterTemperature() {
        return 0.2*history.size();
    }
    protected double pollOilPressure() {
        return 0.3*history.size();
    }
    public String toString() {
        return model+"["+pilot+"]/"+history.size();
    }
}



    6.1. Storing


    Our setup code has not changed at all, just the internal workings of a snapshot.

    // storeFirstCar
    Car car1=new Car("Ferrari");
    Pilot pilot1=new Pilot("Michael Schumacher",100);
    car1.setPilot(pilot1);
    db.store(car1);


    // storeSecondCar
    Pilot pilot2=new Pilot("Rubens Barrichello",99);
    Car car2=new Car("BMW");
    car2.setPilot(pilot2);
    car2.snapshot();
    car2.snapshot();
    db.store(car2);



    6.2. Retrieving


    db4o will provide us with all objects of the given type. To collect all instances of a given class, no matter whether they are subclass members or direct instances, we just provide a corresponding prototype.

    // retrieveTemperatureReadoutsQBE
    SensorReadout proto=
        new TemperatureSensorReadout(null,null,null,0.0);
    ObjectSet result=db.queryByExample(proto);
    listResult(result);


    // retrieveAllSensorReadoutsQBE
    SensorReadout proto=new SensorReadout(null,null,null);
    ObjectSet result=db.queryByExample(proto);
    listResult(result);


    This is one more situation where QBE might not be applicable: What if the given type is an interface or an abstract class? Well, there's a little trick to keep in mind: Class objects receive special handling with QBE.

    // retrieveAllSensorReadoutsQBEAlternative
    ObjectSet result=db.queryByExample(SensorReadout.class);
    listResult(result);


    And of course there's our SODA API:

    // retrieveAllSensorReadoutsQuery
    Query query=db.query();
    query.constrain(SensorReadout.class);
    ObjectSet result=query.execute();
    listResult(result);



    6.3. Updating and deleting


    is just the same for all objects, no matter where they are situated in the inheritance tree.

    Just like we retrieved all objects from the database above, we can delete all stored objects to prepare for the next chapter.

    // deleteAll
    ObjectSet result=db.queryByExample(new Object());
    while(result.hasNext()) {
        db.delete(result.next());
    }



    6.4. Conclusion


    Now we have covered all basic OO features and the way they are handled by db4o. We will complete the first part of our db4o walkthrough in the next chapter   by looking at deep object graphs, including recursive structures.


    6.5. Full source


    package com.db4o.f1.chapter4;
    import java.io.*;
    import java.util.Arrays;
    import com.db4o.*;
    import com.db4o.f1.*;
    import com.db4o.query.*;

    public class InheritanceExample extends Util {
        public static void main(String[] args) {
            new File(Util.DB4OFILENAME).delete();
            ObjectContainer db=Db4o.openFile(Util.DB4OFILENAME);
            try {
                storeFirstCar(db);
                storeSecondCar(db);
                retrieveTemperatureReadoutsQBE(db);
                retrieveAllSensorReadoutsQBE(db);
                retrieveAllSensorReadoutsQBEAlternative(db);
                retrieveAllSensorReadoutsQuery(db);
                retrieveAllObjectsQBE(db);
            }
            finally {
                db.close();
            }
        }
        public static void storeFirstCar(ObjectContainer db) {
            Car car1=new Car("Ferrari");
            Pilot pilot1=new Pilot("Michael Schumacher",100);
            car1.setPilot(pilot1);
            db.store(car1);
        }
        
        public static void storeSecondCar(ObjectContainer db) {
            Pilot pilot2=new Pilot("Rubens Barrichello",99);
            Car car2=new Car("BMW");
            car2.setPilot(pilot2);
            car2.snapshot();
            car2.snapshot();
            db.store(car2);
        }
        public static void retrieveAllSensorReadoutsQBE(
                ObjectContainer db) {
            SensorReadout proto=new SensorReadout(null,null,null);
            ObjectSet result=db.queryByExample(proto);
            listResult(result);
        }
        public static void retrieveTemperatureReadoutsQBE(
                ObjectContainer db) {
            SensorReadout proto=
                new TemperatureSensorReadout(null,null,null,0.0);
            ObjectSet result=db.queryByExample(proto);
            listResult(result);
        }
        public static void retrieveAllSensorReadoutsQBEAlternative(
                ObjectContainer db) {
            ObjectSet result=db.queryByExample(SensorReadout.class);
            listResult(result);
        }
        public static void retrieveAllSensorReadoutsQuery(
                ObjectContainer db) {
            Query query=db.query();
            query.constrain(SensorReadout.class);
            ObjectSet result=query.execute();
            listResult(result);
        }
        
        public static void retrieveAllObjectsQBE(ObjectContainer db) {
            ObjectSet result=db.queryByExample(new Object());
            listResult(result);
        }
        
    }




    www.db4o.com