Android数据库高手秘籍(三)——使用LitePal升级表

转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/39151617


在上一篇文章中,我们学习了LitePal的基本使用方法,体验了使用框架来进行创建表操作的便利。然而大家都知道,创建表仅仅是数据库操作中最主要的一步而已。我们在一開始创建的表结构,随着需求的变更。到了后期是极有可能须要改动的。

因此。升级表的操作对于不论什么一个项目也是至关重要的。那么今天我们就一起来学习一下,在Android传统开发其中升级表的方式,以及使用LitePal来进行升级表操作的使用方法。

假设你还没有看过前一篇文章,建议先去參考一下 Android数据库高手秘籍(二)——创建表和LitePal的基本使用方法 。


LitePal的项目地址是:https://github.com/LitePalFramework/LitePal


传统的升级表方式


上一篇文章中我们借助MySQLiteHelper已经创建好了news这张表,这也是demo.db这个数据库的第一个版本号。然而,如今需求发生了变更,我们的软件除了能看新闻之外。还应该同意用户评论,所以这时就须要对数据库进行升级,加入一个comment表。


该怎么做呢?加入一个comment表的建表语句。然后在onCreate()方法中去运行它?没错,这样的话,两张表就会同一时候创建了,代码例如以下所看到的:

public class MySQLiteHelper extends SQLiteOpenHelper {
	
	public static final String CREATE_NEWS = "create table news ("
			+ "id integer primary key autoincrement, "
			+ "title text, "
			+ "content text, "
			+ "publishdate integer,"
			+ "commentcount integer)";
	
	public static final String CREATE_COMMENT = "create table comment ("
			+ "id integer primary key autoincrement, "
			+ "content text)";

	public MySQLiteHelper(Context context, String name, CursorFactory factory,
			int version) {
		super(context, name, factory, version);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_NEWS);
		db.execSQL(CREATE_COMMENT);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	}

}

这对于第一次安装我们软件的用户来说是全然能够正常工作的,可是假设有的用户已经安装过上一版的软件,那么非常遗憾。comment表是创建不出来的。由于之前数据库就已经创建过了。onCreate()方法是不会又一次运行的。


对于这样的情况我们就要用升级的方式来攻克了,看到MySQLiteHelper构造方法中的第四个參数了吗,这个就是数据库版本号号的标识。每当版本号号添加的时候就会调用onUpgrade()方法,我们仅仅须要在这里处理升级表的操作即可了。

比較简单粗暴的方式是将数据库中现有的全部表都删除掉。然后又一次创建,代码例如以下所看到的:

public class MySQLiteHelper extends SQLiteOpenHelper {
	
	......

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_NEWS);
		db.execSQL(CREATE_COMMENT);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("drop table if exists news");
		onCreate(db);
	}

}

能够看到,当数据库升级的时候,我们先把news表删除掉,然后又一次运行了一次onCreate()方法。这样就保证数据库中的表都是最新的了。


可是。假设news表中本来已经有数据了。使用这样的方式升级的话,就会导致表中的数据全部丢失。所以这并非一种值得推荐的升级方法。

那么更好的升级方法是什么样的呢?这就略微有些复杂了。须要在onUpgrade()方法中依据版本号号加入详细的升级逻辑。我们来试试来吧。比方之前的数据库版本号号是1。那么在onUpgrade()方法中就能够这样写:

public class MySQLiteHelper extends SQLiteOpenHelper {

	......

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_NEWS);
		db.execSQL(CREATE_COMMENT);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		switch (oldVersion) {
		case 1:
			db.execSQL(CREATE_COMMENT);
		default:
		}
	}

}
能够看到,这里在onUpgrade()方法中加入了一个switch推断,假设oldVersion等于1。就再创建一个comment表。如今仅仅须要调用例如以下代码,表就能够得到创建或升级了:
SQLiteOpenHelper dbHelper = new MySQLiteHelper(this, "demo.db", null, 2);
SQLiteDatabase db = dbHelper.getWritableDatabase();

这里我们将版本号号加1,假设用户是从旧版本号升级过来的。就会新增一个comment表。而假设用户是直接安装的新版本号。就会在onCreate()方法中把两个表一起创建了。


OK。如今软件的第二版本号也公布出去了,可是就在公布不久之后,突然发现comment表中少了一个字段,我们并没有记录评论公布的时间。没办法,仅仅好在第三版中修复这个问题了。那我们该怎么样去加入这个字段呢?主要须要改动comment表的建表语句。以及onUpgrade()方法中的逻辑。代码例如以下所看到的:

public class MySQLiteHelper extends SQLiteOpenHelper {

	......

	public static final String CREATE_COMMENT = "create table comment ("
			+ "id integer primary key autoincrement, " 
			+ "content text, " 
			+ "publishdate integer)";

	......

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		switch (oldVersion) {
		case 1:
			db.execSQL(CREATE_COMMENT);
			break;
		case 2:
			db.execSQL("alter table comment add column publishdate integer");
			break;
		default:
		}
	}

}

能够看到,在建表语句其中我们新增了publishdate这一列。这样当运行onCreate()方法去创建表的时候。comment表中就会有这一列了。

那么假设是从旧版本号升级过来的呢?也没有问题,我们在onUpgrade()方法中已经把升级逻辑都处理好了。当oldVersion等于2的时候,会运行alter语句来加入publishdate这一列。

如今调用以下代码来创建或升级数据库:

SQLiteOpenHelper dbHelper = new MySQLiteHelper(this, "demo.db", null, 3);
SQLiteDatabase db = dbHelper.getWritableDatabase();

将数据库版本号号设置成3,这样就能够保证数据库中的表又是最新的了。


如今我们已经学习了新增表和新增列这两种升级方式。那么假设是某张表中的某一列已经没实用了。我想把这一列删除掉该怎么写呢?非常遗憾,SQLite并不支持删除列的功能。对于这情况。多数软件採取的作法是无视它。反正以后也用不到它了,留着也占不了什么空间,所以针对于这样的需求,确实没什么简单的解决的方法。


这大概就是传统开发其中升级数据库表的方式了,虽说能写出这样的代码表示你已经对数据库的升级操作理解的比較清楚了,但随着版本号越来越多,onUpgrade()方法中的逻辑也会变得愈发复杂,略微一不留神。或许就会产生错误。因此,假设能让代码自己主动控制升级逻辑,而不是由人工来管理,那就是再好只是了,那么以下我们就来学习一下如何使用LitePal来进行升级表的操作。


使用LitePal升级表


通过上一篇文章的学习,我们已经知道LitePal是一款ORM模式的框架了,已经熟悉创建表流程的你,相信对于升级表也一定会轻车熟路的。那么为了模仿传统升级表方式中的需求,如今我们也须要创建一张comment表。

第一步该怎么办呢?相信你或许早就已经猜到了,那当然是先创建一个Comment类了。例如以下所看到的:

package com.example.databasetest.model;

public class Comment {
	
	private int id;
	
	private String content;
	
	// 自己主动生成get、set方法 
	...
}

OK,Comment类中有id和content这两个字段,也就意味着comment表中会有id和content这两列。


接着改动litepal.xml中的配置。在映射列表中新增Cooment类,并将版本号号加1,例如以下所看到的:

<?

xml version="1.0" encoding="utf-8"?> <litepal> <dbname value="demo" ></dbname> <version value="2" ></version> <list> <mapping class="com.example.databasetest.model.News"></mapping> <mapping class="com.example.databasetest.model.Comment"></mapping> </list> </litepal>

没错。就是这么简单。仅仅两步,升级的操作就已经完毕了,如今我们仅仅须要操作一下数据库,comment表就会自己主动生成了,例如以下所看到的:
SQLiteDatabase db = Connector.getDatabase();

那么我们还是通过.table命令来查看一下结果。例如以下图所看到的:




OK。comment表已经出来了,那么再通过pragma命令来查看一下它的表结构吧:




没有问题,comment表中眼下有id和content这两列,和Comment模型类中的字段是保持一致的。


那么如今又来了新的需求,须要在comment表中加入一个publishdate列,该怎么办呢?不用怀疑,跟着你的直觉走,相信你已经猜到应该在Comment类中加入这样一个字段了吧,例如以下所看到的:

public class Comment {
	
	private int id;
	
	private String content;
	
	private Date publishDate;
	
	// 自己主动生成get、set方法 
	...
}
然后呢?剩下的操作已经非常easy了。仅仅须要在litepal.xml中对版本号号加1即可了。例如以下所看到的:
<litepal>
    <dbname value="demo" ></dbname>

    <version value="3" ></version>
    ...
</litepal>

这样当我们下一次操作数据库的时候,publishdate列就应该会自己主动加入到comment表中。

调用Connector.getDatabase()方法。然后又一次查询comment表结构。例如以下所看到的:




能够看到。publishdate这一列确实已经成功加入到comment表中了。


通过这两种升级方式的对照。相信你已经充分体会到了使用LitePal进行升级表操作所带来的便利了吧。我们不须要去编写不论什么与升级相关的逻辑。也不须要关心程序是从哪个版本号升级过来的。唯一要做的就是确定好最新的Model结构是什么样的,然后将litepal.xml中的版本号号加1,全部的升级逻辑就都会自己主动完毕了。

LitePal确实将数据库表的升级操作变得极度简单,使非常多程序猿能够从维护数据库表升级的困扰中解脱出来。


然而。LitePal却明显做到了更好。前面我们提到过关于删除列的问题。终于的结论是无法解决,由于SQLite是不支持删除列的命令的。

可是假设使用LitePal,这一问题就能够简单地解决掉。比方说publishdate这一列我们又不想要了。那么仅仅须要在Comment类中把它删除掉,然后将版本号号加1,下次操作数据库的时候这个列就会不见了。


那么有的朋友可能会问了。不是说SQLite不支持删除列的命令吗?那LitePal又是如何做到的呢?事实上LitePal并没有删除不论什么一列,它仅仅是先将comment表重命名成一个暂时表,然后依据最新的Comment类的结构生成一个新的comment表,再把暂时表中除了publishdate之外的数据拷贝到新的表中,最后把暂时表删掉。因此,看上去的效果好像是做到了删除列的功能。


这也是使用框架的优点。假设没有框架的帮助,我们显然不会为了删除一个列而大废周章地去写这么多的代码。而使用框架的话。详细的实现逻辑我们已经不用再关心。仅仅须要控制好模型类的数据结构就能够了。


另外。假设你想删除某一张表的话。操作也非常easy,在litepal.xml中的映射列表中将对应的类删除。表自然也就不存在了。其他的一些升级操作也都是相似的,相信你已经能举一反三,这里就不再赘述了。


好了,今天对LitePal的介绍就到这里吧,下篇文章其中我们会学习使用LitePal来进行表关联的操作,感兴趣的朋友请继续阅读 Android数据库高手秘籍(四)——使用LitePal建立表关联 。


关注我的技术公众号,每天都有优质技术文章推送。关注我的娱乐公众号,工作、学习累了的时候放松一下自己。

微信扫一扫下方二维码即可关注:

        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值