Senior Java and Android Developer Damasia has posted 1 posts at DZone. View Full User Profile

Using db4o in an Android application

06.23.2010
| 19755 views |
  • submit to reddit

db4o is an object database, ie. forget about mapping of tables in a relational model. If you're a developer that translates into savings in time invested in your application and volume of code. db4o's great potential is that you can reuse your (plain, non-mapped) objects by saving and retrieving them as many times as you want. You can persist complex objects with nested collections or other complex objects, any level of complexity in your hierarchy. You're not limited to flat objects with primitive types to get a reasonable performance.

With db4o you can also benefit from Native Queries which brings you closer to the language and combine optimized execution with simplicity even for complex queries. db4o is open source and can be downloaded here.

In order to use db4o in your application you can simply reference a single jar file in your project and that's it (no setup, no server, no complex installation). For a java project using Eclipse you just drop the jar file in the "lib" folder and then add the library to the build path. According to your needs you must choose the db4o-xxx-yyy.jar file to include. If "xxx" is "all" you get all the functionality of db4o. If it's "core" you get the very minimum. With regards to "yyy" depends on what version of Java you need to support (eg. db4o-xx-core-java5.jar targets Java JDK 5 and JDK 6)

How to use db4o in Android

I really enjoy working with db4o on Android. I usually start by creating a central class (eg. Db4oHelper) that handles the db4o API and controls when to create, open and close the database.

public class Db4oHelper {

private static ObjectContainer oc = null;
private Context context;

/**
* @param ctx
*/

public Db4oHelper(Context ctx) {
context = ctx;
}

/**
* Create, open and close the database
*/
public ObjectContainer db() {

try {
if (oc == null || oc.ext().isClosed()) {
oc = Db4oEmbedded.openFile(dbConfig(), db4oDBFullPath(context));
//We first load the initial data from the database
ExercisesLoader.load(context, oc);
}

return oc;

} catch (Exception ie) {
Log.e(Db4oHelper.class.getName(), ie.toString());
return null;
}
}


/**
* Configure the behavior of the database
*/

private EmbeddedConfiguration dbConfig() throws IOException {
EmbeddedConfiguration configuration = Db4oEmbedded.newConfiguration();
configuration.common().objectClass(Exercise.class).objectField("name").indexed(true);
configuration.common().objectClass(Exercise.class).cascadeOnUpdate(true);
configuration.common().objectClass(Exercise.class).cascadeOnActivate(true);
return configuration;
}

/**
* Returns the path for the database location
*/

private String db4oDBFullPath(Context ctx) {
return ctx.getDir("data", 0) + "/" + "pumpup.db4o";
}

/**
* Closes the database
*/

public void close() {
if (oc != null)
oc.close();
}
}



}

Then we can create a Provider for each of our classes where we can implement the associated queries (eg. ExerciseProvider.java to handle persistence of Exercises). We can make it extend Db4oHelper to get all the maintenance methods (open, close, etc).

public class ExerciseProvider extends Db4oHelper {

public final static String TAG = "ExerciseProvider";
private static ExerciseProvider provider = null;

public ExerciseProvider(Context ctx) {
super(ctx);
}

public static ExerciseProvider getInstance(Context ctx) {
if (provider == null)
provider = new ExerciseProvider(ctx);
return provider;
}

public void store(Exercise exercise) {
db().store(exercise);
}

public void delete(Exercise exercise) {
db().delete(exercise);
}

public List findAll() {
return db().query(Exercise.class);
}

}

It's really important not to forget to close the database before exiting the application, otherwise your changes won't be committed. A nice way to implement this in Android is in the Launcher activity (main activity for the application) where we'll create an instance of Db4oHelper and invoke close() upon exit.

public class main extends Activity {             

private Db4oHelper db4oHelper = null;

@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
dbHelper();
}

/**
* Create Db4oHelper instance
*/

private Db4oHelper dbHelper() {
if (db4oHelper == null) {
db4oHelper = new Db4oHelper(this);
db4oHelper.db();
}
return db4oHelper;
}

/**
* Close database before exiting the application
*/



@Override
protected void onPause() {
super.onDestroy();
dbHelper().close();
db4oHelper = null;
}

}

Bottom line

Using db4o on Android is a really nice option if you're not forced to work with ContentProviders (which are only really necessary if you must share data with other external applications and are too coupled to Android's SQLite). For handling all persistence aspects of a single application db4o is a pleasure to work with (no headaches, saved a lot of time, simple and straight-forward!)

Published at DZone with permission of its author, Damasia Maneiro.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Lucas Godoy replied on Wed, 2010/06/23 - 9:37am

I have the idea that this kind of approach is slower than SQLite. Is it true?

Good article.

Eric Galluzzo replied on Wed, 2010/06/23 - 10:01am

Your Provider class seems like a DAO.  You might consider using a generified DAO to save yourself some boilerplate code, along the lines of the following.  We did this recently on a JPA project and it helped greatly.

public class DbProvider<T extends Serializable> extends Db4oHelper {
public Class<T> persistentClass;

public DbProvider( Class<T> persistentClass, Context ctx ) {
super( ctx );
this.persistentClass = persistentClass;
}

public void store( T obj ) {
db().store( obj );
}

public void delete( T obj ) {
db().delete( obj );
}

public List<T> findAll() {
return db().query( persistentClass );
}
}

public class ExerciseProvider extends DbProvider<Exercise> {
public ExerciseProvider( Context ctx ) {
super( Exercise.class, ctx );
}

// Exercise-specific methods here
}

Even better, you might consider using interfaces so that you can plug in whatever persistence provider (Db4o, SQLite, ...) you want.  This might be overkill for an Android app, though.

German Viscuso replied on Wed, 2010/06/23 - 10:26am in response to: Lucas Godoy

Hi Lucas. I believe it's the other way round, first the mapping (table <-> object) process takes time and second db4o uses b-tree indexes for fast access. I can verify this on a simple benchmark that compares db4o vs SQLite where db4o is faster (taken from a benchmark published by the guys that provide Perst). If you want to actually try the benchmark please contact me privately and I'll send it to you.

Moreover the simplicity and time saved are pretty obvious here: http://developer.db4o.com/Projects/html/projectspaces/android_password_manager.html (see the code comparisons, the video sucks)

Best!

German Viscuso replied on Wed, 2010/06/23 - 10:23am in response to: Eric Galluzzo

Hi Eric. Nice use of generics, I believe it quite works to simplify the example. But I agree that using interfaces so that you can plug in whatever persistence provider you want might be overkill for Android (can't really say until we see code).

Best.

Jan Kotek replied on Thu, 2010/06/24 - 6:03am

 Checkout JDBM2 http://jdbm2.googlecode.com. It is under Apache2 license and JAR file have only 130KB

 

German Viscuso replied on Fri, 2010/06/25 - 10:41am in response to: Jan Kotek

Jan: nice project but it's a key/value store not an object database. In a key value store you're forced into an abstraction introduced by the persistence mechanism (eg. working with a hashmap). That's something you don't have to do with an oodb, if you were working with collections, you just keep using them transparently except that you make them them persistent (in db4o for example you have "transparent persistence") and you keep all your object references while at it. IMHO oodbs are closer to the language (feel more integrated with it and natural)

Damasia Maneiro replied on Fri, 2010/06/25 - 1:25pm in response to: Eric Galluzzo

Hi Eric, I will use that in my project. Thanks!

Stuart Merrell replied on Fri, 2010/07/02 - 3:30pm

Hi, Very good... and timely article. I am a developer looking for better ways (than SQLite) of working with persistent data. I was looking for a topic to present for an Android How-To v-meet. I'm still planning it out but I want to utilize the concepts presented here to create a demo on "Mobile Reporting with Android". Looks like I need to stay tuned into Dzone for the latest and greatest mobile development concepts and patterns. Noticed there was only one parenthetical mention of SQLite... was that on purpose? Did google just miss the whole Java OO Persistence Pattern with their implementation?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.