Embedding the db4o Object-Oriented Database

How to get started using this small-footprint object-oriented database in your embedded system programs.

db4o is an open-source, object-oriented database from db4objects. It is embeddable, in the sense that the entire db4o engine is supplied as a single library that links into your application. Versions of db4o exist for Java and .NET/Mono. Consequently, it's an ideal OODBMs engine for Linux applications written in either the Java or .NET frameworks. In this article, the examples provided have been written in C# and tested in Mono running on an Ubuntu Linux system. (We also ran the applications on a Monoppix system.)

Besides being an open-source library—so you can download it instantly and begin experimenting with its capabilities—db4o's other outstanding characteristic is its terse, easily grasped API. In most cases, you'll use methods drawn from a set of nine fundamental calls. In addition, the library's memory footprint is modest, making it ideal for resource-constrained applications (though by no means is db4o incapable of enterprise-level work).

Despite its small footprint and uncomplicated programming interface, db4o provides all the features you'd expect from a commercial database engine: it allows multiuser access, any access on the database is invisibly wrapped in a transaction and all operations adhere to ACID principles (atomicity, consistency, isolation and durability).

Unlike some object-oriented and object-relational database systems, db4o does not require you to pass your code through an instrumentation pre- or post-compilation step. Nor must classes whose objects are to be made persistent be derived from a special persistence-aware superclass. db4o is happy to work with ordinary objects, and you need not inform it of an object's structure before you store that object into a db4o database.

As we hope to show, this provides us with some unexpected capabilities.

A Dictionary Database

Suppose our application is a dictionary—a dictionary in the classic sense. That is, the application manipulates a database that stores words and their definitions. In such an application, we might define a class to model dictionary entries as follows:


/*
 * DictEntry
 */

using System;
using System.Collections;

namespace PersistentTrees
{
	/// <summary>
	/// DictEntry class
	/// A dictionary entry
	/// </summary>
	public class DictEntry
	{
		private string theWord;
		private string pronunciation;
		private ArrayList definitions;

		public DictEntry()
		{
		}

		// Create a new Dictionary Entry
		public DictEntry(string _theWord,
		                string _pronunciation)
		{	theWord = _theWord;
			pronunciation = _pronunciation;
			definitions = new ArrayList();
		}

		// Add a definition to this entry
		// Note that we do not check for duplicates
		public void add(Defn _definition)
		{
			definitions.Add(_definition);
		}

		// Retrieve the number of definitions
		public int numberOfDefs()
		{
			return definitions.Count;
		}

		// Clear the definitions array
		public void clearDefs()
		{
			definitions.Clear();
			definitions.TrimToSize();
		}

		// Properties
		public string TheWord
		{
			get { return theWord; }
			set { theWord = value; }
		}
		public string Pronunciation
		{
			get { return pronunciation; }
			set { pronunciation = value; }
		}

		// Get reference to the definitions
		public ArrayList getDefinitions()
		{
			return definitions;
		}
	}
 }

A DictEntry object consists of three elements: the word itself, its pronunciation and a list of definitions. Meanwhile, a class for describing definition objects might look like this:


/*
 * Defn
 *
 */
using System;
namespace PersistentTrees
{
	/// <summary>
	/// Description of Class1.
	/// </summary>
	public class Defn
	{
		public static int NOUN = 1;
		public static int PRONOUN = 2;
		public static int VERB = 3;
		public static int ADJECTIVE = 4;
		public static int ADVERB = 5;
		public static int CONJUNCTION = 6;
		public static int PARTICIPLE = 7;
		public static int GERUND = 8;

		private int pos;
		private string definition;

		public Defn(int _pos,
		           string _definition)
		{
			pos = _pos;
			definition = _definition;
		}

		// Properties
		public int POS
		{
			get { return pos; }
			set { pos = value; }
		}
		public string Definition
		{
			get { return definition; }
			set { definition = value; }
		}
	}
}

So, a Defn object includes an integer member indicating the part of speech and a string member that holds the text for the definition. This structure allows us to associate multiple definitions with a single entry in the dictionary.

Storing such items into a db4o database is marvelously simple. Assume that we want to add the word float to our dictionary and provide it with three definitions:

Defn _float1 = new Defn(VERB, "To stay on top of a liquid.");
Defn _float2 = new Defn(VERB, "To cause to float.");
Defn _float3 = new Defn(NOUN, "Anything that stays on top of water.");

DictEntry _float = new DictEntry("float", "flote");
_float.add(_float1);
_float.add(_float2);
_float.add(_float3);

At this point, we have a DictEntry object, _float, whose list of definitions includes three items.

First, we open the database itself. A db4o database is modeled by an ObjectContainer object, and we can open (or create, if it doesn't exist) an ObjectContainer with:


ObjectCointainer db = Db4o.openFile("<filename>");

______________________

Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Webcast
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
On Demand
Moderated by Linux Journal Contributor Mike Diehl

Sign up now

Sponsored by Skybot