greenDAO

Kewang
Agenda
●   SQL syntax
●   SQLite @ Android
●   ORM
●   greenDAO
SQL syntax
SELECT
●   SELECT Persons.LastName, Persons.FirstName,
    Orders.OrderNo FROM Persons INNER JOIN
    Orders ON Persons.P_Id=Orders.P_Id ORDER BY
    Persons.LastName
●   SELECT * FROM Persons WHERE LastName
    BETWEEN 'Hansen' AND 'Pettersen'
●   SELECT Customer,OrderDate,SUM(OrderPrice)
    FROM Orders GROUP BY Customer,OrderDate
INSERT
●   INSERT INTO Persons (P_Id, LastName, FirstName)
    VALUES (5, 'Tjessem', 'Jakob')
●   INSERT INTO Persons VALUES (4,'Nilsen', 'Johan',
    'Bakken 2', 'Stavanger')
UPDATE
●   UPDATE Persons SET Address='Nissestien 67',
    City='Sandnes' WHERE LastName='Tjessem' AND
    FirstName='Jakob'
●   UPDATE Persons SET Address='Nissestien 67',
    City='Sandnes'
DELETE
●   DELETE FROM Persons WHERE
    LastName='Tjessem' AND FirstName='Jakob'
SQLite @ Android
4 components
●   SQLiteOpenHelper
●   SQLiteDatabase
●   SQLiteQueryBuilder
●   Cursor
SQLiteOpenHelper



A helper class to manage database
creation and version management.
SQLiteDatabase + SQLiteQueryBuilder


       delete * 1
       append * 3
       insert * 3
       replace(update) * 4
       open * 5
       query * 15
Oh my god, I'm a professional DBA!!!
Never mind, we have......



             execSQL * 2
db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary
key autoincrement, name varchar(20), age INTEGER)");
and



      rawQuery * 4
      db.rawQuery("select count(*) from person", null);
Cursor




 Recordsets returned by a query
Cursor



         getDataType * 16
         movePosition * 6
         isXXX * 6
Sample code - Controller

datasource = new CommentsDataSource(this);

datasource.open();

List<Comment> values = datasource.getAllComments();
ArrayAdapter<Comment> adapter = new
ArrayAdapter<Comment>(this,
android.R.layout.simple_list_item_1, values);


                                   open
Sample code - Controller


String[] comments = new String[] { "Cool", "Very nice",
"Hate it" };
int nextInt = new Random().nextInt(3);

comment = datasource.createComment(comments[nextInt]);

adapter.add(comment);

                                insert
Sample code - Controller


 if (getListAdapter().getCount() > 0) {
   comment = (Comment) getListAdapter().getItem(0);

     datasource.deleteComment(comment);
     adapter.remove(comment);
 }


                               delete
Sample code - Model

@Override
public void onCreate(SQLiteDatabase database) {
  database.execSQL("create table " + TABLE_COMMENTS +
"(" + COLUMN_ID + " integer primary key autoincrement, "
+ COLUMN_COMMENT + " text not null);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
  db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS);

    onCreate(db);
}
Sample code - Model
public Comment createComment(String comment) {
  ContentValues values = new ContentValues();

    values.put("comment", comment);

  long id = database.insert("comments", null, values);
  Cursor cursor = database.query("comments", allColumns,
"_id" + " = " + id, null, null, null, null);

    cursor.moveToFirst();
    cursor.close();

    return cursorToComment(cursor);
}
Sample code - Model


public void deleteComment(Comment comment) {
  long id = comment.getId();

    database.delete("comments", "_id" + " = " + id, null);
}
Sample code - Model

 private Comment cursorToComment(Cursor cursor) {
   Comment comment = new Comment();

     comment.setId(cursor.getLong(0));
     comment.setComment(cursor.getString(1));

     return comment;
 }
Sample code - Model
public List<Comment> getAllComments() {
  List<Comment> comments = new ArrayList<Comment>();
  Cursor cursor = database.query("comments", allColumns,
null, null, null, null, null);

    cursor.moveToFirst();

    while (!cursor.isAfterLast()) {
      comments.add(cursorToComment(cursor));
      cursor.moveToNext();
    }

    cursor.close();

    return comments;
}
No better choice ?
ORM
Object-relational mapping
Record maps to Java Object
Rails sample
We use SQLite @ Android



        OrmLite
        greenDAO
greenDAO
Architecture
Structure
How to use...


private void initDatabase() {
  helper = new DaoMaster.DevOpenHelper(this, NAME, null);
  master = new DaoMaster(helper.getWritableDatabase());
  session = master.newSession();

    cityDao = session.getCityDao();
    townDao = session.getTownDao();
    storeDao = session.getStoreDao();
}
How to use...


         cityDao.insert(new City(1L, "台北市"));


      storeDao._queryTown_Stores(townId).isEmpty()



town =
townDao.queryBuilder().where(TownDao.Properties.Name.eq(
"新莊區"), TownDao.Properties.CityId.eq(5)).unique();
At first, generate code to use it.


public static void main(String[] args) {
  schema = new Schema(4, "tw.kewang.smile319.model");

    addCity();
    addTown();
    addStore();

    new DaoGenerator().generateAll(schema, "../Prj/src-gen");
}
At first, generate code to use it.
private static void addTown() {
  Entity town = schema.addEntity("Town");

    town.addIdProperty().columnName("id");
    town.addStringProperty("name").notNull();
    town.addDoubleProperty("latitude");
    town.addDoubleProperty("longitude");

  Property cityId =
town.addLongProperty("cityId").notNull().getProperty();

    ToMany cityToTowns = city.addToMany(town, cityId);

    cityToTowns.setName("towns");
}
What is generator ?
Generator contains...
●   A schema at least
●   A schema has many entities (models)
●   A entity has many property (data type, not null,
    autoincrement, index......etc.)
●   2 entities have a relationship (optional)
    ●   Project has a leader
    ●   Leader belongs to a project
QueryBuilder
●   whereXXX
●   joinXXX
●   orderXXX
●   listXXX
●   uniqueXXX
●   or, and
●   limit, offset, count
FAQ
1. Why use generator ?
Typically, annotation & reflection



            BUT
1.can't compiler check
2.reflection is very slow @ Android
2. Why use greenDAO ?
Speed up !
1.generator instead of reflection
2.refine SQLiteCursor
3.custom LongHashMap @ LUT
3. What about OrmLite ?
References
●   http://greendao-orm.com/
●   https://github.com/greenrobot/greenDAO
●   http://www.slideshare.net/droidcon/green-dao
49

greenDAO

  • 1.
  • 2.
    Agenda ● SQL syntax ● SQLite @ Android ● ORM ● greenDAO
  • 3.
  • 4.
    SELECT ● SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo FROM Persons INNER JOIN Orders ON Persons.P_Id=Orders.P_Id ORDER BY Persons.LastName ● SELECT * FROM Persons WHERE LastName BETWEEN 'Hansen' AND 'Pettersen' ● SELECT Customer,OrderDate,SUM(OrderPrice) FROM Orders GROUP BY Customer,OrderDate
  • 5.
    INSERT ● INSERT INTO Persons (P_Id, LastName, FirstName) VALUES (5, 'Tjessem', 'Jakob') ● INSERT INTO Persons VALUES (4,'Nilsen', 'Johan', 'Bakken 2', 'Stavanger')
  • 6.
    UPDATE ● UPDATE Persons SET Address='Nissestien 67', City='Sandnes' WHERE LastName='Tjessem' AND FirstName='Jakob' ● UPDATE Persons SET Address='Nissestien 67', City='Sandnes'
  • 7.
    DELETE ● DELETE FROM Persons WHERE LastName='Tjessem' AND FirstName='Jakob'
  • 8.
  • 9.
    4 components ● SQLiteOpenHelper ● SQLiteDatabase ● SQLiteQueryBuilder ● Cursor
  • 10.
    SQLiteOpenHelper A helper classto manage database creation and version management.
  • 11.
    SQLiteDatabase + SQLiteQueryBuilder delete * 1 append * 3 insert * 3 replace(update) * 4 open * 5 query * 15
  • 12.
    Oh my god,I'm a professional DBA!!!
  • 13.
    Never mind, wehave...... execSQL * 2 db.execSQL("CREATE TABLE IF NOT EXISTS person (personid integer primary key autoincrement, name varchar(20), age INTEGER)");
  • 14.
    and rawQuery * 4 db.rawQuery("select count(*) from person", null);
  • 15.
  • 16.
    Cursor getDataType * 16 movePosition * 6 isXXX * 6
  • 17.
    Sample code -Controller datasource = new CommentsDataSource(this); datasource.open(); List<Comment> values = datasource.getAllComments(); ArrayAdapter<Comment> adapter = new ArrayAdapter<Comment>(this, android.R.layout.simple_list_item_1, values); open
  • 18.
    Sample code -Controller String[] comments = new String[] { "Cool", "Very nice", "Hate it" }; int nextInt = new Random().nextInt(3); comment = datasource.createComment(comments[nextInt]); adapter.add(comment); insert
  • 19.
    Sample code -Controller if (getListAdapter().getCount() > 0) { comment = (Comment) getListAdapter().getItem(0); datasource.deleteComment(comment); adapter.remove(comment); } delete
  • 20.
    Sample code -Model @Override public void onCreate(SQLiteDatabase database) { database.execSQL("create table " + TABLE_COMMENTS + "(" + COLUMN_ID + " integer primary key autoincrement, " + COLUMN_COMMENT + " text not null);"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_COMMENTS); onCreate(db); }
  • 21.
    Sample code -Model public Comment createComment(String comment) { ContentValues values = new ContentValues(); values.put("comment", comment); long id = database.insert("comments", null, values); Cursor cursor = database.query("comments", allColumns, "_id" + " = " + id, null, null, null, null); cursor.moveToFirst(); cursor.close(); return cursorToComment(cursor); }
  • 22.
    Sample code -Model public void deleteComment(Comment comment) { long id = comment.getId(); database.delete("comments", "_id" + " = " + id, null); }
  • 23.
    Sample code -Model private Comment cursorToComment(Cursor cursor) { Comment comment = new Comment(); comment.setId(cursor.getLong(0)); comment.setComment(cursor.getString(1)); return comment; }
  • 24.
    Sample code -Model public List<Comment> getAllComments() { List<Comment> comments = new ArrayList<Comment>(); Cursor cursor = database.query("comments", allColumns, null, null, null, null, null); cursor.moveToFirst(); while (!cursor.isAfterLast()) { comments.add(cursorToComment(cursor)); cursor.moveToNext(); } cursor.close(); return comments; }
  • 25.
  • 26.
  • 28.
    Record maps toJava Object
  • 29.
  • 30.
    We use SQLite@ Android OrmLite greenDAO
  • 31.
  • 32.
  • 33.
  • 34.
    How to use... privatevoid initDatabase() { helper = new DaoMaster.DevOpenHelper(this, NAME, null); master = new DaoMaster(helper.getWritableDatabase()); session = master.newSession(); cityDao = session.getCityDao(); townDao = session.getTownDao(); storeDao = session.getStoreDao(); }
  • 35.
    How to use... cityDao.insert(new City(1L, "台北市")); storeDao._queryTown_Stores(townId).isEmpty() town = townDao.queryBuilder().where(TownDao.Properties.Name.eq( "新莊區"), TownDao.Properties.CityId.eq(5)).unique();
  • 36.
    At first, generatecode to use it. public static void main(String[] args) { schema = new Schema(4, "tw.kewang.smile319.model"); addCity(); addTown(); addStore(); new DaoGenerator().generateAll(schema, "../Prj/src-gen"); }
  • 37.
    At first, generatecode to use it. private static void addTown() { Entity town = schema.addEntity("Town"); town.addIdProperty().columnName("id"); town.addStringProperty("name").notNull(); town.addDoubleProperty("latitude"); town.addDoubleProperty("longitude"); Property cityId = town.addLongProperty("cityId").notNull().getProperty(); ToMany cityToTowns = city.addToMany(town, cityId); cityToTowns.setName("towns"); }
  • 38.
  • 39.
    Generator contains... ● A schema at least ● A schema has many entities (models) ● A entity has many property (data type, not null, autoincrement, index......etc.) ● 2 entities have a relationship (optional) ● Project has a leader ● Leader belongs to a project
  • 40.
    QueryBuilder ● whereXXX ● joinXXX ● orderXXX ● listXXX ● uniqueXXX ● or, and ● limit, offset, count
  • 41.
  • 42.
    1. Why usegenerator ?
  • 43.
    Typically, annotation &reflection BUT 1.can't compiler check 2.reflection is very slow @ Android
  • 44.
    2. Why usegreenDAO ?
  • 45.
    Speed up ! 1.generatorinstead of reflection 2.refine SQLiteCursor 3.custom LongHashMap @ LUT
  • 46.
    3. What aboutOrmLite ?
  • 48.
    References ● http://greendao-orm.com/ ● https://github.com/greenrobot/greenDAO ● http://www.slideshare.net/droidcon/green-dao
  • 49.