白日放歌须纵酒,青春作伴好还乡。这篇文章主要讲述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 12private static final String DB_NAME = "mydata.db"; // 数据库名称 13private static final int version = 1; // 数据库版本 14 15 16 17public MyDataBaseOpenOrCreate(Context context) { 18super(context, DB_NAME, null, version); 19} 20 21@Override 22public void onCreate(SQLiteDatabase db) { 23Log.i("tag", "欢迎你的加入"); 24String sql_table = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))"; 25db.execSQL(sql_table); 26String sql_1 = "insert into t_student(stuName) values (\'小波\')"; 27String sql_2 = "insert into t_student(stuName) values (\'小小波\')"; 28String sql_3 = "insert into t_student(stuName) values (\'小小小波\')"; 29db.execSQL(sql_1); 30db.execSQL(sql_2); 31db.execSQL(sql_3); 32} 33 34@Override 35public 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 5private String stuid; 6private String stuName; 7private int age; //为了升级做准备的 8public String getStuid() { 9return stuid; 10} 11public void setStuid(String stuid) { 12this.stuid = stuid; 13} 14public String getStuName() { 15return stuName; 16} 17public void setStuName(String stuName) { 18this.stuName = stuName; 19} 20public int getAge() { 21return age; 22} 23public void setAge(int age) { 24this.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 21private ListView lv; 22private List< student> list = new ArrayList< student> (); 23 24@Override 25protected void onCreate(Bundle savedInstanceState) { 26super.onCreate(savedInstanceState); 27setContentView(R.layout.activity_main); 28 29MyDataBaseOpenOrCreate myDataBase = new MyDataBaseOpenOrCreate( 30MainActivity.this); 31SQLiteDatabase db = myDataBase.getWritableDatabase(); 32Log.i("tag", "创建数据库完成"); 33Cursor cursor = db.query("t_student", null, null, null, null, null, 34null); 35while (cursor.moveToNext()) { 36student s = new student(); 37s.setStuName(cursor.getString(cursor.getColumnIndex("stuName"))); 38 39list.add(s); 40} 41db.close(); 42lv = (ListView) findViewById(R.id.listView1); 43lv.setAdapter(new BaseAdapter() { 44 45// 返回多少条记录 46@Override 47public int getCount() { 48// TODO Auto-generated method stub 49return list.size(); 50} 51 52// 每一个item项,返回一次界面 53@Override 54public View getView(int position, View convertView, ViewGroup parent) { 55View view = null; 56 57 58LayoutInflater inflater = MainActivity.this.getLayoutInflater(); 59// 因为getView()返回的对象,adapter会自动赋给ListView 60view = inflater.inflate(R.layout.list_item, null); 61 62student m = list.get(position); 63 64TextView tv_stuName = (TextView) view 65.findViewById(R.id.tv_stuName); 66tv_stuName.setText(m.getStuName()); 67 68 69return view; 70} 71 72@Override 73public Object getItem(int position) { 74// TODO Auto-generated method stub 75return null; 76} 77 78@Override 79public long getItemId(int position) { 80// TODO Auto-generated method stub 81return 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 12private static final String DB_NAME = "mydata.db"; // 数据库名称 13private static final int version = 2; // 数据库版本 14 15 16 17public MyDataBaseOpenOrCreate(Context context) { 18super(context, DB_NAME, null, version); 19} 20 21@Override 22public void onCreate(SQLiteDatabase db) { 23Log.i("tag", "欢迎你的加入"); 24String sql_table = "create table t_student(stuid integer primary key autoincrement,stuName varchar(50))"; 25db.execSQL(sql_table); 26String sql_1 = "insert into t_student(stuName) values (\'小波\')"; 27String sql_2 = "insert into t_student(stuName) values (\'小小波\')"; 28String sql_3 = "insert into t_student(stuName) values (\'小小小波\')"; 29db.execSQL(sql_1); 30db.execSQL(sql_2); 31db.execSQL(sql_3); 32} 33 34@Override 35public void onUpgrade(SQLiteDatabase db, int oldVersion, int newversion) { 36if (oldVersion == 1){ 37String sql_upgrade_1 = "alter table t_student add column age int default 18"; 38db.execSQL(sql_upgrade_1); 39Log.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 21private ListView lv; 22private List< student> list = new ArrayList< student> (); 23 24@Override 25protected void onCreate(Bundle savedInstanceState) { 26super.onCreate(savedInstanceState); 27setContentView(R.layout.activity_main); 28 29MyDataBaseOpenOrCreate myDataBase = new MyDataBaseOpenOrCreate( 30MainActivity.this); 31SQLiteDatabase db = myDataBase.getWritableDatabase(); 32Log.i("tag", "创建数据库完成"); 33Cursor cursor = db.query("t_student", null, null, null, null, null, 34null); 35while (cursor.moveToNext()) { 36student s = new student(); 37s.setStuName(cursor.getString(cursor.getColumnIndex("stuName"))); 38s.setAge(cursor.getInt(cursor.getColumnIndex("age"))); 39list.add(s); 40} 41db.close(); 42lv = (ListView) findViewById(R.id.listView1); 43lv.setAdapter(new BaseAdapter() { 44 45// 返回多少条记录 46@Override 47public int getCount() { 48// TODO Auto-generated method stub 49return list.size(); 50} 51 52// 每一个item项,返回一次界面 53@Override 54public View getView(int position, View convertView, ViewGroup parent) { 55View view = null; 56 57// 布局不变,数据变 58 59// 如果缓存为空,我们生成新的布局作为1个item 60LayoutInflater inflater = MainActivity.this.getLayoutInflater(); 61// 因为getView()返回的对象,adapter会自动赋给ListView 62view = inflater.inflate(R.layout.list_item, null); 63 64student m = list.get(position); 65 66TextView tv_stuName = (TextView) view 67.findViewById(R.id.tv_stuName); 68tv_stuName.setText(m.getStuName()); 69 70TextView tv_Age = (TextView) view.findViewById(R.id.tv_age); 71tv_Age.setText(m.getAge() + ""); 72 73return view; 74} 75 76@Override 77public Object getItem(int position) { 78// TODO Auto-generated method stub 79return null; 80} 81 82@Override 83public long getItemId(int position) { 84// TODO Auto-generated method stub 85return 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); } }}
【Android菜鸟成长记11 -- sqlite数据库的设计和升降级】
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 21private推荐阅读
- Android Fragment使用 Toolbar使用及Fragment中的Toolbar处理
- Android获取网络图片
- Android Fragment使用 基础篇 温故知新
- android Service学习
- Android Fragment使用 嵌套Fragments (Nested Fragments) 的使用及常见错误
- Android SQLiteOpenHelper
- Android Fragment使用 Activity, Fragment, WebView的状态保存和恢复
- 仿知乎Android端回答UI
- android recyclerview的浅析。