greendao系列5-尊龙凯时登录首页

查询就是返回符合一定条件的实体。可使用原始的sql语句执行查询;或是更好的方式,使用greendao中querybuilder的api。查询支持懒加载,当操作较大的结果集时,便可节约内存、提高性能。


querybuilder

querybuilder类可构建自定义查询,而无需接触sql语句。编写sql语句不是每个人都喜欢并且它容易导致在运行时才发现的错误。而querybuilder简单易用,将你从编写sql语句中拯救出来。同时它不易在查询代码中出现bug,因为在编译时会进行语法检测。编译时的检查包括对属性的引用,这样greendao就可以在底层通过代码生成的方式组成sql语句。

举例:查询所有名为“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();


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对象的参数,不受其他线程影响。如果其他线程试图设置参数或执行查询,将抛出异常,这样便无需使用同步语句。实际上我们应该避免加锁,因为在并发处理使用了相同的查询对象,容易导致死锁。为完全避免潜在的死锁,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则有所有属性的常量。


删除实体

//todo


检测查询

如果查询结果没有返回你期待的,有两个静态标识可开启querybuilder的sql和参数的日志输出:

querybuilder.log_sql = true;
querybuilder.log_values = true;

这样会输出sql命令和调用相关build方法时传入的参数。

上一篇:

下一篇:

网站地图