Channels ▼
RSS

Database

Inside the db4o Database

Source Code Accompanies This Article. Download It Now.


First Replication

Once you have a database created and filled with patient information, suppose you want to replicate that information into another database. I refer to the original database as PATIENTA and the database being replicated into as PATIENTB.

In db4o, replication is a three-step process:

  • First, you must instantiate a ReplicationProcess object. This object must implement a ReplicationConflictHandler(), which is the deus ex machina callback method mentioned earlier. This method is called whenever the version information in both objects has changed since the last synchronization (per db4o's replication plan).
  • Next, you define a query that guides the replication process. In most cases, this query is crafted to return all the objects in the database (thus causing all objects to be replicated). You can modify the query to restrict it to a subset of the database's objects, and thereby fine tune which objects participate in the replication.
  • Finally, you execute the query. Each object returned by the query is handed over to the ReplicationProcess object's replicate() method, which does all the low-level dirty work. It all looks like Listing Three.

// Set things up for replication
Db4o.configure().generateUUIDs(Integer.MAX_VALUE);
Db4o.configure().generateVersionNumbers(Integer.MAX_VALUE);
// Open both databases
ObjectContainer patientADB = Db4o.openFile("PATIENTA.YAP");
ObjectContainer patientBDB = Db4o.openFile("PATIENTB.YAP");
// Create a ReplicationProcess object
  patientADB.ext().replicationBegin(
    patientBDB,
    new ReplicationConflictHandler() {
      public Object resolveConflict(
        ReplicationProcess replicationProcess,
        Object a,
        Object b) { return a; }
  });
//  PATIENTB
replication.setDirection(patientADB,patientBDB);
// Do the replication
Query q = patientADB.query();
ObjectSet replicationSet = q.execute();
while (replicationSet.hasNext()) {
  replication.replicate(replicationSet.next());
}
replication.commit();
// Close both databases
patientADB.close();
Listing Three

After opening the databases, you create a ReplicationProcess object via a call to the replicationBegin() method of the ObjectContainer's extended interface (available through the ext() method). The replicationBegin() method is called on the primary database's ObjectContainer, and takes as its first argument the secondary database's ObjectContainer. Its other argument—which we have supplied as an anonymous object—is the ReplicationConflictHandler object. As you can see, our conflict handler is rather simple. If given a choice between Object a (from PATIENTA) or Object b (from PATIENTB), we choose Object a every time.

Next, we call setDirection() on the ReplicationProcess object, specifying the direction of the replication as going from PATIENTA to PATIENTB.

The query object I create in the next section of code is simply an empty query, which returns all objects in the database. The execution of the query returns an ObjectSet, through which we iterate to process all the objects that are to be replicated by passing those objects into the replicate() method. When it's all done, we commit() the query and close the databases; see Listing Four.

// Set things up for replication
Db4o.configure().generateUUIDs(Integer.MAX_VALUE);
Db4o.configure().generateVersionNumbers(Integer.MAX_VALUE);
// Open both databases
ObjectContainer patientADB = Db4o.openFile("PATIENTA.YAP");
ObjectContainer patientBDB = Db4o.openFile("PATIENTB.YAP");
// Create a ReplicationProcess object
ReplicationProcess replication =
  patientBDB.ext().replicationBegin(
    patientADB,
      public Object resolveConflict(
        ReplicationProcess replicationProcess,
        Object b,
        Object a) { return b; }
  });
// Set the direction from PATIENTB to
replication.setDirection(patientBDB,patientADB);
// Do the replication
replication.whereModified(q);
ObjectSet replicationSet = q.execute();
while (replicationSet.hasNext()) {
  replication.replicate(replicationSet.next());
}
replication.commit();
// Close both databases
patientADB.close();
patientBDB.close();
Listing Four

Pretty simple. And, happily, synchronizing any changes in PATIENTB back to PATIENTA is equally simple. With one small addition, this code is more or less a mirror image of the aforementioned code. (It's a mirror image because we're replicating in the opposite direction.)

As you can see, this code is virtually identical to its preceding cousin. Most differences stem from the fact that the direction is now from PATIENTB to PATIENTA. Hence, the ReplicationProcess object and the conflict resolution handler are modified accordingly. In addition, the setDirection() method identifies PATIENTB as the originating database.

The other addition is a constraint that I attached to the query that drives the replication. Specifically, I called the ReplicationProcess's whereModified() method, with the query as its sole argument. This constrains the query so that it returns only those objects that have changed since the last replication. This significantly speeds the process because objects that have not changed need not be handed to the replication code at all. (New objects are, of course, considered by the replication process to be modified.)

Replication Complete

The complete source code for the patient database is available electronically; see "Resource Center," page 5. The code consists of a number of small, easily extended applications. One creates the primary patient database; another replicates its contents to a secondary database. Another application modifies the secondary database, and I've provided code for replicating back to the master, as well as a simple application that displays the database contents.

You can explore a database even deeper with db4o's ObjectManager. This is a standalone database browser application that lets you open a database and navigate through all its contained objects, object references, data member fields, and so on. You can even modify individual data members. In short, with the help of ObjectManager, you can experiment with more complex replication code, and examine the resulting database to see the effects.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video