GreenDAO 查询

GreenDAO 查询

官网查询介绍:http://greenrobot.org/greendao/documentation/queries/
参考:http://blog.csdn.net/yuyuanhuang/article/details/42751469

查询接口返回符合指定条件的实体对象集合,

你可以使用SQL组织查询语句,但SQl语句容易出错,因为它需要在运行时才能反馈错误,或者采用更好的方法,使用QueryBuilder,可以在没有SQL的情况下自定义查询,并可在编译时检查错误。

greenDao的查询支持延迟加载结果,当结果集很大时会节省内存和提高性能.

QueryBuilder

简单条件查询:查询所有名为Joe的用户,以姓排序

List<User> joes = userDao.queryBuilder()
  .where(Properties.FirstName.eq("Joe"))
  .orderAsc(Properties.LastName)
  .list();

嵌套条件查询:获取所有1970年10月以后出生,名为Joe的用户.
查询条件表达为:名是Joe AND(生日的年份大于1970 OR(生日的年是1970 AND 生日的月等于或大于10))

QueryBuilder<User> 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<User> youngJoes = qb.list();

Query and LazyList

Query类代表一个可以多次执行的查询。如果需要多次执行相同的查询,你应该使用QueryBuilder的build()创建Query。greenDao支持唯一结果(0或1个结果)、和多个结果的查询.

获得唯一结果:

使用Query或QueryBuilder的unique()方法,它会给你唯一的结果或者null(如果没有找到匹配的实体).
如果你的情况不允许null作为结果,调用uniqueOrThrow(),它会保证返回非空的实体(如果没有匹配的结果,它会抛出DaoException异常).

获得多个结果:

list() 所有实体加载到内存,结果是一个典型的ArrayList,容易使用
listLazy() 实体根据需要加载到内存,一旦列表中一个元素被使用,这个元素会被加载和缓存起来,给后续重复使用,使用完后需要关闭
listLazyUncached() 一个虚拟的实体列表:对列表中元素的任何访问将会导致从数据库加载数据。使用后必须关闭
listIterator() 使用迭代器来遍历结果集,它会根据需要加载数据(延迟加载)。数据没有缓存,使用后必须关闭

listLazy、listLazyUncached 和listIterator 使用了LazyList类,为了按需加载数据,该类保存了数据库游标的引用,这也是使用后必须关闭的原因(一般在try/finally代码块中关闭)

listLazy() 所返回的延迟缓存列表和 istIterator() 返回的延迟加载迭代器,在其所有的元素都被访问或遍历到后会自动关闭数据库游标。如果数据的访问过早的结束了(没有遍历完全),那么必须手动关闭数据库游标。

使用Queries进行多次查询

一旦使用QueryBuilder构造了一个query,这个query对象后续可以重复使用,这比总是创建新的Query对象更有效。
如果查询条件没有变,只需要再次调用list/unique方法。
如果参数有改变,必须调用setParameter方法改变参数,参数索引从0开始。

// 查询名为Joe,出生在1970年的用户
Query<User> query = userDao.queryBuilder().where
	(Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
	.build();
List<User> joesOf1970 = query.list();
 
// 随后使用同一个Query对象,我们可以改变参数查询名为Marias,出生在1977年的用户
query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List<User> mariasOf1977 = query.list();

在多线程中执行查询

如果你想在多线程中使用查询,你必须调用query对象的forCurrentThread()方法来获取当前线程的Query实例

从greenDao1.3以后,Query的实例对象绑定到构建query的线程中,这样,你可以安全的对Query对象设置参数而不受其他线程的干扰.如果其他线程试图对query对象设置参数或者执行绑定在其他线程的查询,greenDao会抛出异常。这样,你就不需要使用同步语句。

为了完全避免潜在的死锁,greenDao1.3引入了forCurrentThread()函数,它会返回本线程的Query实例,它在当前线程可以安全的使用。每次调用forCurrentThread(),其参数与使用QueryBuilder初始化Query对象时的参数一致

原始查询

如果QueryBuilder没有提供需要的查询,有两种方法可以执行原始SQL。

首选的方法是使用QueryBuilder和WhereCondition.StringCondition,可以将任何SQL片段作为QueryBuilder的WHERE子句传递。
示例:运行子选择:

Query<User> query = userDao.queryBuilder().where(
  new StringCondition("_ID IN (SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)")
).build();

第二个方法是使用queryRaw或queryRawCreate方法,传递一个原始SQL字符串,该字符串会被追加到在 SELECT+实体列名 之后。通过这种方式,可以在任何需要的WHERE或ORDER BY子句中选择实体。实体表可以使用别名T引用。

示例:构建一个检索GROUP表中组名为“admin”的用户的查询

Query<User> query = userDao.queryRawCreate(
  ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin"
);

构建的sql语句:SELECT USER.COLUMN1, USER.COLUMN2 ... FROM USER T, GROUP G WHERE G.NAME='admin' AND T.GROUP_ID=G._ID

提示:使用生成的常量来指向表和列名,可以避免错别字,因为编译器会检查名字。在实体对应的Dao类中可以找到TABLENAME(数据库表的名字),Dao类中还有一个内部类Properties,包含所有的属性常量(对应列名)。

查找查询中的问题

查询没有返回你期望的值?这里有2个静态的标识,一个是将sql语句打印出来,一个是将传入QueryBuilder的参数打印出来:

QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;

这些日志会记录生成的sql命令和调用build()方法传入的参数,这样可以对比他们是不是预期的,可以将生成的SQL复制到SQLite数据库浏览器中,查看它的执行结果

posted @ 2017-07-27 14:45  zxlc  阅读(2226)  评论(0编辑  收藏  举报