Android 数据库ORM框架GreenDao学习心得及使用总结<二>

简介: 转:http://blog.csdn.net/xushuaic/article/details/24496191   第五篇 查询 查询会返回符合某些特定标准的实体。你可以使用原始的SQL定制查询语句,或者更好的方式:使用GreenDao的QueryBuilder API。

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

 

第五篇 查询

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

 

QueryBuilder

 

QueryBuilder可以帮助你构建自定义的查询语句,而不使用SQL的情况。并不是每个人都喜欢书写SQL语句,当然很容易就会出一些错,这些错误只有在运行的时候才会被发现。而QueryBuilder很容易使用,节省了你书写SQL语句的时间。当然,由于语法的检验是在编译时才执行,所以在查询语句中发现bug是很困难的。

QueryBuilder的编译时间会检验属性的引用,这样能够在greenDao后面,通过代码生成的方法发现bug。

比如:查找所有以“Joe”为first name 的用户,并以last name排序:

 

[java]  view plain copy
 
  1. List joes = userDao.queryBuilder()  
  2. .where(Properties.FirstName.eq("Joe"))  
  3. .orderAsc(Properties.LastName)  
  4. .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).

[java]  view plain copy
 
  1. QueryBuilder qb = userDao.queryBuilder();  
  2. qb.where(Properties.FirstName.eq("Joe"),  
  3. qb.or(Properties.YearOfBirth.gt(1970),  
  4. qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));  
  5. 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 的用户:

 

[java]  view plain copy
 
  1. Query query = userDao.queryBuilder().where(  
  2. Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970))  
  3. .build();  
  4. List joesOf1970 = query.list();  

 

 

使用query对象,可以查询

 

[java]  view plain copy
 
  1. query.setParameter(0, "Maria");  
  2. query.setParameter(1, 1977);  
  3. 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片段。

下面是一个笨拙的例子展示如果使用这种方式进行一个替代联合查询的子查询。

[java]  view plain copy
 
  1. Query query = userDao.queryBuilder().where(  
  2. new StringCondition("_ID IN " +  
  3. "(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

 

[java]  view plain copy
 
  1. 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。

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
 
  1. QueryBuilder.LOG_SQL = true;  
  2. QueryBuilder.LOG_VALUES = true;  

 

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

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

目录
相关文章
|
2月前
|
算法 JavaScript Android开发
|
2月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
3月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
149 1
|
4月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
452 3
|
13天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
39 3
|
13天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
42 3
|
13天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
54 2
|
27天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
184 15
|
20天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
27天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。