E-Database

Object Databases And Java

Pratik Patel

New Java interfaces to OO databases can improve your development time

In this final installment of E-Database, I would like to thank the many readers who have sent me email. I hope you have enjoyed reading these columns as much as I have writing them. I want to end the column with a bang, and I think the promise of using object-oriented databases with Java should sufficiently spark your interest. I’ve discussed Java in this spot before; just a few months ago I outlined the course of Java in enterprise computing (“Java: Gearing Up for the Enterprise,” April 1998). While they are not native Java technology, object databases represent another important area where Java is quickly maturing. The use of object databases in your Java application can significantly improve the development time of a project, as compared to using an RDBMS.

Object databases differ from relational databases in many ways, but the cornerstone of both types of database technology involves two very different foundations. Relational databases are founded on relations manifested as tables, attributes, foreign keys, and so on—known as the relational model. Object databases are based upon the object model—a hierarchy of parent-child objects that can be nested within each other. If you’ve developed with C++, Java, or Smalltalk, you should already be familiar with how to build basic object models. We will use a simple object model in our examples so you can follow along and learn the essentials of storing data from your Java application.

Why Object Databases?

The best reason for using an object database is not a technical one: If you’re developing with an object-oriented language, doesn’t it make sense to store your data in an OO data engine? I could easily write a book comparing object databases and relational databases—indeed, there are already books out there that do. I will highlight just a few points for you here so we can move into our tutorial on the Object Data Management Group (ODMG) Java binding for object databases.

As I just said, the best reason for using an object database in a pragmatic sense is that you are storing your Java objects natively as objects. If you’re currently developing a Java application that uses a relational database, you’re already well aware of the pain of having to translate your Java objects to relational table format and vice versa. Writing this code can take a significant amount of time and add a fair amount of overhead to your application. Additionally, you have to deal with querying your data in a relational format, which means you have to shift your thinking from object to relational and back again, inevitably adding complexity to your project. Object databases store your Java objects just as you have designed them in your application, so querying an object database only requires that you know the object model that is already present in the application.

Object databases also easily handle queries that would require multiple joins in relational databases. If you are modeling complex data in your Java application, developing a relational model would likely involve creating queries that have multiple joins. As you know, multiple join queries are slow and resource intensive; object models don’t have this drawback.

Finally, using an object database with Java requires less overhead programming than using the JDBC to connect to a relational database. If you’ve used the JDBC in a Java application, you’re aware of the need to create result sets and iterate through the result set objects row by row to retrieve data. Because you’re storing the data as native objects, you don’t have to worry about wrapping and unwrapping objects from object to relational formats.

Getting Started with Object Databases

The examples in this column will use Object Design Inc.’s PSE Pro. Although it’s not a full-blown OODBMS, it is a single-user, lightweight object database engine that you can download from ODI’s Web site (www.odi.com). PSE Pro will let you investigate object databases, and you can upgrade your Java application from PSE Pro to an OODBMS—such as Object Design’s Objectstore, POET’s Universal Object Server, Versant’s ODBMS, Objectivity’s Objectivity/DB, or Ardent’s O2—with relative ease. These enterprise-scale products have many of the features that you expect from an industrial-strength data management system.

Most object databases’ Java programming interface is based on the ODMG Java binding. The ODMG maintains this standard, and many of the popular OODBMS vendors are members of this group. The ODMG Java binding defines a standard for accessing an object database from Java; this standard is published by the ODMG. See www.odmg.org for more information. PSE Pro is based on the ODMG standard.

Let’s begin exploring Java and object databases by building a simple set of objects for storing data about a hospital. We need to store basic patient information. See Listing 1 for our basic patient object. This object contains the patient’s name, address, birth date, sex, and medical record number (MRN).

public class Patient {
String FirstName, LastName, Address,
City, State, Zip;
int MRN;
OSDate BirthDate;
int Race;
char Sex;
public Patient(String FirstName,String LastName,
String Address,
String City,String State,String Zip, OSDate
BirthDate, int MRN, int Race, char Sex){
this.FirstName = FirstName;
this.LastName = LastName;
this.Address = Address;
this.City = City;
this.State = State;
this.Zip = Zip;
this.MRN = MRN;
this.Race =Race;
this.Sex= Sex;
this.BirthDate = BirthDate;
}
}

Listing 1. Patient object.

Accessing Object Databases From Java

Java’s object persistence capability is defined as “persistence by reachability,” meaning that objects are stored in the object database as they are referenced or linked by a root object. Within our patient object we have a number of primitive types, as well as other objects: OSDate and String. Hence, when we make an instance of the Patient object persistent, the objects contained in the Patient object are also made persistent.

A root object is the base of an object database—it’s the entry point for a database. For our Patient object, we may create a simple root object, which is a collection of Patient objects. Let’s call this root object “Clinic.” When we store this root object Clinic in our database, any Patient objects we’ve added to it will also be stored. An example will quickly elucidate the point. See Listing 2 for a simple Java application that creates our object database, creates a root object, and populates it with two Patient objects.

Import COM.odi.*;
Import OSDate;
Public class loaddb {
public static void main(String argv[]) {
try {
String DBpath ="c:\\odi\\immun01.odb";
ObjectStore.initialize(null, null);
Database db=null;
db = Database.create (DBpath, ObjectStore.ALL_ 
READ | ObjectStore.ALL_WRITE);
// create a set Collection called Clinic
Transaction t = Transaction.begin(ObjectStore. 
UPDATE);
db.createRoot("Clinic", new OSTreeSet(db));
t.commit();
Patient p1 = new Patient("Pratik", "Patel", "CB 213",
"Chapel Hill", "NC", "27599", new OSDate(69,10,1),
16004, 4, M);
Patient p2 = new Patient("Paul", "Jones", "CB 324",
"Chapel Hill", "NC", "27599", new OSDate(55,5,15),
3023, 1, M);
t = Transaction.begin(ObjectStore.UPDATE);
OSTreeSet clinic;
clinic = (OSTreeSet)db.getRoot("Clinic");
clinic.add(p1);
clinic.add(p2);
t.commit();
db.close();
} catch( Exception e ) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}

Listing 2. The loaddb Java application creates our database and populates it.
 

The loaddb application opens a database connection and creates the database. The application then creates a root object, which is a collection class known as ODTreeSet. We’ll talk more about collections later. All data-related database operations must occur within the context of a transaction, as you can see from the listing. We then create two Patient objects, start a transaction, add the two Patient objects to the root clinic object, and commit the transaction. Finally, we have to close the database. This entire process occurs within a try block to catch any exceptions that the database might throw, and we catch any possible exceptions and print an error message.

Processing the Class Files to Gain Persistence

Although it seems as if we’ve done enough to run the application, there is one more step: Run the PSE post processor so the necessary PSE-specific Java code can be added into the compiled Java class files. This post processing adds the low-level Java instructions into the compiled Java class files to store and retrieve Java objects from the database. See the PSE Pro documentation to determine the syntax for running the postprocessor.

Collections

Collections are relatively new data types to Java but not to other programming languages. Collections hold a set of other objects in a specific manner. ODI supplies several collection classes such as OSTreeSet, OSVector, and OSHashSet. The OSTreeSet class we use as the root object to hold our Patient objects is an unordered, no-duplicates, set-based data type. We use it simply to hold all our patient objects. Additionally, you can query and index the OSTreeSet data type.

Java’s 1.2 release will include Javasoft’s own collection types that are very similar to the ones provided by ODI. When OODBMS vendors adopt Java 1.2, they will likely use the Java standard collection types instead of their own. Of course, collections have other uses besides those related to object databases. You can use a collection data type in your Java application to hold data for transient purposes.

Storage Restrictions in an OODB

There are a few caveats when using an object database. The first question you had when you looked at the code for the application was probably “Why are we using this OSDate class instead of the standard Java Date class?” The reason is that dates in Java use native methods for the specific platform the Java program is running on—dates can be platform specific. To circumvent this, most object database vendors supply a “clean,” platform-independent date class that still contains the functionality of the standard Java date class.

Object database engines also can nominally store only primitive data types or objects based on primitive data types. The String object is a good example. Strings in Java are objects built on the primitive char type. You have to be careful to store objects based on primitives; almost all objects are based on primitive data types or can be broken down into primitive types. In this regard, there is not an object database equivalent of a relational binary large object data type. You can’t simply store a big piece of data directly; you can, however, store an array of bytes. This is useful to know if you are trying to store images, for example.

Querying an Object Database

Now that we’ve created our object database, let’s write a small application to query the database and return some results. See Listing 3 for a query application. Again, we open a connection to the database. This time, we must also get the root class (clinic) before we can run the query. We then run the query and iterate through the returned enumeration object for our query results.

import COM.odi.*;
import COM.odi.util.*;
import COM.odi.util.query.*;
import Patient;
Public class querydb {
public static void main(String argv[]) {
try {
ObjectStore.initialize(null, null);
Database db = Database.open("c:\\odi\\immun01. 
odb", ObjectStore.READONLY);
System.out.println("Database opened\n");
// we already should have an open ODI connection
// start a new PSE transaction in read-only mode
Transaction t = Transaction.begin(ObjectStore.
READONLY);
//create a new collection for our clinic query
Collection clinic = (Collection) db.getRoot ("Clinic");
//Query PSE to get the record which matches this MRN
Set records = new Query(Patient.class, 
"MRN==16004").select(clinic);
Iterator iterator = records.iterator();
while (iterator.hasNext()) {
Patient p = (Patient) iterator.next();
System.out.println("The patient’s name with
MRN 16004 is" + p.FirstName);
}
t.commit();
db.close();
} catch( Exception e ) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}

Listing 3. querydb queries the database and prints a result

Explore Your Options

After playing around with the examples here, you can realize the potential of using an object database in your Java application. You will be able to develop database-aware applications quickly, without having to deal with the extra work required to use a relational database. Object databases are quickly maturing and are the perfect answer for storing data in your Java applications. If you have invested heavily in a relational database, you may not have an option for creating your applications using an object database. Still, you can develop new applications that can use an object database while still maintaining the ability to use an existing relational database.


Pratik R. Patel is a researcher in the UNC-Chapel Hill Medical Informatics research program and is developing Web-based systems for healthcare. He is also coauthor of Visual Developer Java Database Programming with JDBC (The Coriolis Group, 1997). You can reach him via email at prpatel@sunsite.unc.edu.
 


 
search - home - archives - contacts - site index
 

Copyright © 1998 Miller Freeman Inc. All Rights Reserved
Redistribution without permission is prohibited.

Questions? Comments? We would love to hear from you!