ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.


AddThis Social Bookmark Button

Agile Object to Relational Database Replication with db4o
Pages: 1, 2, 3, 4, 5, 6, 7, 8

Agile Development: Schema Evolution

One of the characteristics of agile development is that designs are often refactored. As result, the data model may evolve during the lifetime of a project. What happens if the data model of the db4o databases is changed? First, let's see a simple example of how db4o can handle schema changes to a live native database. Let's say it has been decided that the two separate street1 and street2 fields in the Address class are no longer appropriate, and that we would rather have a single street field. However, there is data in the databases, so we want to make sure of the following:

  • Existing street1 and street2 data is to be merged into the new street field.
  • New objects will only contain a street field.

The obvious thing to do is to modify the Address class definition to include the new field. We can also include the following method, onActivate. db4o will call a method with this name, if it exists, for any object when it is activated--in other words, when it is retrieved with a query and a reference to it is created in memory.

public void objectOnActivate(ObjectContainer container) {
    if((street == null) && (street1 !=null)) {
        street = street1;
        if (street2 != null)
            street = street + ", " + street2;

Next, we run a query for each db4o database that activates and re-stores all of the objects in the database:

ObjectContainer objectContainer = Db4o.openFile("c:/mobileone.yap");
ObjectSet data = objectContainer.get(Address.class);
objectContainer = Db4o.openFile("c:/mobiletwo.yap");
data = objectContainer.get(Address.class);

Now the schema has been changed. The values stored in the original fields remain in the database, but all objects will contain the correct value in the new street field, and all new objects should use the refactored field. Figure 3 shows the Address object tree node in one db4o database viewed in the ObjectManager.

Figure 3
Figure 3. The Address objects in the refactored db4o database

We could now change the class definition for Address again by removing the original street1 and street2 fields, leaving only the refactored field. This would ensure that new objects only have values in the new street field, and that only the new field can be accessed by queries. This would still not remove the old data from the database.

Now that the db4o database schema has been changed, the MySQL schema will also need to be changed, and the data updated to match the changes in the db4 databases. This can be done easily by repeating the replication process. The only intervention that is required before doing this is to alter the Hibernate configuration file for the Address class, Address.hbm.xml, so that only the new street field is included in the mapping.

<!-- Address.hbm.xml -->
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
                "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

<hibernate-mapping default-access="field" default-lazy="false"
    <class name="com.onjava.db4o.drs.Address" table="ADDRESSES">
        <id column="id" type="java.lang.Long">
            <generator class="native"/>
        <property name="street" type="java.lang.String"/>  
        <property name="city" type="java.lang.String"/>
        <property name="zip" type="java.lang.String"/>
        <property name="country" type="java.lang.String"/>

The replication process is repeated, again simply by executing the code listed earlier, and the ADDRESSES table in the MySQL database now contains the data shown in the query below. The street column has been added to the table and is populated with the correct data. The original fields are still in the table (though not shown in this query), but new objects will not map onto them.

mysql>  select id, street, city, zip, country from addresses;
| id | street                    | city       | zip      | country |
| 1  | 2 Second Street, Uptown   | Seattle    | WA 98200 | USA     |
| 2  | 1 First Street, Downtown  | Pittsburgh | PA 15121 | USA     |
| 3  | 3 Third Street            | Denver     | CO 80300 | USA     |
| 4  | 4 Fourth Street, Downtown | Charlotte  | NC 28300 | USA     |
4 rows in set (0.00 sec)


db4o is a compact native object database that is particularly well suited for use embedded within distributed applications involving partially connected devices (although it can also be useful in many other types of system). It offers significant advantages over relational databases in this role: it offers a small footprint and zero administration (you don't have to create tables, as the application's classes directly define the database schema), and can lead to a reduction in development time. Since it basically uses the application's object model directly, it can easily handle models that are difficult to map to relational tables.

On the other hand, it stores data in a way that is unfamiliar to most database developers, with data closely tied to the application code. These points will make some companies nervous: they prefer to have data in an enterprise RDBMS, for example, for access by other applications. db4o's new dRS replication service rewrites some of the rules here: it uses Hibernate to allow easy replication of native object data to any RDBMS supported by Hibernate. db4o is well suited to agile development, as refactoring is well supported, and replication carries this support forward into the RDBMS. For those who are interested in the idea of object databases, but have good reasons for using relational databases, too, db4o and dRS are worth a look.


Jim Paterson is a Lecturer at Glasgow Caledonian University in the UK , specializing in web development and object-oriented software development.

Return to ONJava.com.