Android菜鸟成长记11 -- sqlite数据库的设计和升降级

Google为Andriod的较大的数据处理提供了SQLite,他在数据存储、管理、维护等各方面都相当出色,功能也非常的强大。SQLite具备下列特点:
  1.轻量级
  使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。
  2.独立性
  SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。
  3.隔离性
  SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
  4.跨平台
  SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android。
  5.多语言接口
  SQLite 数据库支持多语言编程接口。
  6.安全性

  SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据。

创建数据库的方法,在android开发中,要想为项目创建数据库,必须继承SQLiteOpenHelper类

  首先,我们创建一个类来继承SQLiteOpenHelper类

  

 1 package com.example.sqlltetest;
 2
 3 import android.content.Context;
 4 import android.database.DatabaseErrorHandler;
 5 import android.database.sqlite.SQLiteDatabase;
 6 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 7 import android.database.sqlite.SQLiteOpenHelper;
 8 import android.util.Log;
 9
10 public class MyDataBaseOpenOrCreate extends SQLiteOpenHelper{
11
12     private static final String DB_NAME = "mydata.db"; // 数据库名称
13     private static final int version = 1; // 数据库版本
14
15
16
17     public MyDataBaseOpenOrCreate(Context context) {
18         super(context, DB_NAME, null, version);
19     }
20
21     @Override
22     public void onCreate(SQLiteDatabase db) {
23         Log.i("tag", "欢迎你的加入");
24         String sql_table = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))";
25         db.execSQL(sql_table);
26         String sql_1 = "insert into t_student(stuName) values (‘小波‘)";
27         String sql_2 = "insert into t_student(stuName) values (‘小小波‘)";
28         String sql_3 = "insert into t_student(stuName) values (‘小小小波‘)";
29         db.execSQL(sql_1);
30         db.execSQL(sql_2);
31         db.execSQL(sql_3);
32     }
33
34     @Override
35     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newversion) {
36
37     }
38
39 }

如过你的项目没有数据库的化,他会走onCreate()的方法,如果有的话,他是不会走onCreate()方法的,至于onUpgrade()方法,是当你数据库发生更新时触发的,上面我们通过日志打印来测试

那么我们创建一个实体类来关联数据库

 1 package com.example.entity;
 2
 3 public class student {
 4
 5     private String stuid;
 6     private String stuName;
 7     private int age;//为了升级做准备的
 8     public String getStuid() {
 9         return stuid;
10     }
11     public void setStuid(String stuid) {
12         this.stuid = stuid;
13     }
14     public String getStuName() {
15         return stuName;
16     }
17     public void setStuName(String stuName) {
18         this.stuName = stuName;
19     }
20     public int getAge() {
21         return age;
22     }
23     public void setAge(int age) {
24         this.age = age;
25     }
26
27 }

后面我们直接通过程序来显示数据

  

 1 package com.example.sqlltetest;
 2
 3 import java.util.*;
 4
 5 import com.example.entity.student;
 6
 7 import android.app.Activity;
 8 import android.database.Cursor;
 9 import android.database.sqlite.SQLiteDatabase;
10 import android.os.Bundle;
11 import android.util.Log;
12 import android.view.LayoutInflater;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.widget.BaseAdapter;
16 import android.widget.ListView;
17 import android.widget.TextView;
18
19 public class MainActivity extends Activity {
20
21     private ListView lv;
22     private List<student> list = new ArrayList<student>();
23
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28
29         MyDataBaseOpenOrCreate myDataBase = new MyDataBaseOpenOrCreate(
30                 MainActivity.this);
31         SQLiteDatabase db = myDataBase.getWritableDatabase();
32         Log.i("tag", "创建数据库完成");
33         Cursor cursor = db.query("t_student", null, null, null, null, null,
34                 null);
35         while (cursor.moveToNext()) {
36             student s = new student();
37             s.setStuName(cursor.getString(cursor.getColumnIndex("stuName")));
38
39             list.add(s);
40         }
41         db.close();
42         lv = (ListView) findViewById(R.id.listView1);
43         lv.setAdapter(new BaseAdapter() {
44
45             // 返回多少条记录
46             @Override
47             public int getCount() {
48                 // TODO Auto-generated method stub
49                 return list.size();
50             }
51
52             // 每一个item项,返回一次界面
53             @Override
54             public View getView(int position, View convertView, ViewGroup parent) {
55                 View view = null;
56
57
58                 LayoutInflater inflater = MainActivity.this.getLayoutInflater();
59                 // 因为getView()返回的对象,adapter会自动赋给ListView
60                 view = inflater.inflate(R.layout.list_item, null);
61
62                 student m = list.get(position);
63
64                 TextView tv_stuName = (TextView) view
65                         .findViewById(R.id.tv_stuName);
66                 tv_stuName.setText(m.getStuName());
67
68
69                 return view;
70             }
71
72             @Override
73             public Object getItem(int position) {
74                 // TODO Auto-generated method stub
75                 return null;
76             }
77
78             @Override
79             public long getItemId(int position) {
80                 // TODO Auto-generated method stub
81                 return 0;
82             }
83
84         });
85     }
86
87 }

显示的结果:

  

当我们第一次运行的时候,在日志中可以看到之前oncreate()方法中日志

但是当我们在重新运行一次的时候,日志是这样的

由此可见,只有我们数据库没有这个数据库的时候他才会走oncreate()方法。

因为我们创建的是app项目,会经常发生数据变化,所以我们就需要对数据库进行更新。

更新的思路:

当前版本 v1.0
  1.  没有安装过    会直接 走 onCreate()  
--------------------------------------
 当前版本 v2.0   [onUpgrade 情况:n-1,onCreate 情况:1]    升级就会直接走  onUpgrade() 方法
  1.  v1.0 --> v2.0  onUpgrade   
  2.  没有安装过       onCreate()  
-----------------------------------------
 当前版本 v3.0   [onUpgrade 情况:n-1,onCreate 情况:1]
  1.  v1.0 -->v3.0    onUpgrade   
      alter table t_message add column isdel bit default 0;
      插入数据
  2.  v2.0 -->v3.0    onUpgrade  
       alter table t_message add column isdel bit default 0;
  3.  没有安装过       onCreate()

----------------------------------------------------------------------

降级的设计关键点
1、考虑云端要保存用户【自定义数据、行为习惯】。专业术语profile-->>提高用户黏度
2、考虑[当前]的最低版本要求-->>降低维护成本
3、尽可能本地的数据转移(所有新版本,都不删除字段)-->尽可能把未知变已知
    try catch

升级数据库的话,就在那个onUpgrade()方法中进行,我们把之前定义version(版本号)改为2,再在 onUpgrade()方法中修改数据库

  

 1 package com.example.sqlltetest;
 2
 3 import android.content.Context;
 4 import android.database.DatabaseErrorHandler;
 5 import android.database.sqlite.SQLiteDatabase;
 6 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 7 import android.database.sqlite.SQLiteOpenHelper;
 8 import android.util.Log;
 9
10 public class MyDataBaseOpenOrCreate extends SQLiteOpenHelper{
11
12     private static final String DB_NAME = "mydata.db"; // 数据库名称
13     private static final int version = 2; // 数据库版本
14
15
16
17     public MyDataBaseOpenOrCreate(Context context) {
18         super(context, DB_NAME, null, version);
19     }
20
21     @Override
22     public void onCreate(SQLiteDatabase db) {
23         Log.i("tag", "欢迎你的加入");
24         String sql_table = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))";
25         db.execSQL(sql_table);
26         String sql_1 = "insert into t_student(stuName) values (‘小波‘)";
27         String sql_2 = "insert into t_student(stuName) values (‘小小波‘)";
28         String sql_3 = "insert into t_student(stuName) values (‘小小小波‘)";
29         db.execSQL(sql_1);
30         db.execSQL(sql_2);
31         db.execSQL(sql_3);
32     }
33
34     @Override
35     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newversion) {
36         if (oldVersion == 1){
37             String sql_upgrade_1 = "alter table t_student add column age int default 18";
38             db.execSQL(sql_upgrade_1);
39             Log.i("db", "从1到2,升级成功!");
40         }
41
42     }
43
44
45 }

当然数据的改变,我们的显示也要跟着改变,我们对之前的MainActivity进行修改

  

 1 package com.example.sqlltetest;
 2
 3 import java.util.*;
 4
 5 import com.example.entity.student;
 6
 7 import android.app.Activity;
 8 import android.database.Cursor;
 9 import android.database.sqlite.SQLiteDatabase;
10 import android.os.Bundle;
11 import android.util.Log;
12 import android.view.LayoutInflater;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.widget.BaseAdapter;
16 import android.widget.ListView;
17 import android.widget.TextView;
18
19 public class MainActivity extends Activity {
20
21     private ListView lv;
22     private List<student> list = new ArrayList<student>();
23
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28
29         MyDataBaseOpenOrCreate myDataBase = new MyDataBaseOpenOrCreate(
30                 MainActivity.this);
31         SQLiteDatabase db = myDataBase.getWritableDatabase();
32         Log.i("tag", "创建数据库完成");
33         Cursor cursor = db.query("t_student", null, null, null, null, null,
34                 null);
35         while (cursor.moveToNext()) {
36             student s = new student();
37             s.setStuName(cursor.getString(cursor.getColumnIndex("stuName")));
38             s.setAge(cursor.getInt(cursor.getColumnIndex("age")));
39             list.add(s);
40         }
41         db.close();
42         lv = (ListView) findViewById(R.id.listView1);
43         lv.setAdapter(new BaseAdapter() {
44
45             // 返回多少条记录
46             @Override
47             public int getCount() {
48                 // TODO Auto-generated method stub
49                 return list.size();
50             }
51
52             // 每一个item项,返回一次界面
53             @Override
54             public View getView(int position, View convertView, ViewGroup parent) {
55                 View view = null;
56
57                 // 布局不变,数据变
58
59                 // 如果缓存为空,我们生成新的布局作为1个item
60                 LayoutInflater inflater = MainActivity.this.getLayoutInflater();
61                 // 因为getView()返回的对象,adapter会自动赋给ListView
62                 view = inflater.inflate(R.layout.list_item, null);
63
64                 student m = list.get(position);
65
66                 TextView tv_stuName = (TextView) view
67                         .findViewById(R.id.tv_stuName);
68                 tv_stuName.setText(m.getStuName());
69
70                 TextView tv_Age = (TextView) view.findViewById(R.id.tv_age);
71                 tv_Age.setText(m.getAge() + "");
72
73                 return view;
74             }
75
76             @Override
77             public Object getItem(int position) {
78                 // TODO Auto-generated method stub
79                 return null;
80             }
81
82             @Override
83             public long getItemId(int position) {
84                 // TODO Auto-generated method stub
85                 return 0;
86             }
87
88         });
89     }
90
91 }

下面我们看一下日志和结果:

好了,我们的数据库升级成功了,接着我们来尝试一下降级吧,

我们先把version(版本好)换成1

  

package com.example.sqlltetest;

import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MyDataBaseOpenOrCreate extends SQLiteOpenHelper{

    private static final String DB_NAME = "mydata.db"; // 数据库名称
    private static final int version = 1; // 数据库版本

    public MyDataBaseOpenOrCreate(Context context) {
        super(context, DB_NAME, null, version);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i("tag", "欢迎你的加入");
        String sql_table = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))";
        db.execSQL(sql_table);
        String sql_1 = "insert into t_student(stuName) values (‘小波‘)";
        String sql_2 = "insert into t_student(stuName) values (‘小小波‘)";
        String sql_3 = "insert into t_student(stuName) values (‘小小小波‘)";
        db.execSQL(sql_1);
        db.execSQL(sql_2);
        db.execSQL(sql_3);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newversion) {
        if (oldVersion == 1){
            String sql_upgrade_1 = "alter table t_student add column age int default 18";
            db.execSQL(sql_upgrade_1);
            Log.i("db", "从1到2,升级成功!");
        }

    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        try {
            //第一、先把t_message 未来的表,改名
            String rename_sql = "alter table t_student rename to t_student_bak";
            db.execSQL(rename_sql);
            Log.i("down", "1.改名成功");
            //第二、建立降级的表名的表结构
            String sql_message = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))";
            db.execSQL(sql_message);
            Log.i("down", "2.建立2.0表结构成功");
            //第三、把备份的数据,copy到 新建的2.0的表(即将之前表名的数据插入到降级的版本中)
            String sql_copy = "insert into t_student select stuName from t_student_bak";
            db.execSQL(sql_copy);
            Log.i("down", "3.copy到用户数据到 2.0的表");
            //第四、把备份表drop掉
            String drop_sql = "drop table if exists t_student_bak";
            db.execSQL(drop_sql);
            Log.i("down", "4.把备份表drop掉");

        } catch (Exception e) {
            //如果上面的方法不行,采取最暴力的行为,把表删了,重新建立一张之前版本的表
            Log.i("hi", "降级失败,重新建立");
            String sql_drop_old_table = "drop table if exists t_student";
            String sql_message = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))";
            String sql_init_1 = "insert into t_student(stuName) values (‘小波‘)";
            String sql_init_2 = "insert into t_student(stuName) values (‘小明‘)";
            String sql_init_3 = "insert into t_student(stuName) values (‘小红‘)";
            db.execSQL(sql_drop_old_table);
            db.execSQL(sql_message);
            db.execSQL(sql_init_1);
            db.execSQL(sql_init_2);
            db.execSQL(sql_init_3);
        }
    }

}
 1 package com.example.sqlltetest;
 2
 3 import java.util.*;
 4
 5 import com.example.entity.student;
 6
 7 import android.app.Activity;
 8 import android.database.Cursor;
 9 import android.database.sqlite.SQLiteDatabase;
10 import android.os.Bundle;
11 import android.util.Log;
12 import android.view.LayoutInflater;
13 import android.view.View;
14 import android.view.ViewGroup;
15 import android.widget.BaseAdapter;
16 import android.widget.ListView;
17 import android.widget.TextView;
18
19 public class MainActivity extends Activity {
20
21     private ListView lv;
22     private List<student> list = new ArrayList<student>();
23
24     @Override
25     protected void onCreate(Bundle savedInstanceState) {
26         super.onCreate(savedInstanceState);
27         setContentView(R.layout.activity_main);
28
29         MyDataBaseOpenOrCreate myDataBase = new MyDataBaseOpenOrCreate(
30                 MainActivity.this);
31         SQLiteDatabase db = myDataBase.getWritableDatabase();
32         Log.i("tag", "创建数据库完成");
33         Cursor cursor = db.query("t_student", null, null, null, null, null,
34                 null);
35         while (cursor.moveToNext()) {
36             student s = new student();
37             s.setStuName(cursor.getString(cursor.getColumnIndex("stuName")));
38             //s.setAge(cursor.getInt(cursor.getColumnIndex("age")));
39             list.add(s);
40         }
41         db.close();
42         lv = (ListView) findViewById(R.id.listView1);
43         lv.setAdapter(new BaseAdapter() {
44
45             // 返回多少条记录
46             @Override
47             public int getCount() {
48                 // TODO Auto-generated method stub
49                 return list.size();
50             }
51
52             // 每一个item项,返回一次界面
53             @Override
54             public View getView(int position, View convertView, ViewGroup parent) {
55                 View view = null;
56
57                 // 布局不变,数据变
58
59                 // 如果缓存为空,我们生成新的布局作为1个item
60                 LayoutInflater inflater = MainActivity.this.getLayoutInflater();
61                 // 因为getView()返回的对象,adapter会自动赋给ListView
62                 view = inflater.inflate(R.layout.list_item, null);
63
64                 student m = list.get(position);
65
66                 TextView tv_stuName = (TextView) view
67                         .findViewById(R.id.tv_stuName);
68                 tv_stuName.setText(m.getStuName());
69
70                 /*TextView tv_Age = (TextView) view.findViewById(R.id.tv_age);
71                 tv_Age.setText(m.getAge() + "");*/
72
73                 return view;
74             }
75
76             @Override
77             public Object getItem(int position) {
78                 // TODO Auto-generated method stub
79                 return null;
80             }
81
82             @Override
83             public long getItemId(int position) {
84                 // TODO Auto-generated method stub
85                 return 0;
86             }
87
88         });
89     }
90
91 }

结果:

因为我的数据主键用的是自增长,没有对数据降级的表的数据插入数据进行考虑,所以直接把之前那个表个删了在建一个新的。

时间: 11-29

Android菜鸟成长记11 -- sqlite数据库的设计和升降级的相关文章

Android—SQLITE数据库的设计和升降级

Google为Andriod的较大的数据处理提供了SQLite,他在数据存储.管理.维护等各方面都相当出色,功能也非常的强大.SQLite具备下列特点: 1.轻量级 使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小. 2.独立性 SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的"安装". 3.隔离性 SQLite 数据库中所有的信息(比如表.视图.触发器等)都包含在一个文件夹内,方便管理和维护. 4.跨平台 SQLite 目前

Android菜鸟成长记12 -- ORMLite的简单使用

在我们的开发中,为了提高开发效率,我们一般都会使用到框架,ormilte则是我们必不可少的数据库框架. 对于ORMLite我也是今天才刚刚接触,我们先从一个简单的项目来了解它吧. ORMLite jar 要想使用ormlite,我们要先下载其jar包. 下载方法: 我们可以到官网去下载:http://ormlite.com/releases/ 下载的时候,我们要下载一个core的jar和android的jar,本人用的是ormlite-android-5.0.jar和ormlite-core-5

Android菜鸟成长记5-ADB和sqllite

Android开发环境中,ADB是我们进行Android开发经常要用的调试工具,它的使用当然是我们Android开发者必须要掌握的. ADB概述 Android Debug Bridge,Android调试桥接器,简称adb,是用于管理模拟器或真机状态的万能工具,采用了客户端-服务器模型,包括三个部分: 1.客户端部分,运行在开发用的电脑上,可以在命令行中运行adb命令来调用该客户端,像ADB插件和DDMS这样的Android工具也可以调用adb客户端. 2.服务端部分,是运行在开发用电脑上的后

Android菜鸟成长记9 -- selector的用法

在项目开发的时候,由于系统给出的控件不够美观,因此开发时领导常常要我更改下界面,用美工给的图片取代系统图片.开始时,我只是给按钮等设置一下背景图片,这样做虽然美观了,但界面看起来却比较死板,比如用户点击了按钮后,按钮没一点反应.于是我就再给控件添加上onTouch监听事件,按下后改变背景颜色,松手后再恢复原来颜色.但后来发现了selector这个利器,真是喜出望外,不用再添加onTouch监听事件了,用起来也方便灵活.不得不说,多和其他开发人员交流技术经验等还是很有必要的,特别是像我这样独自负责

Android菜鸟成长记8 -- 布局实践(微信界面的编写)

前面我们简单的介绍了一下android的五大布局,那么现在我们来实践一下,写一个简单的微信界面 首先,我们新建一个weixin.xml的linnerlayout布局 我们日常使用的微信,从简单的方面来说我可一分成三个内容,头部标签栏,中间显示信息栏,还有一个底部.那么我们就按照这个来先建一个页面 1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="

Android菜鸟成长记15 -- BitMap

BitMap简介 Bitmap是Android系统中的图像处理的最重要类之一.用它可以获取图像文件信息,进行图像剪切.旋转.缩放等操作,并可以指定格式保存图像文件.本文从应用的角度,着重介绍怎么用Bitmap来实现这些功能. BitMap的常用属性 1. BitMap类 public void recycle()--回收位图占用的内存空间,把位图标记为Dead  public final boolean isRecycled() --判断位图内存是否已释放  public final int g

Android菜鸟成长记1 -- JSON的解析

JSON的定义  一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. android提供的json解析类 android的json解析部分都在包org.json下,主要有以下几个类: JSONObject:可以看作是一个json对象,这是系统中有关JSON定义的基本单元,其包含一对儿(Key/

菜鸟成长记1,软件工程大一经历

菜鸟成长记1 -----大一总结及反思 大一即将结束,突然间想总结一下我的大一生活,最重要的还是好好反思一下. 回首整个大一感觉自己学了好多的东西,但最终的感觉还是一无所成,大一上学期学习c语言,一直处于一个总是一个没有入门的感觉,虽然简单的c经长期磨练已经差不多搞懂,不过稍微复杂点的抑或着说稍微麻烦点的都没有真正学会,仅仅是学过c而已,在学c的同时一直想练ACM可能真的是天赋不够也可能是自己不是这块料,在几经折磨下,做了uva上不超过30道题的情况下放弃了,除想练ACM这中间还接触了java和

在 Android 应用程序中使用 SQLite 数据库以及怎么用

part one : android SQLite 简单介绍 SQLite 介绍 SQLite 一个非常流行的嵌入式数据库.它支持 SQL 语言,而且仅仅利用非常少的内存就有非常好的性能.此外它还是开源的,不论什么人都能够使用它.很多开源项目((Mozilla, PHP, Python)都使用了 SQLite. SQLite 由下面几个组件组成:SQL 编译器.内核.后端以及附件.SQLite 通过利用虚拟机和虚拟数据库引擎(VDBE).使调试.改动和扩展 SQLite 的内核变得更加方便. 图