LitePal的存储操作
传统的存储数据方式
其实最传统的存储数据方式肯定是通过SQL语句拼接字符串来进行存储的,不过这种方式有点过于“传统”了,今天我们在这里就不讨论这种情况。实际上,Android专门提供了一种用于存储数据的简便方法,使得我们不用编写SQL语句就可以执行存储操作。下面来看一下SQLiteDatabase中的insert()方法:
public long insert(String table, String nullColumnHack, ContentValues values)
可以看到,insert方法接收三个参数,第一个参数是表名,第二个参数通常都用不到,直接传null,第三个参数则是一个封装了待存储数据的ContentValues对象。因此,比如说我们想往news表中插入一条新闻,就可以这样写:
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("title", "这是一条新闻标题");
values.put("content", "这是一条新闻内容");
values.put("publishdate", System.currentTimeMillis());
long id = db.insert("news", null, values);
其中,调用ContentValues的put()方法来添加待存储数据,put()方法接收两个参数,第一个参数是数据库表中对应的列名,第二个参数就是要存储的值,最后调用一下insert()方法,这条新闻就会插入到news表当中了,并且该数据行对应的id会作为返回值进行返回。
用法很简单是吗?确实,比起直接使用SQL语句,SQLiteDatabase中提供的insert()方法的确简单了很多。但insert()方法也并非是那么的完美,它还是有很多不方便的地方的,比如说没有考虑表关联的情况,我们需要手动对关联表的外键进行存储。再比如说,没有提供批量存储的功能,当我们有一个集合的数据需要存储时,需要通过循环来遍历这个集合,然后一次次地调用insert()方法来插入数据。
好了,那么关于传统存储数据的用法就简单介绍到这里,因为确实没什么的更多的用法了,并且它也不是我们今天的主角。接下来,就让我们看一看今天的惊喜,学习如何使用LitePal来进行数据库存储的操作。
使用LitePal存储数据
LitePal中与存储相关的API其实并不多,但用法还是颇为丰富的,而且比起传统的insert()方法,使用LitePal来存储数据可以简单到让你惊叹的地步,那么今天我们就来完整地学习一下LitePal存储数据的所有用法。
在前面几篇文章当中,我们在项目里已经建好了News、Comment、Introduction、Category这几个实体类,通过这些实体类,LitePal就可以把相应的表自动创建出来。现在来观察这几个实体类,我们发现这几个类都是没有继承结构的。没错,因为LitePal进行表管理操作时不需要这些实体类有任何的继承结构,当时为了简单起见就没有写。但是进行CRUD操作时就不行了,LitePal要求所有的实体类都要继承自DataSupport这个类,因此这里我们就要把继承结构给加上才行。修改News类的代码,如下所示:
public class News extends DataSupport{ ...... // 自动生成get、set方法
}
可以看到,这里只是让News类继承自了DataSupport,其它什么都没有改变。另外几个Comment、Introduction、Category类也使用同样的改法,这里就不一一演示了。
继承了DataSupport类之后,这些实体类就拥有了进行CRUD操作的能力,那么比如想要存储一条数据到news表当中,就可以这样写:
News news = new News();
news.setTitle("这是一条新闻标题");
news.setContent("这是一条新闻内容");
news.setPublishDate(new Date());
news.save();
怎么样?是不是非常简单,不需要SQLiteDatabase,不需要ContentValues,不需要通过列名组装数据,甚至不需要指定表名,只需要new出一个News对象,然后把要存储的数据通过setter方法传入,最后调用一下save()方法就好了,而这个save()方法自然就是从DataSupport类中继承而来的了。
除此之外,save()方法还是有返回值的,我们可以根据返回值来判断存储是否成功,比如说这样写:
if (news.save()) {
Toast.makeText(context, "存储成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "存储失败", Toast.LENGTH_SHORT).show();
}
可以看出,save()方法返回的是一个布尔值,用于表示存储成功还是失败,但同时也说明这个方法是不会抛出异常的。有些朋友希望如果存储失败的话就抛出异常,而不是返回一个false,那就可以使用saveThrows()方法来代替,如下所示:
News news = new News();
news.setTitle("这是一条新闻标题");
news.setContent("这是一条新闻内容");
news.setPublishDate(new Date());
news.saveThrows();
使用saveThrows()方法来存储数据,一旦存储失败就会抛出一个DataSupportException异常,我们可以通过对这个异常进行捕获来处理存储失败的情况。
那有些细心的朋友可能已经注意到,使用的insert()方法来存储数据时是有返回值的,返回的是插入行对应的id。但LitePal中的save()方法返回的是布尔值,那么我们怎样才能拿到存储成功之后这条数据对应的id呢?对此,LitePal使用了一种非常巧妙的做法,还记得我们在每个实体类中都定义了一个id字段吗?当调用save()方法或saveThrows()方法存储成功之后,LitePal会自动将该条数据对应的id赋值到实体类的id字段上。让我们来做个试验吧,代码如下所示:
News news = new News();
news.setTitle("这是一条新闻标题");
news.setContent("这是一条新闻内容");
news.setPublishDate(new Date());
Log.d("TAG", "news id is " + news.getId());
news.save();
Log.d("TAG", "news id is " + news.getId());
在save之前打印一下news的id,在save之后再打印一次,现在运行一下,打印结果如下所示:
OK,在save之前打印的id是0,说明此时id这个字段还没有被赋值,在save之后打印的id是1,说明此时id已经被赋值了。那么我们再到数据库表中再查看一下这条记录到底有没有存储成功吧,如下图所示:
可以看到,这条新闻确实已经存储成功了,并且对应的id正是1,和我们前面打印的结果是一致的。
不过LitePal的存储功能显示不仅仅只有这些用法,事实上,LitePal在存储数据的时候默默帮我们做了很多的事情,比如多个实体类之间有关联关系的话,我们不需要考虑在存储数据的时候怎么去建立数据与数据之间的关联,因为LitePal一切都帮我们做好了。
还是通过一个例子来看一下吧,Comment和News之间是多对一的关系,一条News中是可以包含多条评论的,因此我们就可以这样写:
Comment comment1 = new Comment();
comment1.setContent("好评!");
comment1.setPublishDate(new Date());
comment1.save();
Comment comment2 = new Comment();
comment2.setContent("赞一个");
comment2.setPublishDate(new Date());
comment2.save();
News news = new News();
news.getCommentList().add(comment1);
news.getCommentList().add(comment2);
news.setTitle("第二条新闻标题");
news.setContent("第二条新闻内容");
news.setPublishDate(new Date());
news.setCommentCount(news.getCommentList().size());
news.save();
可以看到,这里先是存储了一条comment1数据,然后存储一条comment2数据,接着在存储News之前先把刚才的两个Comment对象添加到了News的commentList列表当中,这样就表示这两条Comment是属于这个News对象的,最后再把News存储到数据库中,这样它们之间的关联关系就会自动建立了。让我们查看数据库表检查一下吧,首先看一下news表,如下所示:
OK,第二条新闻已经成功存储到news表中了,这条新闻的id是2。那么从哪里可以看出来关联关系呢?我们在上一篇文章中学过,多对一关联的时候,外键是存放在多方的,因此关联关系我们要到comment表中去查看,如下所示:
可以看到,两条评论都已经成功存储到comment表中了,并且这两条评论的news_id都是2,说明它们是属于第二条新闻的。怎么样,仅仅是在存储数据之前建立好实体类之间的关系,再调用一下save()方法,那么数据之间的关联关系就会自动建立了,是不是非常简单?上面的代码只是多对一情况的一种用法,还有一对一和多对多的情况,其实用法都是差不多的,相信你已经能举一反三了。
另外,LitePal对集合数据的存储还专门提供了一个方法,比如说我们有一个News集合,那么应该怎样去存储这个集合中的每条News呢?传统情况下可以这样写:
List<News> newsList;
...
for (News news : newsList) {
news.save();
}
通过一个循环来遍历出这个集合中的每一个News对象,然后逐个调用save()方法。这样的写法当然是可以的,但是效率会比较低,因为调用save()方法的时候除了会执行存储操作之外,还会去分析News类的关联关系,那么每次循环都去重新分析一遍关联关系显然是比较耗时的。因此,LitePal提供了一个saveAll()方法,专门用于存储集合数据的,用法如下所示:
List<News> newsList;
...
DataSupport.saveAll(newsList);
saveAll()方法接收一个Collection集合参数,只要把待存储的集合数据传入即可。这个方法可以完成和上面一段代码完全一样的功能,但效率却会高得多,而且写法也更加简单。
LitePal的存储操作的更多相关文章
- Android数据库高手秘籍(五)——LitePal的存储操作
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/39345833 经过前面几篇文章的学习,我们已经把LitePal的表管理模块的功能都 ...
- xiv存储操作
XIV存储操作维护手册 二○一二年七月 目录 1. 存储划分... 3 1.1. 定义Storage Pool 3 1.2. ...
- 爬虫--Scrapy-持久化存储操作
总体概况 持久化存储操作: a. 磁盘文件 a) 基于终端指令 i. 保证parse方法返回一个可迭代类型的对象(存储解析到的页面内容) ii. 使用终端指令完成数据存储到制定磁盘文件中的操作 1. ...
- Linux下IP SAN共享存储操作记录
一.简单介绍SAN,即存储区域网络(storage area network and SAN protocols),它是一种高速网络实现计算机与存储系统之间的数据传输.常见的分类是FC-SAN和IP- ...
- 爬虫--Scrapy-持久化存储操作2
1.管道的高级操作 将爬取到的数据值分别存储到本地磁盘.redis数据库.mysql数据. 需求:将爬取到的数据值分别存储到本地磁盘.redis数据库.mysql数据. 1.需要在管道文件中编写对应平 ...
- 利用Object.defineProperty 简化 Chrome插件本地存储操作
通常谷歌插件本地存储写法很别扭☹,如 chrome.storage.sync.get(null,function(data){ //todo console.log(data); }); 如果get ...
- Python使用cx_Oracle模块操作Oracle数据库--通过sql语句和存储操作
https://www.jb51.net/article/125160.htm?utm_medium=referral Python使用cx_Oracle调用Oracle存储过程的方法示例 http ...
- android 数据存储操作之SQLite
一. SQLite介绍 SQLite是android内置的一个很小的关系型数据库. 二. SQLiteOpenHelper的使用方法 ①SQLiteOpenHelper是一个辅助类来管理数据库的创建和 ...
- Win7 文件加密存储操作后,如何在事后备份证书、秘钥
这个密钥的特点是只有在此系统下用此账户才可以修改,即便是你用此账户设置加密后删除此账户再重新建一个同名的账户依然无法修改.而且此密钥无法破解.所以一旦加密后,重装系统或者更换账户就无法修改了.唯一的办 ...
随机推荐
- 分布式Id - redis方式
本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案之外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来说是我们常用并接触比较多的,因此主要 ...
- Android中px dpi dip density densityDpi 的相关说明
转自:http://www.cnblogs.com/wader2011/archive/2011/11/29/2267490.html 概念解释 名词 解释 Px (Pixel像素) 不同设备显示效果 ...
- 垃圾佬的旅游III(Hash + 暴力)
题目链接:http://120.78.128.11/Problem.jsp?pid=3445 最开始的思路就是直接暴力求解,先把所有的数值两两存入结构体,再从小到大枚举.用二分的思路去判断数值以及出现 ...
- 提供就医帮助的安卓APP
首先 这是我们团队第一次开发安卓APP,也是我 个人第一个开发项目APP,俗话说:“万事开头难”.所以对于新手的我们来说,做好开发前的准备至关重要.凡事预则立不预则废! 首先我们团队这次开发的提供就医 ...
- charles 自动存储/auto_save
本文参考:charles 自动存储 自动保存工具 auto_save "自动保存"工具会在你设定的间隔后,自动保存并清除抓取到的内容.假设你设置了3分钟,则每隔三分钟会保存一次, ...
- 数据库占用CPU过高,性能分析与调优
一.使用 dstat -tcdlmnsygr --disk-util 查看当前系统资源使用状况,当前cpu使用率100% 二.使用TOP命令 查看当前占用CPU进程,可以看到当前占用CPU进程最高的是 ...
- JavaScript之对象Array
数组Array是JavaScript中最常用的类型之一,同一数组中可以保存任意类型的数据,并且它的长度是动态的,会随着数组中数据的加减自动变化.每个数组都有一个表示其长度(数组元素的个数)的lengt ...
- .Net Core 3.0 gRPC部署问题解决
前言 .Net Core3.0终于如约而至的来了.在3.0中增加了许多东西.也有了许多的变化.今天我们看的就是在3.0中使用gRPC并遇到的问题.gRPC现在可以非常方便简洁的在.Net Core中使 ...
- python库之turtle(图形绘制) 开启新的快乐源泉
相信有不少人学习python 都是听了老前辈的推荐 “学python好,python有趣的代码多” 比如说画一只小狮子 这就是今天想要介绍的绘制图形库-turtle 如果也想这样画一只小狮子,或者其他 ...
- FIT文件CRC校验
校验FIT文件CRC代码做个记录,分为两步先校验头部然后再校验整个FIT文件.校验头部不是必需的看个人需要吧.为了偷懒使用Okio库,还有计算CRC的时候用的Garmin的FitSDK. public ...