//此系列博文是《第一行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. python学习笔记-(二)python入门

    1.第一个python程序 1.1 直接打印输出 打开cmd,输入python进入到python交互式环境:(看到>>>是在Python交互式环境下:) 在python交互环境下输入 ...

  2. 处理字符串-String类和正则表达式

    ---基本元字符       . [] | () ---限定元字符      +至少匹配一个 *匹配0个或任意多个 ?匹配0个或1个(默认是贪心的)           当?在(*,+,?,{n},{ ...

  3. Linux常用服务部署与优化之Samba篇

    关于Samba的简介概述在此略过,开始搭建Samba服务. 1.安装Samba yum install -y samba samba-client 2.编辑Samba配置文件 首先共享一个目录,任何人 ...

  4. 初学Memcached安装及使用(CentOS7)

    1.yum install memcached安装memecached 2.chkconfig memcached on设置memcached开机启动 3.service memcached star ...

  5. 安装ubuntu和安装ubuntu后要安装的软件列表

    安装ubuntu 老毛桃进入win pe修复启动项 在win pe下面制作ubuntu的安装盘,只用的软件是ultraISO 参考博客下面的分区的那篇文章  http://jingyan.baidu. ...

  6. cx_freeze 把 .py 打包成 .exe

    1.安装 python-3.4.3 默认安装路径 C:\Python34 2.安装 cx_Freeze-4.3.3.win32-py3.4 3.运行 Python Version 3.4 regist ...

  7. APP抓链接工具(Fiddler版)

    1.下载Fiddler源代码: http://pan.baidu.com/s/1hqEUK0O 2.修改如下源代码: 3.运行截图:

  8. iOS版本控制git小结--yoowei

    # 显示隐藏文件 defaults write com.apple.finder AppleShowAllFiles Yes && killall Finder # 不显示隐藏文件 d ...

  9. Yii2 redis与cache

    原文地址:http://www.myexception.cn/php/1974979.html composer require yiisoft/yii2-redis 安装后使用超简单,打开 comm ...

  10. 缓存 HttpContext.Current.Cache和HttpRuntime.Cache的区别

    先看MSDN上的解释: HttpContext.Current.Cache:为当前 HTTP 请求获取Cache对象. HttpRuntime.Cache:获取当前应用程序的Cache.  我们再用. ...