第五篇 查询

查询会返回符合某些特定标准的实体。你可以使用原始的SQL定制查询语句,或者更好的方式:使用GreenDao的QueryBuilder API。该查询也支持lazy-loading的结果集。这样在操作大量结果集的时候可以节省内存和性能。

QueryBuilder

QueryBuilder可以帮助你构建自定义的查询语句,而不使用SQL的情况。并不是每个人都喜欢书写SQL语句,当然很容易就会出一些错,这些错误只有在运行的时候才会被发现。而QueryBuilder很容易使用,节省了你书写SQL语句的时间。当然,由于语法的检验是在编译时才执行,所以在查询语句中发现bug是很困难的。
QueryBuilder的编译时间会检验属性的引用,这样能够在greenDao后面,通过代码生成的方法发现bug。
比如:查找所有以“Joe”为first name 的用户,并以last name排序:

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

嵌套情况

获取用户名字为“Joe”并且在1970年9月之后出生的用户
这里要说明下:user 的birthday对于year,month,和day是一个分离的属性。我们可以以一种更正常的方式表达这种条件:
First name is “Joe” AND (year of birth is greater than 1970 OR (year of birth is 1970 AND month of birth is equal to or greater than 10 (October).

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

Query 和 LazyList

Query类代表一个可以多次执行的查询。当你使用QueryBuilder之一的方法去获取结果的时候,QueryBuilder内部使用了Query 类。
如果你想运行更多相同的查询,你应该调用build()在QueryBuilder上,去创建Query,而不是执行它。
greenDao支持唯一的结果和结果列表。如果你想得到一个唯一的结果,可以调用Query或者QueryBuilder的unique()方法,这样在没有匹配条件的时候会返回一个唯一的结果,而不是null。如果你希望禁止用例中返回null,可以调用uniqueOrThrow(),该方法会保证返回一个非null的实体。否则就会抛出一个DaoException。

如果你期望一次性返回多个实体,可以使用以下方法:
list():所有的实体被加载到内存中。该结果通常是一个没有magic involved的ArrayList。使用起来最简单。
listLazy():实体按照需求加载进入内存。一旦列表中的一个元素被第一次访问,它将被加载同时缓存以便以后使用。必须close。
ListLasyUncached(): 一个“虚拟”的实体列表:任何对列表元素的访问都会导致从数据库中加载,必须close。
listIterator(): 遍历通过需要的时候加载(lazily)获得的结果,数据没有缓存,必须close。
listLazy, listLazyUncached 和 listIterator类使用了greenDao的LazyList类。为了根据需求加载数据,它持有了一个数据库cursor的引用。
这是做是为了确保关闭 lazy list和iterators(通常在try/finally 代码块中)。
一旦有的元素被访问或者遍历过,来自lsitLazy()的cache lazy list和来自listIterator()方法的lazy iterator将会自动关闭cursor。
然而,如果list的处理过早的完成了,你应该调用 close()手动关闭。

多次执行查询

一旦你使用QueryBuilder构建了一个query,该query对象以后可以被重复使用。这种方式比总是重复创建query对象要高效。
如果query的参数没有变更,你只需要再次调用list/unique方法即可。如果有参数变更,你就需要调用setParameter方法处理每一个变更的参数。
现在,个别参数由基于零的参数索引寻址。该下标基于你传递到querybuilder的参数。

使用query对象获取出生在1970年 并且 first name 为 joe 的用户:

Query query = userDao.queryBuilder().where(
Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
.build();
List joesOf1970 = query.list();

使用query对象,可以查询

query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List mariasOf1977 = query.list();

在多个线程中执行查询

如果你在多线程中使用了查询,你必须调用query的 forCurrentThread()为当前的线程获得一个query实例。从greenDAO 1.3开始,
query的实例化被绑定到了那些创建query的线程身上。这样做保证了query对象设置参数时的安全性,避免其他线程的干扰。如果其他线程
试着在query对象上设置参数或者执行查询绑定到了其它线程,将会抛出异常。这样一来,你就不需要一个同步语句了。
事实上你应该避免使用lock,因为如果在并发的事务中使用了同一个query对象,可能会导致死锁。
为了完全避免那些潜在的死锁问题,greenDAO 1.3 引入了forCurrentThread方法,它会返回一个query对象的thread—local实例,该实例
在当前的线程中使用是安全的。当每一次调用 forCueerntThread()的时候,该参数会在builder构建query的时候,设置到初始化参数上。

原始的查询

这里有两种方式执行原始的SQL去获取实体。较好的一种方式是使用QueryBuilder 和 WhereCondition.StringCondition。
使用这个方法,你可以为 query builder 的 WHERE 子句传递任何SQL片段。
下面是一个笨拙的例子展示如果使用这种方式进行一个替代联合查询的子查询。

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

该示例中query Builder没有提供你需要的特性,你可以回到原始的queryRaw或者queryRawCreate方法。它们允许你传递原始的SQL字符串,这些字符串会被添加到SELECT 和实体列后面。这种方式,你可以拥有一个 WHERE 和 ORDER BY 语句查询实体。这种实体表可以通过别名“T”引用。

下面的例子展示了如何创建一个query:使用联合获取名为“admin”的group的users

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

提示

你可以通过生成的常量引用表或者列名。这样建议是为了避免错别字,因为编译器会检验这些名字。在任何实体的DAO,你可以发现 TABLENAME 持有着数据库的名字和一个内部类“Properties”.它的所有属性都是常量。

删除查询

批量删除不删除单独的实体,但所有的实体要匹配一些准则。为了执行批量删除,创建一个QueryBuilder,调用它的buildDelete方法,它会返回一个DeleteQuery。

这部分的API可能会在以后有所变化,比如添加一些更加便利的方法。记住,批量删除现在不会影响到identity scope中的实体。在它们被通过ID访问之前(load 方法)

如果它们被缓存了,你可以激活那些将要被删除的实体。如果导致了一些使用的问题。你可以考虑清除identity scope。

查询故障处理

如果你的query没有返回期望的结果,这里有两个静态的flag,可以开启QueryBuilder身上的SQL和参数的log。

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

它们会在任何build方法调用的时候打印出SQL命令和传入的值。这样你可以对你的期望值进行对比,或许也能够帮助你复制SQL语句到某些

SQLite 数据库的查看器中,执行并获取结果,以便进行比较。

本文转自:http://blog.csdn.net/xushuaic/article/details/24496191

GreenDao官方文档翻译(下)的更多相关文章

  1. GreenDao官方文档翻译(上)

    笔记摘要: 上一篇博客简单介绍了SQLite和GreenDao的比较,后来说要详细介绍下GreenDao的使用,这里就贴出本人自己根据官网的文档进行翻译的文章,这里将所有的文档分成上下两部分翻译,只为 ...

  2. Alljoyn瘦客户端库介绍(官方文档翻译 下)

    由于其他事情耽误,这个翻译现在才完成.接上篇—— 4 瘦客户端核心库架构 由于AllJoyn瘦客户端核心库(AJTCL)必须运行在那些功耗受限.计算能力有限.资源紧缺的设备上,因此它无法像运行在通用型 ...

  3. Data Binding Guide——google官方文档翻译(下)

    这篇博客是Data Binding Guide官网文档翻译的下篇.假设没看过前半部分翻译的能够先看Data Binding Guide--google官方文档翻译(上)  一,数据对象 不论什么不含业 ...

  4. Flume官方文档翻译——Flume 1.7.0 User Guide (unreleased version)中一些知识点

    Flume官方文档翻译--Flume 1.7.0 User Guide (unreleased version)(一) Flume官方文档翻译--Flume 1.7.0 User Guide (unr ...

  5. Flume官方文档翻译——Flume 1.7.0 User Guide (unreleased version)(二)

    Flume官方文档翻译--Flume 1.7.0 User Guide (unreleased version)(一) Logging raw data(记录原始数据) Logging the raw ...

  6. Aircrack-ng官方文档翻译[中英对照]---Airmon-ng

    Aircrack-ng官方文档翻译---Airmon-ng Description[简介] This script can be used to enable monitor mode on wire ...

  7. Aircrack-ng官方文档翻译[中英对照]---Aireplay-ng

    Aircrack-ng官方文档翻译---Aireplay-ng[90%] Description[简介] Aireplay-ng is used to inject frames. Aireplay- ...

  8. Retrofit官方文档翻译

    Retrofit官方文档翻译 官方文档网址 http://square.github.io/retrofit/ 介绍 Retrofit 将你的 HTTP API 转换为 Java 接口. public ...

  9. Spark官方文档翻译(一)~Overview

    Spark官方文档翻译,有问题请及时指正,谢谢. Overview页 http://spark.apache.org/docs/latest/index.html Spark概述 Apache Spa ...

随机推荐

  1. MongoDB (三) MongoDB 安装

    MongoDB安装在Windows上 在 Windows上,首先要安装 MongoDB下载最新发布的MongoDB: http://www.mongodb.org/downloads 确保得到正确的版 ...

  2. Spark基础与Java Api介绍

    原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3832405.html  一.Spark简介 1.什么是Spark 发源于AMPLab实验室的分布式内存计 ...

  3. 李洪强iOS开发之- 实现简单的弹窗

     李洪强iOS开发之- 实现简单的弹窗 实现的效果:  112222222222223333333333333333

  4. 李洪强iOS开发之OC点语法和变量作用域

    OC点语法和变量作用域 一.点语法 (一)认识点语法 声明一个Person类: 1 #import <Foundation/Foundation.h> 2 3 @interface Per ...

  5. linux环境几个特殊的shell变量

    特殊的shell变量: $0  获取当前执行的shell脚本的文件名 $n  获取当前执行的shell脚本的第n个参数值,n=1..9 $*  获取当前shell的所有参数 “$1 $2 $3 …注意 ...

  6. C++名字空间/C++命名空间

    0.序言 名字空间是C++提供的一种解决符号名字冲突的方法. 一个命令空间是一个作用域,在不同名字空间中命名相同的符号代表不同的实体. 通常,利用定义名字空间的办法,可以使模块划分更加方便,减少模块间 ...

  7. iOS 深拷贝和浅拷贝

    注意,本文只说结论不说过程 1. 对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝).如果是对可变对象复制,都是深 ...

  8. 使用RPM管理软件包

    一.概念简介 RPM 全名是『 RedHat Package Manager 』简称则为 RPM,是以一种数据库记录的方式来将你所需要的套件安装到你的 Linux 主机的一套管理程序. 二.实验环境 ...

  9. PowerDesigner如何自定义报表模板

    PowerDesigner如何自定义报表模板 帅宏军 使用PowerDesigner设计数据库非常方便,但是它自带的报表模板一般不符合中国的使用情况.如何设计一个自己的报表模板,并在做项目的数据库设计 ...

  10. Mac显示和隐藏文件的命令

    打开命令行输入即可,不过要重启Finder才能看到效果 显示: defaults write com.apple.finder AppleShowAllFiles -bool true 隐藏: def ...