green dao

Post on 19-May-2015

22.467 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

greenDAO

A look behind the scenes

Droidcon Berlin 2012, Markus Junginger

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

Agenda

What is greenDAO?

– SQLite database

– ORM

– Code generation based on meta model

Background info and „secret“ internals

– Why code generation?

– Performance Tweaks

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

Common solution: ORM

ORM offers a higher level API

– Read and write objects

– CREATE TABLE done for you

– Expressing Queries

SQLite

Database

Java Object

Java Object

Java Object greenDAO

Example: SQLite vs. greenDAO

String[] columns = { "note", "date_changed" };

String[] idArgs = { String.valueOf(id) };

SQLiteCursor cursor = (SQLiteCursor) db.query("notes", columns,

"_id=?", idArgs, null, null, "note");

try {

if (cursor.getCount() != 1) {

throw new Exception("Unexpected count: " +cursor.getCount());

}

cursor.moveToNext();

String note = cursor.getString(0);

String date = cursor.getString(1);

updateUi(note, date);

} finally {

cursor.close();

}

// greenDAO

Note note = noteDao.load(id);

updateUi(note.getNote(), note.getDate());

greenDAO Overview

Entities & DAOs

Code generation

Open Source:

https://github.com/greenrobot/greenDAO

Apache 2 license: core library

(embedded in your app)

GPL3: generator

(you usually don‘t have changes here)

greenDAO Structure

Generator Project (Plain Java)

Schema-Model • Entities • Properties • Relations • Indexes, …

greenDAO Generator Lib +FreeMarker

Android Project

Sources

greenDAO Core Lib

Generated Sources • Entities • DAOs

greenDAO Code Generation

Code Generation: Meta Model

In generator project

Defines data model

(your schema)

Define with Java

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);

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;

}

}

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);

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();

Entity relations

Entity type relates to another entity type

Supports to-one and to-many relations

Unidirectional

Bidirectional: requires manual updates

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();

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();

Active Entities

Have (some) persistence methods

– update

– delete

– refresh

greenDAO Design Goals

Maximum Performance

Low resource usage

– Memory consumption

– Library size

Easy-to-use API

Focus on the essentials

Optimized for Android

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

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)

Regular Performance Tracking

Different scenarios are tested

Tracked in Excel files

Excel files are pushed to github

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

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

Profiling to find hotspots

Use traceview

Enable in code: Debug.

startMethodTracing(

traceName);

See class

PerformanceTest

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%

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);

}

Custom Cursor implementation

Replacing SQLiteCursor

de.greenrobot.dao.FastCursor

Performance gain: ~30%

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

LongHashMap & More

Custom de.greenrobot.dao.LongHashMap

+ Locking improvements

+ Minor performance tweaks

Performance gain: from 30% up to 117%

Performance: Entities / Second

Measured on a Nexus S (1 GHz), Android 2.3

Performance comparison

Measured on a Nexus S (1 GHz), Android 2.3

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

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?

Disclaimer, Rechtliches

Alle Inhalte urheberrechtlich geschützt.

© Copyright 2011 Markus Junginger

All rights reserved.

Kontakt: markus@greenrobot.de

http://greenrobot.de

http://twitter.com/#!/greenrobot_de

top related