greenDAO is an ORM (object relational mapping) library that uses code generation to provide a higher level API for SQLite databases on Android. It generates Java classes from an entity model that allows reading and writing objects to the database instead of using raw SQL. This improves productivity by handling common database tasks like queries and transactions. The generated code avoids reflection for better performance compared to annotation-based ORMs. The library focuses on optimization through techniques like custom cursors, entity caching, and bulk operations to achieve high performance suitable for Android.
1. A look behind the scenes
greenDAO
Droidcon Berlin 2012,
Markus Junginger
2. About me, Follow me
Android developer since 2007
Founder of greenrobot.de, Munich
@green_dao Most updates
@greenrobot_de
Most important updates
+Markus Junginger
+greenrobot
3. Agenda
What is greenDAO?
– SQLite database
– ORM
– Code generation based on meta model
Background info and „secret“ internals
– Why code generation?
– Performance Tweaks
4. Problem with DB Development
Database world || Java world
No object orientation
Data access feels quite low levely
A lot of boilerplate code for SQLite
– SQL scripts, e.g.: CREATE TABLE, Queries
– Cursor iterations
– Parameter binding
5. Common solution: ORM
Java Object
SQLite
greenDAO Java Object
Database
Java Object
ORM offers a higher level API
– Read and write objects
– CREATE TABLE done for you
– Expressing Queries
9. Code Generation: Meta Model
In generator project
Defines data model
(your schema)
Define with Java
10. Example: Model for Generator
Schema schema = new Schema(1,
"de.greenrobot.daoexample");
Entity simple = schema.addEntity("Note");
simple.addIdProperty();
simple.addStringProperty("text").notNull();
simple.addDateProperty("date");
new DaoGenerator().generateAll(
"../DaoExample/src-gen", schema);
11. Example: Generated Entity
public class Note {
private String text;
// ID, date and constructors skipped
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
12. Code: Insert, Update, Delete
Note note = new Note();
note.setText(“Say hello to world”);
noteDao.insert(note);
Log.d("Dao", “New ID: " + note.getId());
note.setText(“Save the world”);
noteDao.update(note);
noteDao.delete(note);
13. QueryBuilder
References generated Properties
Java Complier checks
Example: Get all users with first name
“Joe“, and sort by last name
List<User> joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
14. Entity relations
Entity type relates to another entity type
Supports to-one and to-many relations
Unidirectional
Bidirectional: requires manual updates
15. ToOne Example
Entities Customer & Order
An order has one customer
Modelling in the generator project
Property customerId = order.addLongProperty(
"customerId").notNull().getProperty();
order.addToOne(customer, customerId);
Resolving in the app
Customer customer = order.getCostumer();
16. ToMany Example
Entities Customer & Order
A customer places many orders
Modelling in the generator project
Property customerId = order.addLongProperty(
"customerId").notNull().getProperty();
customer.addToMany(order, customerId);
Resolving in the app
List<Order> orders = costumer.getOrderList();
18. greenDAO Design Goals
Maximum Performance
Low resource usage
– Memory consumption
– Library size
Easy-to-use API
Focus on the essentials
Optimized for Android
19. Save size, keep it the DRY way
Generate code, but as sparly as possible
Example: load method of DAO
AbstractDao class (core library)
– Implements everything expect readEntity
Generated DAO implements readEntity
– Just construct entities from a cursor position
Library size: 59 KByte + some K per DAO
20. 3 Basic Performance Rules
1. Group DB changes into a transaction!
Can be like 500 times faster; still a FAQ
2. Don’t forget database indexes
3. Use prepared statements (precompiled)
21. Regular Performance Tracking
Different scenarios are tested
Tracked in Excel files
Excel files are pushed to github
22. Why Code Generation?
Annotation-based solutions: common with
JEE ORMs (Hibernate, JPA)
Parsing of annotations start-up time
Android & annotations:
getting/setting values requires reflection
Reflection quite slow on Android (n. slide)
Code generation to avoid reflection
23. Reflection Performance
Method Reflection (roughly)
getInt ~ 50 x slower
getString ~ 50 x slower
setInt ~ 400 x slower
setString ~ 150 x slower
Example: 100,000 Operations
(e.g. 10,000 entities with 10 properties)
setInt: 9 ms, reflected 3875ms
24. Profiling to find hotspots
Use traceview
Enable in code:
Debug.
startMethodTracing(
traceName);
See class
PerformanceTest
25. Reading entities & Constructor
Entities read from the database
Solution 1: Calling setters
MyEntity myEntity = new MyEntity();
myEntity.setX(cursor.getString(0));
…
Solution 2: Constructor only
MyEntity myEntity = new MyEntity(
cursor.getString(0), …);
Performance gain: 33%
26. Optimization Candidate: Cursor
Quite some time is spent in Android API
android.database.AbstractWindowedCursor
get… Methods are “slow”
@Override
public short getShort(int columnIndex) {
checkPosition();
return mWindow.getShort(mPos, columnIndex);
}
@Override
public int getInt(int columnIndex) {
checkPosition();
return mWindow.getInt(mPos, columnIndex);
}
28. Lookup by ID
Identity Scope (≈ Entity Caching)
Mapping ID Entity
HashMap<Long, MyEntity>
Problem: Long object creation
LongSparseArray<MyEntity>
Problem: does not scale
Evaluated several alternatives
29. LongHashMap & More
Custom de.greenrobot.dao.LongHashMap
+ Locking improvements
+ Minor performance tweaks
Performance gain: from 30% up to 117%
32. Current Workflow vs. Migration
Works best if you start from scratch
(Start with Entity modeling)
Migration: additional effort required
– Pre-existing entities: have to be replaced
– Existing tables: entities have to modeled
Ideas how to address migration
– Generic DAO (Annotation based entities!)
– Import existing Model from SQLite DB files
33. Current Feature Requests
Generate Adapters, CRUD Apps,
Parceable, conversion to JSON/XML, …
Convenience support for async ops
Client/Server(Cloud) data synchronization
More flexible primary keys (PKs)
Pre- and post persist callbacks
What is most important to you?