Welcome!

Java Authors: Maureen O'Gara, Liz McMillan, Walter H. Pinson, III, Yakov Werde, Tony Bishop

Related Topics: Java

Java: Article

Evaluating Options for Persisting Java Objects

Hibernate, DB4O, and Caché Database with Jalapeño

DB4O
DB4O provides three different ways to retrieve your objects: Query By Example, Native Queries, and SODA Queries. Each has its pros and cons.

The simplest and most limited is QBE. With this method, you create a prototype of the object you're looking for using one of the object's constructors, and DB4O returns the matching records.

// QBE Example - Retrieve Person By Name
Person proto=new Person("Ben","Franklin",0);
ObjectSet result=db.get(proto);
listResult(result);

Native Queries are the preferred query method and are typesafe, compile-time checked, and refactorable.

Caché
Cache provides an object oriented query mechanism that uses SQL forselection and which returns an iterator you can use to traverse the returned objects. You also have the option of using JDBC and SQL to perform complex queries over multiple related objects (SQL JOINS) or VIEWS. The results of these complex queries can also be accessed as objects, as long as the Object ID is returned as part of the query.

import com.intersys.pojo.ApplicationContext;
import com.intersys.pojo.ObjectManager;

try {
    ObjectManager objectManager;
String url="jdbc:Caché ://localhost:1972/" + namespace;
    objectManager = ApplicationContext.createObjectManager (url, username, password);

    String sql = "Name %startsWith ?"; // Search for people by name
    if ("null".equalsIgnoreCase (query)){query = null;
}
    String[] qargs = {query};
    Iterator people = objectManager.openByQuery (Person.class, sql, qargs);
    while (people.hasNext()){IPerson person = (Person) people.next();
       System.out.print ("Name: " + person.getName() );
   }
    objectManager.close ();
} catch (Exception ex) {
    System.out.println( "Caught exception: " + ex.getClass().getName() + ": " + ex.getMessage() );
    ex.printStackTrace();
}

Controlling Object Depth
One of the challenges of storing objects is to control how many objects are stored and retrieved at one time. For example, consider a company that contains 100 departments and each department contains 25 to 50 employees. Using Java Serialization, serializing the Company object would also persist all the Department and Employee objects - and instantiating the Company would also instantiate the related Department and Employee objects. If all you need to persist is the Company Object, you've done a lot of unnecessary work! There's considerable impact on performance and memory requirements for every object instantiated. Furthermore, if you send this object over the network, you want to be as efficient as possible - and therefore only send the Company Object.

What's needed is a mechanism for controlling how deeply you traverse the object tree when instantiating objects.

Hibernate
Hibernate handles this well because it's based on a relational database structure. It is easy to control the depth of the data (or the depth of the objects) returned by specifying LAZY or EAGER loading and if you switch to JDBC, you have total control using SQL JOIN statements.

When you specify LAZY loading, the POJO is actually replaced with a proxy object that will load properties and collections via the Hibernate session as needed.

DB4O
DB4O provides excellent control over object depth. You can easily specify exactly how many levels you want to retrieve or update. You can also turn on cascading updates/deletion - which traverses the entire object graph:

Db4o.configure().objectClass(Car.class).cascadeOnUpdate(true);

Or you can specify the activation depth when selecting/updating/deleting:

SensorReadout readout=car.getHistory();
while(readout!=null) {
db.activate(readout,2); // Activate the next 2 object levels!!!
System.out.println(readout);
readout=readout.getNext();
}

Thus you can specify: "Get the next three levels only" if desired or "Get everything!"

CAUTION: DB4O doesn't enforce referential integrity, so be very careful when deleting with cascade delete enabled. You can delete objects that are still pointed to by other objects in the database.

Caché
Caché provides good control over object depth as well. You can specify FetchType = Eager or Lazy like Hibernate. Calling the "detach(Object)" method ensures that all data in the given object (including all objects reachable from it by following references) can be accessed without a connection to the database.

Once again, if you switch to JDBC/SQL, you have total control over object depth via SQL JOIN statements, but can still open the objects referenced in the resultset.


More Stories By Richard Conway

Richard Conway is a software developer and technology consultant with more than 15 years of technology, project management, and information services experience. He has extensive experience developing Java/Struts-based web applications. He started focusing more on Swing based developments at the beginning of 2005 and has just finished a Swing-based client/server asset management project. He lives in Miami with his wife Patricia, is currently working on an EMR application, and plays sand volleyball in his spare time.

Comments (2) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


Most Recent Comments
Stefan Edlich 05/24/07 05:38:44 PM EDT

Hi,
your article is very well done. However one point:
>DB4O doesn't provide any support for constraints.
The is only partially true.
It's more then easy to implement this in just a few simple lines using db4o callbacks.

Best
Stefan Edlich
(Author of "The Defintive Guide to db4o" Apress)

Stefan Edlich 05/24/07 05:38:33 PM EDT

Hi,
your article is very well done. However one point:
>DB4O doesn't provide any support for constraints.
The is only partially true.
It's more then easy to implement this in just a few simple lines using db4o callbacks.

Best
Stefan Edlich
(Author of "The Defintive Guide to db4o" Apress)