Android Analyse

Filter Search

Only this category...

greenDAO – An Android ORM for SQLite

Written by Jeremy D on November 25 2012 @ 5:42 am | 1 comment

1
greendao

Recently I evaluated an Android Object Relational Mapping (ORM) called greenDAO which simplifies your Android development by generating your Data Access Object (DAO) layer and your Domain Objects based on a simple Java schema you define.

Use of an ORM also supports the Domain Model Pattern which:

  • Improves software quality and maintainability.
  • Is fundamental to the Domain Driven Design approach.

The Tutorial

Lets walk through getting the greenDAO tutorial up and running and I shall explain as we go:

  1. Download the greenDAO zip file.
  2. Extract the zip and copy DaoExample and DaoExampleGenerator folders into your Eclipse workspace folder.
  3. Import them as existing projects into your workspace from within Eclipse.
  4. If you browse to ExampleDaoGenerator within the IDE you will observe this is the example file which defines the schema (Generated into your DAO and Domain Object Java code when run).
  5. The main method constructs a Schema object and defines where the generated source will be deployed.
public static void main(String[] args) throws Exception {
        // Defines the Schema object and the package it will be exported to        
        Schema schema = new Schema(3, "de.greenrobot.daoexample");
        // Call the addNote method which appends the Note definition to the schema
        addNote(schema);
        // Call the addCustomerOrder method which adds the customer order and associated table definitions
        addCustomerOrder(schema);
        // Generate the DAO and domain objects based on the schema to the target location
        new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
    }

The addNote and addCustomerOrder methods further refine the schema by defining some domain objects and their relationships. The definition of the schema is where your domain modelling is realized.

NB: Ideally you will have completed a domain design and modelling process using UML which can now be realised via greenDAO schema definition.

private static void addNote(Schema schema) {
        Entity note = schema.addEntity("Note");
        note.addIdProperty(); 
        note.addStringProperty("text").notNull(); 
        note.addStringProperty("comment"); 
        note.addDateProperty("date"); 
}

private static void addCustomerOrder(Schema schema) {
        Entity customer = schema.addEntity("Customer"); 
        customer.addIdProperty(); 
        customer.addStringProperty("name").notNull();

        Entity order = schema.addEntity("Order"); 
        order.setTableName("ORDERS"); // "ORDER" is a reserved keyword 
        order.addIdProperty();

        Property orderDate = order.addDateProperty("date").getProperty(); 
        Property customerId = order.addLongProperty("customerId").notNull().getProperty(); 
        order.addToOne(customer, customerId);
        ToMany customerToOrders = customer.addToMany(order, customerId); 
        customerToOrders.setName("orders"); 
        customerToOrders.orderAsc(orderDate); 
}

Review the code in the ExampleDaoGenerator until you feel you understand the role of this class and the schema definition.

When you wish to generate your DAO and Domain Objects Run ExampleDaoGenerator as a Java Application via Eclipse.

Now that you have generated your DAO and Domain Objects, browse to DaoExample\src-gen\de\greenrobot\daoexample to review the generated source.

Browse to DaoExample\src\de\greenrobot\daoexample\NoteActivity.java. This is the Android Activity which will be shown when your application is run. Take some time to look at the code in this class and you will identify the wiring for the UI elements which leverage the Database via greenDAO to persist the notes.

If your Eclipse is correctly configured you will be able to right click on your DaoExample project and select Run as > Android Application. I recommend playing with the application either on a connected device or using the emulator. You should add a few notes and verify they are persisted and loaded correctly.

As you can see the greenDAO tutorial gives you a pretty good understanding of the steps required to implement the schema and generate your DAO and Domain Objects. The team from greenDAO deserve recognition for how easy to use they have made this ORM and how well documented it is.

How do I use the DAO for CRUD operations?

The first step to accessing the DAO and the associated CreateReadUpdateDelete(CRUD) operations is to construct an SQLiteOpenHelper. Typically you will use the generated DevOpenHelper for development and your own custom written OpenHelper for production. Your OpenHelper will handle applying schema updates. I am currently in the process of writing a blog post on performing a schema update and data-migration with greenDAO, so stay tuned.

// As we are in development we will use the DevOpenHelper which drops the database on a schema update
DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null); 
// Access the database using the helper 
SQLiteDatabase db = helper.getWritableDatabase(); 
// Construct the DaoMaster which brokers DAOs for the Domain Objects
DaoMaster daoMaster = new DaoMaster(db); 
// Create the session which is a container for the DAO layer and has a cache which will return handles to the same object across multiple queries
daoSession = daoMaster.newSession(); 
// Access the Notes DAO
NoteDao noteDao = daoSession.getNoteDao();

Now that we have the DAO reference we can perform CRUD operations for our domain objects.

// [C]reate
Note note = new Note(); 
noteDao.insert(note); 
System.out.println("Inserted: " + note.getId()); 
// [R]ead
noteDao.load(1); 
noteDao.loadAll(); 
// [U]pdate 
note.setComment("This is a new comment"); 
noteDao.update(note); 
// [D]elete 
noteDao.delete(note); 
noteDao.deleteAll();

What are the transaction options available and why do I need them?

It is important once you start using the ORM commercially that you understand the implications of transactions. Sometimes you wish to perform a chunk of work as a single atomic block, grouping a number of actions together so that they either succeed (and are committed) or fail (and are rolled back) together. Transactions allow the Database to ensure referential integrity is maintained given a sometimes chaotic operating environment.

greenDAO uses transactions under the hood for every call (e.g. insert or delete) on a DAO, however it also exposes abstractions to allow you to manage the transactions. Without getting into too much detail, here are some situations in which you would take control of the transactions:

  • If you need to commit a change which occurs across multiple tables then a transaction can be used to ensures they occur according to the ACID principles
  • If you have a large number of operations and you wish to perform them efficiently, then you should explicitly group them into a single transaction. This will free greenDAO from the transaction overhead of a transaction per call (making it significantly faster to execute them).
daoSession.runInTx(new Runnable() {
    public void run() {
        // Everything in run will be executed in a single transaction.
        ....
    }
});

QueryBuilder and querying your data

The QueryBuilder lets you create powerful queries without having to write raw SQL. The QueryBuilder is a fluent interface, which makes your code very easy to read and maintain. QueryBuilder also ensures compile time checking (as opposed to SQL which will fail at runtime as it is an String).

// The following code will query the DAO for all notes which were added today. 
List<Note> notes = noteDao.queryBuilder().where(Properties.Date.eq(today)).orderAsc(Properties.Date).list();

It is also possible to limit the queries effectively allowing you to determine a min/max value

// The following code will query only the most expensive price 
List<Price> expensive = daoSession.getPriceDao().queryBuilder().orderDesc(Properties.Amount).limit(1).list();

Customising your Domain Objects (e.g. adding helper methods/constructors)

By enabling keep mode in your schema definition you can add custom code to your generated domain objects and it will not be overwritten upon re-generation.

// Enable keep sections on the schema 
schema.enableKeepSectionsByDefault();

Browse to the domain objects you wish to add behaviour to. The abstraction supports three kinds of keep sections; fields, methods and imports. Below are some contrived examples which demonstrate what it may look like if you used these keep sections in a Domain Object.

// KEEP INCLUDES - put your custom includes here 
import android.text.format.Time; 
// KEEP INCLUDES END

...

// KEEP FIELDS - put your custom fields here
/** Number of milliseconds in a fortnight */ 
public static final long FORTNIGHT = 1209600000; 
// KEEP FIELDS END</p>

...

// KEEP METHODS - put your custom methods here 
/** 
 * @return boolean indicating if this session was recently downloaded. 
 */
public boolean isNew() {
    Time now = new Time(); 
    now.setToNow(); 
    return((now.toMillis(true) - downloadDate) &lt; FORTNIGHT); 
} 
// KEEP METHODS END

Upgrading your schema and migrating data?

At a high level you simply provide your own hand written class which extends DaoMaster.OpenHelper. The SchemaUpgradeOpenHelper you provide will override the onUpdate method which will check the current version and upgrade the database to the latest schema and migrate the data.

NB: Another post will be coming soon which will address in more detail and with examples how to perform this schema update.

Where can I find help?

greenDAO uses Stack Overflow for support, if you have any questions which are not answered by the documentation then SO is your best bet

My final comments

greenDAO appears to be an excellent tool for rapid development and for encouraging developers to adhere to good domain modelling practices. The merits of ORMs for large or complicated systems are still hotly debated. Ultimately framework decisions need to be made on a case by case basis.

I believe greenDAO saves me time and simplifies my development, this is why I use and advocate it for Android development. What are you waiting for? Give greenDAO a go today!

Jeremy D
Jeremy D
Google+

Jeremy has more than 8 years professional Java experience. Jeremy is a big Android fan and highly values the platform openness, ease of integration and flexibility. Jeremy is currently using a Samsung Galaxy S2. In his spare time he is working on multiple Android applications, which will be available soon!

One Comment

  1. 102 Rodney

    Excellent article. Thanks very much.

Your Response...

Start of page