OrmLite for Android

We have a project coming out soon.  Its the biggest one we’ve worked on, complexity-wise, anyway.  It's an iPhone conversion, which made pretty heavy use of core data. My original Android work was done before there was a phone, and I haven’t really done much on the platform after the G1 came out, so I assumed there would be some form of ORM tool available by now.  Well, when I looked around, there really wasn’t.  This is odd.  The Java community is huge, and there are plenty of ORM tools out there.  Why none for Android?

The first issue is performance.  Imagine using Hibernate on a phone.  Hibernate gets a lot of grief, but I use it for server code, and its a great tool.  Usually when people complain about performance its because they do stupid things.  But that’s on a server or desktop.  On a phone, any full-blown ORM is going to do a lot of extra garbage that you don’t need on a phone.  So, even if you could use one, you wouldn’t want to.  Any ORM tool for the phone has to be really basic.

No JDBC (even though there is).  Every tool that talks to a database in java uses JDBC, but Android doesn’t include a driver for the native Sqlite database, so you’d have to include your own (2+ megs), or use a different database (thanks.  Prefer not to explain to employer why I took a huge risk on their product).

But there IS  a JDBC driver on the phone.  You’re just not supposed to use it.  You never know what’s going to change and suddenly not work.

So, anybody planning on writing an ORM has to write it for a proprietary API, and has to worry that Android 3 will suddenly have a JDBC driver, and the whole thing will be kind of a waste.

There’s sqldroid, which adapts jdbc calls to the sqlite api in Android.  Nice idea.  We tried it.  Its hacky, and doesn’t actually “work”.

The only “real” ORM on Android is Active Android.  I applaud the effort.  However, its feels like a bit too much, and isn’t practical.  As far as I can tell, it tries to handle db management for you, based solely on your object definitions and changes.  OK, except its foolish and doomed to failure in any real schema.  I asked about that before starting the ormlite effort.  I can’t believe anybody would ever use a platform that wouldn’t allow you to update your database schema.  Also, no offense to the AA guys, but $20/license and closed source?  Open source the thing, dominate, and get some contracting gigs instead.  Even the Android source is available.  I hope you do this and make a really great alternative to what we built, but in the meantime…

Enough bashing.  I present ormlite for Android.

I found Gray's post on stackexchange, that his api, ormlite, worked with sqlite and would probably work on Android.  That started a weeks long saga that saw the database calls in the API be abstracted, and both a JDBC and Android version be implemented.

What you have now is a simple ORM tool that works with native Android calls, is open source, free, and includes useful app templates to help you get started.

OrmLite Basics

Using OrmLite is pretty simple.  For each table, create an object to represent the data, and add @DatabaseTable to the class.  For each field, add @DatabaseField.  There are some details in the configuration of both which allow you to do most of the basics in the ORM space, but that’s the basics (find all the tasty details here).

@DatabaseTable

public class ClickGroup implements Serializable

{

@DatabaseField(generatedId = true)

private Integer clickGroupId;

@DatabaseField

private String groupName;

//Yada yada

}

@DatabaseTablepublic class ClickGroup implements Serializable{    @DatabaseField(generatedId = true)    private Integer clickGroupId;    @DatabaseField    private String groupName;
//Yada yada
}

You access data by creating a Dao object, and querying with some pretty standard function calls.

Ehh, its a lot of blab.  Look at the docs, or download and try out the “ClickCount” app.

Connection Management

One of the more frustrating things about Android and Sqlite is that there is little discussion about how you should use it and what to avoid.  It took a lot of searching, trial and error, and actually walking through the code to suss out the details.  Completing that, we’ve cooked up some prototypical classes that you can use to avoid issues when implementing your database access.  All of these are in full force in the ClickCount app, which is available indownload form and directly in the ormlite source on sourceforge.

OrmLiteSqliteOpenHelper - This extends android’s SQLiteOpenHelper, and provides Ormlite specific onCreate and onUpgrade methods.  In this situation, the lazy way to handle updates is also the only way that really makes sense.  See above.  Do updates manually.  You can use ‘AndroidTableUtils.createTable’ to create tables from your ORM object class definitions.

open_helper_classname String Property - Once you create your OpenHelper instance, add the class name under this property in the ‘strings.xml’ resource file.  The app classes will use that to find which class instance to create.  Check out ClickCounter app’s ‘strings.xml’ file.  Don’t think too much about this.  Just do it.

OrmLiteBaseActivity/OrmLiteBaseTabActivity - Essentially the same thing.  Base class to use instead of android’s Activity and TabActivity classes.  These classes manage the db connections so you don’t have to!  You should be able to call ‘getHelper()’ or ‘getConnectionSource()’ without concern for opening/closing connections, db locks, or whatever.  There are two classes because somebody developing Android thought having the different base classes was a great idea.  Now all the code is duped.  Good use forScala’s Traits, methinks.  I still have some learning to do before I write production code in Scala, though.

OrmLiteBaseService - Same thing as the Activity classes, but for Services.  Boldly read/write to your db long after the user closes your app.  Go nuts *.  It’ll take it.

AndroidTableUtils - Static helpers to create and drop tables from the class definitions.  Best to use during dev and initial db creation.  They will be no help updating.  Again, see above about why.

AndroidSqliteManager - You should rarely (as in never) call this class directly.  It manages a single OpenHelper instance by way of reference counting, to prevent database locks and potentially lost updates.  If you have some exotic things going on, or want to use more than one db in an app, you may need to interact with this class.

* Don’t go nuts.

Tips for you and yours

While implementing the ormlite stuff on Android, and using android db access in general, I’ve learned some things.

- When updating more than one object, use a transaction.  In ormlite, see TransactionManager.callInTransaction.  there are HUGE performance benefits to using sqlite transactions on the phone.

- I was shocked, but even basic db ops can take a significant amount of time.  This flies in the face of common knowledge in most server/desktop apps.  Ideally, EVERYTHING should be in a worker thread of some type, but at least for bigger queries and updates, spawn a worker thread.  I actually put big updates out into a local Service instance.

I guess that’s it for tips?  I’m a wealth of knowledge.  Its late, though.  I only write blog posts when I’m too tired to actually work.  Its 12:38AM on a Friday night.  Lame.  K out.

OH YEAH!

What’s Wrong with OrmLite (or, “Yeah, we know”)

When you reference associated objects, you MUST remember to refresh them manually.  If you’re used to a big ORM, this will be a let down.  Yeah, we know.  This way, there’s no central store, no object instrumentation, etc.  You’re also not getting huge object graphs that you didn’t intend to.  Just the basics.  A little extra work, a little extra code, but much simpler from an implementation perspective, and (arguably) better from a performance perspective.

Again, short on the “what’s wrong”.  Maybe I’ll add more later.  Basically, you could list most of the features of a full-blown ORM here and complain about them missing, but it is a pretty simple API.  Its meant to shuttle data into and out of your objects.  If you want anything else, hey, there’s the source

K out, again.