Greendao Query and QueryBuilder

greenDao查询(Queries)

Queries帮助你返回entities。你可以使用Raw SQL(原生查询)构造查询,然而使用greenDao的QueryBuilder API才是更加优雅的方式。Queries支持lazy-loading的查询结果。

当处理一个较大的结果集时,lazy-loading(懒加载模式)可以节省内存提高性能。

QueryBuilder

你可以使用QueryBuilder 创建自定义查询,而不用做丑陋的SQL拼接。毕竟不是每一个人都擅长写SQL,并且还容易出错。QueryBuilder使用非常方便,它将你从SQL编写中解脱出来。妈妈再也不用担心写SQL时出现bug了,因为语法检查是在编译时进行的。 greenDao简单查询例子:查询所有first name为“Joe”的人,然后按照last name排序。

greenDao Nested conditions query(嵌套查询)例子: 有一个需求是查询first name为“Joe”并且出生在1970年10月或者之后的人。 假如我们有一个用户,其中生日被分为,year、month、day三个字段。于是我们可以写出一个嵌套查询。

Query and LazyList

使用QueryBuilder的方法来获取结果,例如list(),在QueryBuilder的内部是使用的Query类。如果你想得到Query的引用来多次执行,可以使用QueryBuilder.Build()来创建查询。 greenDao支持唯一结果(0 or 1个结果)和结果集。如果希望获得唯一结果就调用unique(),这样会获得唯一结果或者null。如果你不希望获得null,可以调用uniqueOrThrow()这样可以确保返回一个非空的entity。 如果你期望返回多个entity作为查询结果,可以使用如下的方法:

方法 描述
list() entity都会加载到内存中,返回的结果通常就是ArrayList。
listLazy() Entity按需加载到内存中,在第一次访问list中的element时,它就会呗加载并且缓存。
listLazyUncached() 每次访问结果集的时候都是从数据库中加载,而不使用缓存。
listIterator() 通过迭代器访问结果集,并且采用的时lazy-loading,结果不会缓存。
listLazy,listLazyUncached,listIterator都是采用greenDao的LazyList类。在真正使用数据的时候加载(on-demand),它持有一个database cursor引用。这就是为什么需要调用close方法关闭lazy lists和iterators(通常在try/finally块里面)。当所有的element被访问了之后,listLazy()和listIterator()自动关闭cursor。如果list提前处理完成,调用close()就是你必须完成的工作。

查询复用(Executing Queries multiple times)

如果使用QueryBuilder创建query,查询对象(Query object)可以重用。可以避免重复创建查询对象性能更高。如果查询参数没有变化,可以再调用list或者unique方法。如果查询参数有变化,需要对每一个改变的parameter调用setParameter方法。可以通过下标index访问parameter。 下面的例子是用Query Object查询出生在1970年并且first name为“Joe”的人:

使用上面的查询对象,我们可以查询1977年之后出生的“Marias”

多线程查询(Executing queries in multiple threads)

如果使用多线程查询,必须调用query的forCurrentThread()方法,返回当前线程的查询实例。从greenDao1.3开始,查询实例与创建查询的现场绑定在一起。在查询对象上安全地调用setParameter,而其他线程不能干预。

如果线程A想调用已经被线程B绑定的query对象,或者执行查询,将会抛出一个exception。像这样,你不需要synchronized。实际上要避免使用锁,因为如果当前的transaction使用同一个查询对象时,将导致死锁。

为了避免这种潜在的死锁,greenDao1.3推出了forCurrentThread()方法。这将返回一个thread-local的查询实例,用于当前线程的安全调用。每次forCurrentThread()被调用,parameters就会被设置称为查询对象创建的初始状态。

原生查询(Raw queries)

如果QueryBuilder没有提供你需要的特性,那么Raw Queries就是最后的解决方案。这里有两种方法执行Raw SQL。推荐使用QueryBuilder,WhereConditon,StringCondition。通过这种方式可以传入任何的SQL片段作为Where条件。下面是一个假设的例子执行一个子查询(采用join是更好的解决方案):

另外一种方式是采用queryRaw或者queryRawCreate方法。可以传入一个raw SQL,它被追加到SELECT和columns之后。这样,就可以使用Where和Order by来选择entities。表还可以使用别名“T”: 下面的例子是查询“admin”用户组下面的所有用户:

注意:为了避免录入错误,使用表名和列名时采用自动生成的约束,因为编译器会检查名称。在entity的Dao里,可以看到TABLENAME管理数据库表名,所有包含约束的的内部类属性管理表的列名称。

Delete Queries

要执行批量删除,需要创建一个QueryBuilder然后调用他的buildDelete方法,然后执行DeleteQuery。这部分的API将来会有变动。

打开调试日志,追踪问题(Troubleshooting queries)

如果你的查询没有返回期望的结果,这里有两个static标记用来打开SQL和parameter日志:



  copyright@黑月神话,转载请注明出处:vjson.com

发表评论