Project stORM:
an ORM for SQLite
+David Chandler
(ex) Android Developer Advocate
http://turbomanage.com
simple
template-based
Object
Relational
Mapping
David Chandler
turbomanage.wordpress.com
1.0
why
hand-coded SQL, ugh
why
SQLite already has obj-like wrappers
- ContentValues (insert, update)
- Cursor (query)
many apps just require a place to stuff
some objects
existing ORMs use reflection or require
up-front modeling
goals
easy
convention over configuration
annotation-driven
- @Database, @Entity
- seamless code gen with JDT
easy to debug
minimal performance overhead
non-goals
kitchen sink
model all relations
absolute max performance
setup (Eclipse / ADT)
add storm-api.jar to libs/
add storm-impl.jar to annotation factory
classpath
setup (Android Studio)
github.com/turbomanage/storm-gen
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.13.+'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
}
}
apply plugin: 'android-apt'
dependencies {
apt ‘com.turbomanage.storm:storm-impl:1.0'
compile 'com.android.support:appcompat-v7:19.1.0'
compile 'log4j:log4j:1.2.17'
compile 'javax.persistence:persistence-api:1.0'
compile ‘com.turbomanage.storm:storm-api:1.0'
}
use
Extend DatabaseHelper, annotate with
@Database
Create POJOs, annotate with @Entity
Generates
- DbFactory
- EntityTable
- EntityDao
new EntityDao(ctx).insert/get/query...
use (like Objectify)
dao.insert(T obj)
dao.insertMany(Iterable<T> objs)
T dao.get(long id)
dao.update(T obj)
dao.delete(long id) / dao.deleteAll()
List<T> dao.listAll() or load().list()
dao.listAllByExample(T exampleObj)
dao.load().eq(COL, val).eq(...).exec()
conventions
generated package names
- +.db, +.dao
COLNAME ==
fieldName.toUpperCase()
transient fields are not persisted
id
- long id (default)
- or annotate another field with @Id
- column name is _id (for CursorAdapter)
supported types
all primitives & wrappers
- boolean, byte, byte[], char, double, enum,
float, int, long, short, String
- byte[] have affinity BLOB
- boolean, byte, char have affinity INTEGER
roll-your-own
- extend TypeConverter<J,S>
- annotate with @Converter
nice
List<T> dao.listByExample(T obj)
T dao.getByExample(T obj)
- throws TooManyResultsException
insertMany uses 1 transaction
column name enum in Table class
- filter().eq(Columns.FIRSTNAME, “David”)...
red squigglies from APT
csv
dao.getDatabaseHelper(ctx)
dbHelper.backupAllTablesToCsv()
dbHelper.restore...FromCsv()
exact type conversions
- blobs are Base64 encoded
- doubles saved as raw hex values
file named dbName.vn.TableName+?
UpgradeStrategy
DROP_CREATE
BACKUP_RESTORE (csv)
- dropped cols disappear
- new cols get default values
- renaming not yet supported
UPGRADE
- override DatabaseHelper.upgrade() and/or
- override TableHelper.onUpgrade(...) for
each
limits
no relations (yet)
- want: order.items
- have: item.orderId
- could: orderDao.getItems()
- leaning toward Ref<Order>.get()
can’t compare doubles or blobs with
FilterBuilder.eq()
- planned: .eq(COL, val, delta)
- alt: dao.query(String where, String[] args)
sqlite3
adb shell
cd /data/data/your_app/databases
sqlite3 name_of_db
.schema
SELECT * FROM ...
dbFactory
static db name, version
singleton instance of DatabaseHelper
getTableHelpers()
dao
extends SQLiteDao<T>
- most of the code lives in the base class
points to DatabaseFactory
points to TableHelper
table
all SQL
all getX() / bindX()
Cursor --> obj --> ContentValues
obj --> String[] (for csv)
impl
how to support incremental
compilation?
- anno processing happens in rounds
- full src not available in every round
- stormEnv file under .apt_generated (ADT)
- or build/generated/apt/debug (AS)
- if in doubt, del stormEnv & Project | Clean
Freemarker templates in impl/src/res
watch the Error Log view
working with APT
Start gradle daemon
Connect a remote debugger to it
Initiate your build (including APT
processing)
In IntelliJ, use Rebuild to force APT run
http://turbomanage.wordpress.com/
2014/06/09/debug-an-annotation-
processor-with-intellij-and-gradle/
Android Debug Bridge
adb logcat
adb shell
adb shell dumpsys meminfo <pkg>
adb kill-server :-(
other command lines
- android (launches SDK manager)
- hierarchyviewer
- emulator @avd_name (see ~/.android/avd)
Freebie: adb back up
adb backup -apk -all -nosystem -f
~/mybackupfile.ab
adb restore ~/mybackupfile.ab
future
limited relations (@Key, Ref<T>)
more filter methods gt(), lt(), etc.
@Id for custom id col
@Column(name=”custom”)
src
github.com/turbomanage/storm-gen
R
androidannotations.org
Mark Murphy’s Busy Coder’s Guide to
Android Development
Google I/O sessions
+Android Developers
turbomanage.com (my blog)
google.com/+DavidMichaelChandler
square.github.com (event bus, DI, etc.)

StORM: a lightweight ORM for Android SQLite