zoukankan      html  css  js  c++  java
  • Android笔记——数据库升级与降级

    一、概述

          SQLite是Android内置的一个很小的关系型数据库。SQLiteOpenHelper是一个用来辅助管理数据库创建和版本升级问题的抽象类。我们可以继承这个抽象类,实现它的一些方法来对数据库进行自定义操作。下面两个方法必须重写:

    public void onCreate(SQLiteDatabase db)

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

    SQLiteOpenHelper里的onCreate执行:

    1.只在数据库还没有建立时运行一次.如果数据库已经存在了,就不再执行onCreate方法,即在第一次打开数据库的时候才会执行

    2.在清除数据之后再次运行-->打开数据库,这个方法会执行

    3.没有清除数据,不会执行这个方法

    4.数据库升级的时候这个方法不会执行,想执行需要先删除数据,再调用onCreate方法

    onUpgrade的执行:

    1.第一次创建数据库的时候,这个方法不会执行

    2.清除数据后再次运行(相当于第一次创建)这个方法不会执行

    3.数据库已经存在,而且版本升高的时候,这个方法才会调用,但不会自动执行onCreate

    onDowngrade的执行:

    1.执行数据库的降级操作

    2.只有新版本比旧版本低的时候才会执行

    3.如果不执行降级操作,会抛出异常

     

    二、升级数据库

     1 public class MyDatabaseHelper extends SQLiteOpenHelper{
     2 
     3     public static final String CREATE_BOOK="create table BOOK("
     4             +"id integer primary key autoincrement,"
     5             +"author text,"
     6             +"price real,"
     7             +"pages integer,"
     8             +"name text,"
     9             +"category_id integer)";
    10     public static final String CREATE_CATECORY="create table Category("
    11             +"id integer primary key autoincrement,"
    12             +"category_name text"
    13             +"category_code integer)";
    14     private Context mContext;
    15     public MyDatabaseHelper(Context context, String name,
    16             CursorFactory factory, int version) {
    17         super(context, name, factory, version);
    18         mContext=context;
    19     }
    20 
    21     @Override//创建数据库是调用
    22     public void onCreate(SQLiteDatabase db) {
    23         db.execSQL(CREATE_BOOK);
    24         db.execSQL(CREATE_CATECORY);
    25         Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    26     }
    27 
    28     @Override//版本更新时调用
    29     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    30         //Log.i("db","测试");
    31         switch(oldVersion){
    32         case 1://版本1升级版本二是执行上面的创建表的语句
    33             db.execSQL(CREATE_CATECORY);
    34             Log.i("db","创建成功表Category成功");
    35         case 2://版本2升级版本3时执行向Book表中添加一个字段
    36             db.execSQL("alter table Book add column category_id integer");
    37             Log.i("db","添加字段成功");
    38             default:
    39         }
    40     }
    41 }

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

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

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

    三、降级

     1 private static final String DB_NAME = "mydata.db"; // 数据库名称
     2     private static final int version = 2; // 数据库版本
     3 
     4     public MyDatabaseOpenHelper(Context context) {
     5         super(context, DB_NAME, null, version);
     6     }
     7 
     8     // 问题:什么时候执行
     9     // 没有前生
    10     @Override
    11     public void onCreate(SQLiteDatabase db) {
    12         // TODO Auto-generated method stub
    13         // 编写【从0开始到最新状态】建表语句
    14         Log.i("hi", "没有数据库,创建数据库,创建v2.0成功");
    15         String sql_message = "create table t_message (id int primary key,tou1  varchar(50),userName varchar(50),lastMessage varchar(50),datetime  varchar(50))";
    16         String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1')";
    17         String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1')";
    18         String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1')";
    19         db.execSQL(sql_message);
    20         db.execSQL(sql_init_1);
    21         db.execSQL(sql_init_2);
    22         db.execSQL(sql_init_3);
    23 
    24     }
    25 
    26     // v2.0 现在进行时
    27     @Override
    28     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    29         
    30         if (oldVersion == 2){
    31             String sql_upgrade_1 = "alter table t_message add column isdel bit default 0";
    32             db.execSQL(sql_upgrade_1);
    33             Log.i("db", "从2到3,升级成功!");
    34         }
    35 //        
    36         if (oldVersion == 1) {
    37             Log.i("db", "从1到3,升级成功!");
    38             String sql_upgrade_1 = "alter table t_message add column isdel bit default 0";
    39             db.execSQL(sql_upgrade_1);
    40             String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1',0)";
    41             String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1',0)";
    42             String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1',0)";
    43             db.execSQL(sql_init_1);
    44             db.execSQL(sql_init_2);
    45             db.execSQL(sql_init_3);
    46             Log.i("db", "从1到3,升级成功!");
    47         }
    48     }
     1 /* 模拟从3.0 降低会2.0 */
     2     @Override
     3     public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     4         //正常来讲大于2.0的,应该有t_message 这张表,且2.0有的字段,3.0都有
     5         try {
     6             //第一、先把t_message 未来的表,改名
     7             String rename_sql = "alter table t_message rename to t_message_bak";
     8             db.execSQL(rename_sql);
     9             Log.i("down", "1.改名成功");
    10             //第二、建立2.0的表结构
    11             String sql_message = "create table t_message (id int primary key,tou1  varchar(50),userName varchar(50),lastMessage varchar(50),datetime  varchar(50))";
    12             db.execSQL(sql_message);
    13             Log.i("down", "2.建立2.0表结构成功");
    14             //第三、把备份的数据,copy到 新建的2.0的表
    15             String sql_copy = "insert into t_message select id,tou1,userName,lastMessage,datetime from t_message_bak";
    16             db.execSQL(sql_copy);
    17             Log.i("down", "3.copy到用户数据到 2.0的表");
    18             //第四、把备份表drop掉
    19             String drop_sql = "drop table if exists t_message_bak";
    20             db.execSQL(drop_sql);
    21             Log.i("down", "4.把备份表drop掉");
    22             
    23         } catch (Exception e) {
    24             //失败
    25             Log.i("hi", "降级失败,重新建立");
    26             String sql_drop_old_table = "drop table if exists t_message";
    27             String sql_message = "create table t_message (id int primary key,tou1  varchar(50),userName varchar(50),lastMessage varchar(50),datetime  varchar(50))";
    28             String sql_init_1 = "insert into t_message values (1,'abc','abc1','abcd1','hi1')";
    29             String sql_init_2 = "insert into t_message values (2,'abc','abc2','abcd2','hi1')";
    30             String sql_init_3 = "insert into t_message values (3,'abc','abc2','abcd2','hi1')";
    31             db.execSQL(sql_drop_old_table);
    32             db.execSQL(sql_message);
    33             db.execSQL(sql_init_1);
    34             db.execSQL(sql_init_2);
    35             db.execSQL(sql_init_3);
    36         }
    37     }

     代码说明,这就不说了!

  • 相关阅读:
    11
    关于一些问题的解决办法[记录]TF400017
    jdbc一次性采集mysql和oracle的海量数据,5000W+为例
    java 读取配置文件类
    Apache Thrift
    Runtime.getRuntime().exec 类 防止阻塞
    angularjs select
    angularjs
    简单的搭mysql开发环境
    运用java反射
  • 原文地址:https://www.cnblogs.com/wugu-ren/p/6118151.html
Copyright © 2011-2022 走看看