查询就是返回符合一定条件的实体。可使用原始的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...方法:
方法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方法时传入的参数。
上一篇:
下一篇: