Select Page

Using Db4o in an Android Application

Damasia Maneiro
Published: June 13, 2022

Db4o is an object database, i.e., forget about the 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 at any level of complexity in your hierarchy. You’re not limited to flat objects with primitive types to get reasonable performance.

With db4o you can also benefit from native queries which bring 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, and no complex installation. For a Java project using Eclipse, you just drop the jar file in the “lib” folder and add the library to the build path. According to your needs, you must choose the db4o-xxx-yyy.jar file to be included. If “xxx” is “all,” you get all the functionality of db4o. If it’s “core,” you get the very minimum. Regarding “yyy” depends on what version of Java you need to support (e.g., 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 (e.g., 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) + "https://dzone.com/" + "pumpup.db4o";
    } /**       * Closes the database       */
    public void close() {
        if (oc != null) oc.close();
    }
}
}

Next, we can create a Provider for each of our classes where we can implement the associated queries (e.g., ExerciseProvider.java to handle persistence of Exercises). We can make it extend Db4o Helper 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); 
delete(Exercise exercise) { 
db().delete(exercise);
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 db4o Helper 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;              }}

Using db4o on Android is a nice option if you’re not forced to work with Content Providers, which are only 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: it creates no headaches, it saves a lot of time, and is simple and straightforward.

Source: dzone.com