Have "Patients"
To illustrate db4o's API, how replication is crafted, and how a conflict resolution method is supplied, I present a patient-weight monitoring databaseone that a nutritionist might use to keep track of pounds that patients have added or lost.
The database holds objects from two classes: Patient and WeightEntry; see Listing One(a). (For clarity, I only show the data fields of the classes.)
<b>(a)</b> public class Patient { private String name; private long patientID; private ArrayList weightHistory; ... methods for Patient ... } public class WeightEntry { private float weight; private long weightDate; ... methods for WeightEntry ... } <b>(b)</b> public void addWeight(float _weight, long _timeMillis) { // Create new WeightEntry WeightEntry _weightEntry = new WeightEntry(_weight, _timeMillis); // Attach it this.weightHistory.add(_weightEntry); }
The fields defined for Patient are reasonably obvious; they hold the patient's name and a system-assigned patient identification number.
The weightHistory ArrayList tracks the patient's weight. So, when a new weight is recorded, a new WeightEntry object is created and placed on the end of the ArrayList. (We are assuming, here, that new weight recordings are placed at the end of the list, so it stays in a time-sorted order.)
Of course, before replicating anything, you have to get it into the database in the first place. First, let's define a methoda member of Patientthat lets you add an entry onto the ArrayList, as in Listing One(b) (also available electronically). This method instantiates a WeightEntry object, initializes its fields, and attaches it to the ArrayList. Now, you can create a patient and store his information into the database; see Listing Two.
// Make the database replication-capable Db4o.configure().generateUUIDs(Integer.MAX_VALUE); Db4o.configure().generateVersionNumbers(Integer.MAX_VALUE); // Open a database (Create if it does not exist) ObjectContainer patientDB = Db4o.openFile("PATIENTA.YAP"); // Create a new Patient Patient _patient = new Patient( "John Doe", 001L); // Add a weight _patient.addWeight((float)190.0, java.lang.System.currentTimeMillis()); // Put the new patient in the database patientDB.set(_patient); // Commit the transaction and close the database patientDB.commit(); patientDB.close();
This is really all you need to store the patient John Doe, whose ID is 001, and whose weight at the time this snippet was run was 190 lbs.
Again, db4o's API is remarkably succinct. First, the class that models a database is db4o's ObjectContainer. To put an object into a database, you merely need to pass a reference to that object to the ObjectContainer's set() method. The db4o engine discovers the object's structure invisibly, regardless of the depth and complexity of that structure. So, in our example, not only is the Patient object stored, but its member ArrayList (weightHistory) and the WeightEntry object (within the ArrayList) are all stored as well. This characteristicthat all objects referenced by an object that is persistent are also persistentis referred to as "persistence by reachability."
Notice that, before I opened the database, I called a pair of methods that configured the db4o engine to make the database replication capable. Specifically, I set global parameters so that any database subsequently created by the application would have UUIDs and version numbers enabled. Again, these options are going to cost us a bit in terms of performance and space consumed, so you only set them for databases to be replicated.