//此系列博文是《第一行Android代码》的学习笔记,如有错漏,欢迎指正!

  之前我们为了保证数据库中的表是最新的,只是简单地在 onUpgrade()方法中删除掉了当前所有的表,然后强制重新执行了一遍 onCreate()方法。这种方式在产品的开发阶段确实可以用,但是当产品真正上线了之后就绝对不行了。想象以下场景,比如你编写的某个应用已经成功上线,并且还拥有了不错的下载量。现在由于添加新功能的原因,使得数据库也需要一起升级,然后用户更新了这个版本之后发现以前程序中存储的本地数据全部丢失了。

  所以我们需要进行一些合理的控制,保证在升级数据库的时候数据不会丢失。我们知道,每一个数据库版本都会对应一个版本号, 当指定的数据库版本号大于当前数据库版本号的时候, 就会进入到 onUpgrade()方法中去执行更新操作。所以我们可以在这里为每一个版本号赋予它各自改变的内容,然后在onUpgrade()方法中对当前数据库的版本号进行判断,再执行相应的改变就可以了。

  下面我们来进入实践:

一、Mission One: 在数据库中添加一张Book表

  这个比较简单,MyDatabaseHelper代码如下:

 public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public MyDatabaseHelper(Context context, String name, CursorFactory
factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

二、Mission Two:向数据库中再添加一张 Category表

 public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)"; public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
default:
}
}
}

 可以看到,在 onCreate()方法里我们新增了一条建表语句,然后又在 onUpgrade()方法中添加了一个 switch 判断,如果用户当前数据库的版本号是 1,就只会创建一张 Category表。这样当用户是直接安装的第二版的程序时,就会将两张表一起创建。而当用户是使用第二版的程序覆盖安装第一版的程序时,就会进入到升级数据库的操作中,此时由于 Book 表已经存在了,因此只需要创建一张 Category表即可。

三、Misson Three:在 Book表中添加一个 category_id 的字段

 public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table Book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text, "
+ "category_id integer)";
public static final String CREATE_CATEGORY = "create table Category ("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)"; public MyDatabaseHelper(Context context, String name,CursorFactory factory, int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (oldVersion) {
case 1:
db.execSQL(CREATE_CATEGORY);
case 2:
db.execSQL("alter table Book add column category_id integer");
default:
}
}
}

  首先我们在 Book 表的建表语句中添加了一个 category_id 列,这样当用户直接安装第三版的程序时,这个新增的列就已经自动添加成功了。然而,如果用户之前已经安装了某一版本的程序, 现在需要覆盖安装, 就会进入到升级数据库的操作中。 在 onUpgrade()方法里,我们添加了一个新的 case,如果当前数据库的版本号是 2,就会执行 alter命令来为Book 表新增一个 category_id 列。 

  这里有一点需要注意:switch 中每一个 case 的最后都是没有使用 break的。这样做的原因是为了保证在跨版本升级的时候, 每一次的数据库修改都能被全部执行到。比如用户当前是从第二版程序升级到第三版程序的,那么 case 2中的逻辑就会执行。而如果用户是直接从第一版程序升级到第三版程序的,那么 case 1 和 case 2 中的逻辑都会执行。使用这种方式来维护数据库的升级,不管版本怎样更新,都可以保证数据库的表结构是最新的,而且表中的数据也完全不会丢失了。

  

  //End.

Android学习笔记(十八)——再谈升级数据库的更多相关文章

  1. python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置

    python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...

  2. 【转】 Pro Android学习笔记(八八):了解Handler(2):什么是Handler

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 之前我们有一篇很好的博文<Andro ...

  3. 【转】 Pro Android学习笔记(八二):了解Package(1):包和进程

    文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ 在之前,我们已经学习了如何签发apk,见P ...

  4. 【转】 Pro Android学习笔记(八十):服务(5):访问远程服务

    目录(?)[-] Client的AIDL文件 Client的代码 建立连接 请求服务 断开连接 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://bl ...

  5. Android学习笔记(八)——四种基本布局

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! 布局是一种可用于放置很多控件的容器,它可以按照一定的规律调整内部控件的位置,或是嵌套子布局,从而编写出精美的界 ...

  6. (C/C++学习笔记) 十八. 继承和多态

    十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: cl ...

  7. 【转】 Pro Android学习笔记(八五):了解Package(4):lib项目

    目录(?)[-] 什么是lib项目 小例子 Lib的实现 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowing ...

  8. 【转】 Pro Android学习笔记(八九):了解Handler(3):延迟执行小例子

    目录(?)[-] 小例子 Handler的处理 Activity的代码片段 后台线程和UI的互动 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://b ...

  9. 【转】 Pro Android学习笔记(八六):了解Package(5):使用lib

    目录(?)[-] 在项目中使用lib 源代码 了解一些机制 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowin ...

随机推荐

  1. 安装Flask

    安装Flask步骤 输入网址https://bitbucket.org/pypa/setuptools](https://bitbucket.org/pypa/setuptools,回车后进入setu ...

  2. ajax请求下拉列表框的实现(面向对象封装类)

    实现的效果图 <?php class Car{ private $carColor; private $carType; public function __construct($carColo ...

  3. eclipse自动部署问题

    1. 使用myeclipse自动部署的方法(使用myeclipse 2015自动部署有问题,待解决)(换成2014的便可以自动部署): 1.Window->preferences->Mye ...

  4. MySQL学习笔记——多表连接和子查询

    多表连接查询 # 返回的是两张表的乘积 SELECT * FROM tb_emp,tb_dept SELECT COUNT(*) FROM tb_emp,tb_dept # 标准写法,每个数据库都能这 ...

  5. Sky Box

    http://www.keithlantz.net/2011/10/rendering-a-skybox-using-a-cube-map-with-opengl-and-glsl/ http://o ...

  6. jquery左边滚动,完毕后跳转回来

    代码如下 function in_scroll(){ $liW = ; $num = $(".in-cy li").size(); $ulW = $liW*$num; $(&quo ...

  7. Auto generating Entity classes with xsd.exe for XML Serialization and De-Serialization

    More info here: http://blogs.msdn.com/b/yojoshi/archive/2011/05/14/xml-serialization-and-deserializa ...

  8. Autofac和DynamicProxy2搭配实现Aop动手训练

    http://www.cnblogs.com/zhengwl/p/5433181.html Aop含义:aspect-oriented programming 实现工具介绍 Autofac是一个比较流 ...

  9. Effective Objective-C 2.0 — 第10条:在既有类中使用关联对象存放自定义数据

    可以通过“关联对象”机制来把两个对象连起来 定义关联对象时可指定内存管理语义,用以模仿定义属性时所采用的“拥有关系”与“非拥有关系” 只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于 ...

  10. jquery取消选择select下拉框

    有三个select下拉框一个大类,两个小类隐藏,需要在选择大类的时候,小类显示同时清除另外的小类选择的项这需求有点儿.......... 下面是三个select: <select name=&q ...