使用LitePal查询数据
LitePal在查询方面提供了非常丰富的API,功能多种多样,基本上已经能够满足我们平时所有的查询需求了。不仅如此,LitePal在查询API的设计方面也是非常用心,摒弃了原生query()方法中繁琐的参数列表,而是改用了一种更为灵巧的方式——连缀查询。除此之外,LitePal查询的结果也不再返回Cursor对象,然后再由开发者自己去逐个取出,而是直接返回封装好的对象。这些改变都使得查询数据变得更加简单,也更加合理,那么下面我们就来完整地学习一下LitePal中查询数据的所有用法。
简单查询
比如说现在我们想实现一个最简单的功能,查询news表中id为1的这条记录,使用LitePal就可以这样写:
- News news = DataSupport.find(News.class, 1);
天呐!有没有觉得太轻松了?仅仅一行代码,就可以把news表中id为1的记录查出来了,而且结果还是自动封装到News对象里的,也不需要我们手动再从Cursor中去解析。如果是用原生的SQL语句,或者query()方法来写,至少要20行左右的代码才能完成同样的功能!
那我们先冷静一下,来分析分析这个find()方法。可以看到,它的参数列表也比较简单,只接收两个参数,第一个参数是一个泛型类,也就是说我们在这里指定什么类,返回的对象就是什么类,所以这里传入News.class,那么返回的对象也就是News了。第二个参数就更简单了,就是一个id值,如果想要查询id为1的记录就传1,想查id为2的记录就传2,以此类推。
本来一个还算颇为复杂的功能,通过LitePal之后就变得这么简单了!那么你可能已经迫不及待地想要学习更多LitePal中更多的查询用法了,别着急,我们一个个来看。
你也许遇到过以下场景,在某些情况下,你需要取出表中的第一条数据,那么传统的做法是怎么样的呢?在SQL语句中指定一个limit值,然后获取返回结果的第一条记录。但是在LitePal中不用这么麻烦,比如我们想要获取news表中的第一条数据,只需要这样写:
- News firstNews = DataSupport.findFirst(News.class);
那我们举一翻三,如果是想要获取News表中的最后一条数据该怎么写呢?同样简单,如下所示:
- News lastNews = DataSupport.findLast(News.class);
那么我们看到这里,目前都只是查询单条数据的功能,如果想要查询多条数据该怎么办呢?比如说,我们想把news表中id为1、3、5、7的数据都查出来,该怎么写呢?也许有的朋友会比较聪明,立马就想到可以一个个去查,就调用四次find()方法嘛,然后把1、3、5、7这四个id分别传进去不就可以了。没错,这样做完全是可以的,而且效率也并不低,但是LitePal给我们提供了一个更简便的方法——findAll()。这个方法的用法和find()方法是非常类似的,只不过它可以指定多个id,并且返回值也不再是一个泛型类对象,而是一个泛型类集合,如下所示:
- List<News> newsList = DataSupport.findAll(News.class, 1, 3, 5, 7);
虽说这个语法设计算是相当人性化,但是在有些场景或许不太适用,因为可能要你要查询的多个id已经封装到一个数组里了。那么没关系,findAll()方法也是接收数组参数的,所以说同样的功能你也可以这样写:
- long[] ids = new long[] { 1, 3, 5, 7 };
- List<News> newsList = DataSupport.findAll(News.class, ids);
- List<News> allNews = DataSupport.findAll(News.class);
而且大家不要以为刚才这些都只是findAll()的几个方法重载而已,实际上刚才我们的这几种用法都是调用的同一个findAll()方法!一个方法却能够实现多种不同的查询效果,并且语义性也很强,让人一看就能理解,这就是LitePal的查询艺术!
连缀查询
当然了,LitePal给我们提供的查询功能还远远不只这些,好戏还在后头。相信大家现在也已经发现了,我们目前的查询功能都是基于id来进行查询的,并不能随意地指定查询条件。那么怎样才能指定查询条件呢?让我们回想一下传统情况应该怎么做,query()方法中接收七个参数,其中第三和第四个参数就是用于指定查询条件的,然后其它几个参数都填null就可以了。但是呢,前面我们已经痛批过了这种写法,因为冗长的参数列表太过繁琐,那么LitePal又是怎么解决这个问题的呢?我们现在就来学习一下。
为了避免冗长的参数列表,LitePal采用了一种非常巧妙的解决方案,叫作连缀查询,这种查询很灵活,可以根据我们实际的查询需求来动态配置查询参数。 那这里举个简单的例子,比如我们想查询news表中所有评论数大于零的新闻,就可以这样写:
- List<News> newsList = DataSupport.where("commentcount > ?", "0").find(News.class);
接着我们在where()方法之后直接连缀了一个find()方法,然后在这里指定一个泛型类,表示用于查询哪张表。那么上面的一段代码,查询出的结果和如下SQL语句是相同的:
- select * from users where commentcount > 0;
但是这样会将news表中所有的列都查询出来,也许你并不需要那么多的数据,而是只要title和content这两列数据。那么也很简单,我们只要再增加一个连缀就行了,如下所示:
- List<News> newsList = DataSupport.select("title", "content")
- .where("commentcount > ?", "0").find(News.class);
可以看到,这里我们新增了一个select()方法,这个方法接收任意个字符串参数,每个参数要求对应一个列名,这样就只会把相应列的数据查询出来了,因此select()方法对应了一条SQL语句中的select部分。
那么上面的一段代码,查询出的结果和如下SQL语句是相同的:
- select title,content from users where commentcount > 0;
- List<News> newsList = DataSupport.select("title", "content")
- .where("commentcount > ?", "0")
- .order("publishdate desc").find(News.class);
那么上面的一段代码,查询出的结果和如下SQL语句是相同的:
- select title,content from users where commentcount > 0 order by publishdate desc;
- List<News> newsList = DataSupport.select("title", "content")
- .where("commentcount > ?", "0")
- .order("publishdate desc").limit(10).find(News.class);
那么上面的一段代码,查询出的结果和如下SQL语句是相同的:
- select title,content from users where commentcount > 0 order by publishdate desc limit 10;
- List<News> newsList = DataSupport.select("title", "content")
- .where("commentcount > ?", "0")
- .order("publishdate desc").limit(10).offset(10)
- .find(News.class);
那么上面的一段代码,查询出的结果和如下SQL语句是相同的:
- select title,content from users where commentcount > 0 order by publishdate desc limit 10,10;
激进查询
不过,上述我们的所有用法中,都只能是查询到指定表中的数据而已,关联表中数据是无法查到的,因为LitePal默认的模式就是懒查询,当然这也是推荐的查询方式。那么,如果你真的非常想要一次性将关联表中的数据也一起查询出来,当然也是可以的,LitePal中也支持激进查询的方式,下面我们就来一起看一下。
不知道你有没有发现,刚才我们所学的每一个类型的find()方法,都对应了一个带有isEager参数的方法重载,这个参数相信大家一看就明白是什么意思了,设置成true就表示激进查询,这样就会把关联表中的数据一起查询出来了。
比如说,我们想要查询news表中id为1的新闻,并且把这条新闻所对应的评论也一起查询出来,就可以这样写:
- News news = DataSupport.find(News.class, 1, true);
- List<Comment> commentList = news.getCommentList();
激进查询的用法非常简单,就只有这么多,其它find()方法也都是同样的用法,就不再重复介绍了。但是这种查询方式LitePal并不推荐,因为如果一旦关联表中的数据很多,查询速度可能就会非常慢。而且激进查询只能查询出指定表的关联表数据,但是没法继续迭代查询关联表的关联表数据。因此,这里我建议大家还是使用默认的懒加载更加合适,至于如何查询出关联表中的数据,其实只需要在模型类中做一点小修改就可以了。修改News类中的代码,如下所示:
- public class News extends DataSupport{
- ...
- public List<Comment> getComments() {
- return DataSupport.where("news_id = ?", String.valueOf(id)).find(Comment.class);
- }
- }
原生查询
相信你已经体会到,LitePal在查询方面提供的API已经相当丰富了。但是,也许你总会遇到一些千奇百怪的需求,可能使用LitePal提供的查询API无法完成这些需求。没有关系,因为即使使用了LitePal,你仍然可以使用原生的查询方式(SQL语句)来去查询数据。DataSuppport类中还提供了一个findBySQL()方法,使用这个方法就能通过原生的SQL语句方式来查询数据了,如下所示:
- Cursor cursor = DataSupport.findBySQL("select * from news where commentcount>?", "0");