greenDAO学习分享总结
greenDAO(最新版本号V2.0.0的Readme)
========
greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases. Being highly optimized for Android, greenDAO offers great performance and consumes minimal memory.
1. 轻量、高速的ORM(Object Relation Mapping对象关系映射)解决方式,将实体对象映射到SQLite数据库中
2. Android开发中数据库操作的最佳方案
3. 提供高性能、消耗低内存
Home page, documentation, and support links: http://greendao-orm.com/
Features
greenDAO has a unique set of features:
- Rock solid: greenDAO has been around since 2011 and is used by countless famous apps(2011年開始被用于非常多有名的应用开发中)
- Super simple: concise and straight-forward API(简明好用的api)
- Small: The library is <100K and it’s just plain Java jar (no CPU dependent native parts)(100kb大小。不依赖不同手机cpu型号native层,Android集成的java jar包就能够)
- Fast: Probably the fastest ORM for Android, driven by intelligent code generation(android上最快的orm,自己主动生成代码,无需自己写繁琐的entity实体类,实体dao层处理类)
- Safe and expressive query API: QueryBuilder uses property constants to avoid typos(简洁的api供查询)
- V2.0.0 Powerful joins: query across entities and even chain joins for complex relations(眼下最新greendao已经有2.0版,添加了为比較复杂关系表,提供关联查询等)
- V2.0.0 Flexible property types: use custom classes or enums to represent data in your entity
Add greenDAO to your project
greenDAO is available on Maven Central. Please ensure that you are using the latest versions by checking here and here
Gradle dependency for your Android app:
compile 'de.greenrobot:greendao:2.0.0'
Gradle dependency for your Java generator project:
compile 'de.greenrobot:greendao-generator:2.0.0'
(在Android Studio怎样引用greendao)
Features in Beta(说明还处于Beta版)
Those features are already here for you to try out. Note: Documentation and test coverage may be lacking, and the API may change in the future.
Asynchronous API(异步操作api)
- New AsyncSession (acquired from DaoSession.startAsyncSession()) provides most operations for DAOs, Queries, and transactions in a asynchronously variant
- AsyncOperations are processed in order by a background thread
- waitForCompletion methods for AsyncSession and AsyncOperations
- AsyncOperationListener for asynchronous callback when operations complete
- Asynchronous operations can be merged in single transactions (details follow)
- Added raw SQL queries returning a Query object (LazyList support etc.)
More Open Source by greenrobot
EventBus is a central publish/subscribe bus for Android with optional delivery threads, priorities, and sticky events. A great tool to decouple components (e.g. Activities, Fragments, logic components) from each other.(greenrobot团队的还有一有名开源项目)
greenrobot-common is a set of utility classes and hash functions for Android & Java projects.
Follow us on Google+ to stay up to date.
——————————-华丽的切割线———————————-
For the same given entity, greenDAO inserts and updates entities over 2 times faster, and loads entities 4.5 times faster for loading entities than ORMLite. For typical applications the loading speed is the most important.
(比起ORMLite快,同样的数据,更新是它的两倍。查询是它的4.5倍)
greenDAO 使用「Code generation」的方式
DAO CODE GENERATION PROJECT
这是其核心概念:为了在我们的 Android 工程中使用 greenDAO ,我们须要另建一个纯 Java Project,用于自己主动生成后继 Android 工程中须要使用到的 Bean、DAO、DaoMaster、DaoSession 等类。
CORE CLASSES & MODELLING ENTITIES
从https://github.com/greenrobot/greenDAO上下载整个完整的项目,然后导入到Android Studio中去,修复參数配置,终于在IDE中完整的项目结构文件夹例如以下:
Entity
Entity simple = schema.addEntity("SimpleEntity");
simple.addIdProperty();
simple.addBooleanProperty("simpleBoolean");
simple.addByteProperty("simpleByte");
simple.addShortProperty("simpleShort");
simple.addIntProperty("simpleInt");
simple.addLongProperty("simpleLong");
simple.addFloatProperty("simpleFloat");
simple.addDoubleProperty("simpleDouble");
simple.addStringProperty("simpleString");
simple.addByteArrayProperty("simpleByteArray");
//生成一个ContentProvider内容提供器,供其它程序訪问数据
simple.addContentProvider().readOnly();
QueryBuilder
查询就是返回符合一定条件的实体。
可使用原始的SQL语句运行查询;或是更好的方式,使用greenDAO中QueryBuilder的API。查询支持懒载入。当操作较大的结果集时。便可节约内存、提高性能。
举例:查询全部名为“Joe”的用户。且按姓排序。
List joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
嵌套条件的样例:获取名为“Joe”出生在1970年10月份或1970年之后的用户。
假如用户的生日分成年月日三个字段,这样便可换一种方式来表示上面的查询:名字是“Joe” AND (生日年份大于但不包含1970 OR(生日年份是1970 AND 月份大于等于10))。
QueryBuilder qb = userDao.queryBuilder();
qb.where(Properties.FirstName.eq("Joe"),
qb.or(Properties.YearOfBirth.gt(1970),
qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));
List youngJoes = qb.list();
**(注意上面的括号。为了引出ge推断条件大于等于)
GreenDAO的Properties字段属性查询条件全部定义在了一个de.greenrobot.dao.Property类里面,详情请參照该类里面方法说明。
QueryBuilder的查询推断全部定义在一个de.greenrobot.dao.query.QueryBuilder类里面,详情请參照该类里面方法说明。
Query和LazyList
Query类代表着一个查询,可被运行多次。但使用QueryBuilder的方法之中的一个(如list())获取一个结果时。QueryBuilder内部就是使用Query类。假设要多次运行同样的请求,可调用QueryBulder的build()方法创建一个查询而非运行它。
greenDAO同一时候支持获取单个结果(0或者1个结果)和结果列表。
若期待获取一个结果能够调用Query(或QueryBulder)的unique(),这将返回一个结果或匹配不到返回null。若不同意返回nul,可调用uniqueOrThrow(),它将保证返回一个非null实体(否则会抛出一个DaoException)。
若期待返回多个结果,能够调用以下的list…方法:
list() 全部实体载入内存,以ArrayList形式返回,使用最简单。
listLazy() 实体按需载入到内存。当列表中的当中一个元素第一次被訪问。它会被载入并缓存备将来使用。
使用完必须关闭。
listLazyUncached() 一个“虚拟”的实体列表:不论什么訪问列表中的元素都会从数据库中读取。使用完必须关闭。
listIterator() 可迭代訪问结果集,按需载入数据,数据不缓存。使用完必须关闭。
方法listLazy,listLazyUncached和 listIterator需使用greenDAO的LazyList类。LazyList持有一个数据库游标,可按需载入数据。
这也是为什么必须确保关闭懒载入列表和迭代器(通常使用try/finally包裹)。listLazy()的懒载入列表和listIterator()懒载入迭代器,在全部元素被訪为或遍历后自己主动关闭游标。可是。还是必须调用close()方法。防止list的运行过早结束。
多次运行查询
通过QueryBuilder创建一个Query,Query对象能够在一次查询结束后又一次使用。
相比创建新的Query对象,这样更加高效。假设查询參数没有改变,可再次调用list/unique方法。假设參数改变。则必须调用setParameter方法改动对应的參数。參数的索引地址从0開始。而索引为參数加入到QueryBuilder的顺序。
以下的样例使用一个查询对象,获取以“Joe”为名,出生于1970年的用户:
Query query = userDao.queryBuilder().where(
Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
.build();
List joesOf1970 = query.list();
使用该查询对象,可搜索“Marias”生于1977年:
query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List mariasOf1977 = query.list();
多线程运行查询
多线程中使用查询。必须调用Query的forCurrentThread()获取当前线程的查询实例。
从greenDAO1.3開始。Query对象实例绑定到创建它的线程。
这样便可安全的设置Query对象的參数,不受其它线程影响。假设其它线程试图设置參数或运行查询,将抛出异常。这样便无需使用同步语句。
实际上我们应该避免加锁。由于在并发处理使用了同样的查询对象。easy导致死锁。
为全然避免潜在的死锁,greenDAO1.3引入方法forCurentThread(),返回一个本地线程的Query对象,能够被当前线程安全使用。每次forCurrentThread()方法被调用,全部參数将被设置成该查询被其builder创建时的參数。
原始查询
有两种方法运行原始SQL语句,获取实体结果集。
最好的方式是使用QueryBuilder和WhereCondition.StringCondition。可传入不论什么SQL片段到WHERE字句。例如以下:
Query query = userDao.queryBuilder().where(
new StringCondition("_ID IN " +
"(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)").build();
当QueryBuilder的功能未能符合需求时,可使用queryRaw或queryRawCreate方法。
你可传入一个原始语句,它会被加入到SELECT和实体字段后。
用这样的方式能够编写不论什么WHERE和ORDER BY字句去查询须要的实体集。实体表能够使用别名“T”来引用。
以下的样例使用联合查询检索所在组为“admin”的全部用。
Query query = userDao.queryRawCreate(", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");
注意:可用生成的常量表示表名和字段名。这是推荐的做法。避免编写错误。在一个实体的DAO中。TABLENAME表示数据库的表名。其内部类Properties则有全部属性的常量。
删除实体
删除实体的基类是de.greenrobot.dao.AbstractDao,里面提供了删除的api
public void deleteAll() {
// String sql = SqlUtils.createSqlDelete(config.tablename, null);
// db.execSQL(sql);
db.execSQL("DELETE FROM '" + config.tablename + "'");
if (identityScope != null) {
identityScope.clear();
}
}
/** Deletes the given entity from the database. Currently, only single value PK entities are supported. */
public void delete(T entity) {
assertSinglePk();
K key = getKeyVerified(entity);
deleteByKey(key);
}
/** Deletes an entity with the given PK from the database. Currently, only single value PK entities are supported. */
public void deleteByKey(K key) {
……
}
这个类还提供了loadAll和insert方法
支持事务
SQLite 数据库是支持事务的,事务的特性能够保证让某一系列的操 作要么全部完毕,要么一个都不会完毕。
GreenDAO也封装了SQLite的事务属性,如de.greenrobot.dao.AbstractDao类里(详细怎样做SQLite事务的封装请參照源代码):
/**
* Inserts the given entities in the database using a transaction.
*
* @param entities
* The entities to insert.
*/
public void insertInTx(Iterable<T> entities) {
insertInTx(entities, isEntityUpdateable());
}
检測查询
假设查询结果没有返回你期待的,有两个静态标识可开启QueryBuilder的SQL和參数的日志输出:
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
这样会输出SQL命令和调用相关build方法时传入的參数。
个人感悟
只是这个框架的本质是对sqlite数据库api的封装。提供了更简洁的api调用。相对使用android原生sqlite的优势有:
1、对于ORM关系型数据库,sqlite须要自己写sql语句来组织数据之间的关系,greendao提供了更加便捷的api为我们攻克了。
2、实现了数据库查询list集合的缓存机制,这是sqlite所没有的。
3、攻克了多线程查询中遇到的各种问题,避免了sqlite的加锁查询。
4、框架实现。让代码更加规范更加简洁。
结语
GreenDAO框架给我们提供了在Android平台上非常好的ORM框架设计思路。是一个非常值的学习的开源项目。