GreenDao_5.查询

查询

查询返回匹配某些规则的数据。你可以使用原SQL查询或使用querybuilder API greendao来获取数据。查询还支持lazy-loading,它可以在操作大的结果集时节省内存和性能。

QueryBuilder

querybuilder类允许你针对Entity自定义查询条件而不需要使用SQL语句。编写SQL不是每个人都喜欢的,也容易出现错误,你只会在运行时通知。QueryBuilder是更容易使用和节省你写SQL的时间。

例如:Query for all users with the first name “Joe” ordered by their last name.

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

例如: Get users with the first name “Joe” that are born in October 1970 or later.

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

Limit, Offset, and Pagination

有时候你只需要一个查询中的少量数据,如前10条数据用于在界面展示。这将在你有很多数据并且无法使用where限制查询的条数。QueryBuilder 就提供了这样的方法:

limit(int)  限制查询返回的数据条数。
offset(int) 设置查询跳过的条数,offset(int)必须和limit(int)一起使用。

(自定义类型作为查询参数)Custom Types as Parameters

通常GreenDao会在查询中自动进行类型匹配转换。例如booleans 匹配成 INTEGER 用0、1来表示;Dates 会匹配成 (long) INTEGER 数据。
但是自定义类型是一个例外:现在,你在查询中必须使用在数据库中表示的值。例如为了匹配enum被转换成int,你在在查询中应该使用int数据

(查询和懒加载)Query and LazyList

Query类代表一个可以被执行多次的查询。当你使用QueryBuilder中的方法去获取数据(例如list()),QueryBuilder 内部也使用了Query。如果你想执行一个查询多次,可以在QueryBuilder使用build()创建一个Query而不是执行他。
greenDAO 支持unique 数据和unique 数据集。如果你希望在Query或QueryBuilder使用unique()获取一个unique数据, 你将会得到一个数据或者查询不到数据时得到null。如果你希望得到一个non-null数据,你可以使用uniqueOrThrow(),该方法确保返回non-null数据或者抛出DaoException。
如果你想得到数据集,可以使用以下list方法:

list()  
所有实体加载到内存中;结果通常是一个ArrayList,容易使用
listLazy()  
实体是按需加载到内存中。一旦访问列表中的一个元素第一次加载和缓存以备将来使用。必须关闭。
listLazyUncached()  
一个“虚拟”的实体列表:任何访问列表元素的结果从数据库加载数据。必须关闭。
listIterator()  
遍历结果通过加载数据按需(延迟)。数据没有被缓存。必须关闭

方法listLazy、listLazyUncached、listIterator都使用了greenDAO的 LazyList 类。为了实现按需加载数据,它持有数据库cursor对象。这个就是必须确保关闭LazyList和iterators,通常是在try..catch代码块中。

执行查询多次(Executing Queries multiple times)

一旦你通过QueryBuilder创建了query 对象,该query对象可以在之后复用,这样比重新创建新的Query 对象更加高效。如果查询条件不变,你只要使用list()或unique()获取结果。如果查询条件有所改变,你可以使用setParameter 方法修改查询条件。现在,参数按顺序排列,下标已0开始。

//查询first name=Joe 并且出生在1970的用户
Query query = userDao.queryBuilder().where(
Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))
.build();
List joesOf1970 = query.list();
//查询first name=Maria并且出生在1977的用户
query.setParameter(0, "Maria");
query.setParameter(1, 1977);
List mariasOf1977 = query.list();

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

如果你要想在多线程执行查询,你必须在query对象调用forCurrentThread()为当前线程获取一个Query实例。Query对象绑定在调用build()方法的线程上。这样你可以很安全的调用setParameter方法,而其他线程无法干扰。如果其他线程调用绑定在别的线程的Query的setParameter方法或执行绑定在别的线程的Query,将会抛出异常。就像,你不需要一个synchronized 的statement。事实上,你应该避免使用lock因为当前transactions使用同一个Query对象时有可能导致死锁出现。

为了完全避免这些潜在的死锁,greenDAO 提供了 forCurrentThread()方法。这个将会返回Query类型的thread-local的实例,可以在当前线程安全使用。每次forCurrentThread()被调用时,parameters设置为initial parameters,当Query对象被build方法创建出来时。

原始查询(Raw queries)

防止QueryBuilder 没有提供你想要的方法,Raw queries是你的一条后路。这里提供了两种方式使用原始查询获取数据实体。其中更加推荐的方式是使用QueryBuilder 和WhereCondition,StringCondition。使用这个可以通过任何SQL WHERE子句的片段去构建Query对象。

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

另一种方式是使用QueryBuilder提供的queryRaw或queryRawCreate方法。它们允许您通过原始SQL字符串,这是附加在选择和实体列。通过这种方式,您可以有任何WHERE和ORDER BY子句你想选择实体。实体表可以使用别名“T”

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

查询异常排查(Troubleshooting queries)

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

通过设置以上两个属性,将会输出那些将生成的SQL命令,调用时传递的值构建时的日志。它还帮助复制已经生成的sql语句到SQL数据库管理工具中和执行相应的sql语句。

你可能感兴趣的:(GreenDao官方教程)