数据库是Android的一种数据存储方式,但是SQLiteOpenHelper是抽象类,我们需要自己写一个实现类来实现onCreate方法和onUpgrade方法,这两个方法分别会在数据库创建和更新的时候调用到。
getWritableDatabase方法和getReadableDatabase方法分别返回一个可写的数据库和一个可读的数据库。如果发现数据库不存在,就会调用onCreate方法创建一个数据库,
如果版本号升级就调用onUpgrade升级数据库。创建的数据库在/data/data/xxx(package)/xxx.db
SQLiteOpenHelper:
如下是一个SQLiteOpenHelper的实现类,创建的时候生成两张表,更新的时候生成一张表。
package com.example.sql.sql;
import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
* Created by hongbin on 17-3-6.
*/
public class MyOpenHelper extends SQLiteOpenHelper {
//数据库版本号
private static final int DATABASE_VERSION = 1;
//数据库名
private static final String DATABASE_NAME = "Test.db";
//数据库表名
public static final String[] TABLE_NAMES = {"TABLE_0", "TABLE_1", "TABLE_2"};
public MyOpenHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
Log.d("dbLog","MyOpenHelper");
}
public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
super(context, name, factory, version, errorHandler);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
Log.d("dbLog","onCreate");
//创建表一语句
StringBuffer sBuffer0 = new StringBuffer();
sBuffer0.append("CREATE TABLE [" + TABLE_NAMES[0] + "] (");
sBuffer0.append("[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ");
sBuffer0.append("[name] TEXT,");
sBuffer0.append("[age] INTEGER)");
//创建表二语句
StringBuffer sBuffer1 = new StringBuffer();
sBuffer1.append("CREATE TABLE [" + TABLE_NAMES[1] + "] (");
sBuffer1.append("[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ");
sBuffer1.append("[name] TEXT,");
sBuffer1.append("[age] INTEGER)");
// 执行SQL语句
sqLiteDatabase.execSQL(sBuffer0.toString());
sqLiteDatabase.execSQL(sBuffer1.toString());
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
Log.d("dbLog","onUpgrade");
StringBuffer sBuffer3 = new StringBuffer();
sBuffer3.append("CREATE TABLE [" + TABLE_NAMES[2] + "] (");
sBuffer3.append("[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ");
sBuffer3.append("[name] TEXT,");
sBuffer3.append("[age] INTEGER)");
sqLiteDatabase.execSQL(sBuffer3.toString());
}
}
Activity:
public class MainActivity extends AppCompatActivity {
private MyOpenHelper myOpenHelper;
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myOpenHelper = new MyOpenHelper(this);
//获取一个可写的数据库,如果不存在就创建,如果版本更新就升级
Log.d("dbLog","getWritableDatabase");
db = myOpenHelper.getWritableDatabase();
}
}
Log:
从以上日志可以发现数据库创建和升级的流程。
第一次运行的时候版本号为1,执行getWritableDatabase方法没有数据库,所以调用onCreate方法创建了一个数据库,数据库名为Test.db,并且创建了两张表;第二次运行的时候版本号为2,执行getWritableDatabase方法时发现数据库版本升级了,所以调用onUpgrade方法,在Test.db下创建了TABLE_2表。
创建之后对数据库的增删改查可以用execSQL来执行SQL语句,也可以分别用insert、delete、update、query来执行,这里就不细说了。
批量处理
在数据库的使用过程中,常常需要一次性操作大量的数据,如果用循环一次一次的操作肯定是很消耗事件的,这时候我们就需要用到开启一个事务来做批处理。做个实验验证一下一次性插入5000条数据的时间消耗。
public void onClick(View view) {
int i = 0;
String sql = "INSERT INTO %s VALUES (null, %s, %s)";
try {
Log.d("dbLog","非批处理");
Log.d("dbLog","start");
while(i < 5000){
db.execSQL(String.format(sql,MyOpenHelper.TABLE_NAMES[0],i,i));
i++;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
Log.d("dbLog","finish");
Log.d("dbLog","插入" + i + "条数据");
}
}
//----------------------------------我是一条分割线------------------------------------//
public void onClick(View view) {
int i = 0;
String sql = "INSERT INTO %s VALUES (null, %s, %s)";
try {
Log.d("dbLog","批处理");
Log.d("dbLog","start");
db.beginTransaction();
while(i < 5000){
db.execSQL(String.format(sql,MyOpenHelper.TABLE_NAMES[1],i,i));
i++;
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
db.endTransaction();
Log.d("dbLog","finish");
Log.d("dbLog","插入" + i + "条数据");
}
}
不采用事务来执行人5000次的插入操作,从日志中可以看到,start到finish的时间差是34.53秒。
而采用事务来执行人5000次的插入操作,从日志中可以看到,start到finish的时间差是1.16秒。
这里的性能差别真是太大啦。
我们都知道磁盘的读写是很耗时的,简单来说,每一次的插入都是一个事务,执行5000插入操作相当于执行了5000次的磁盘读写,而采用事务包装的话就把5000次的插入操作当作一次事务,也就是一次磁盘读写,时间上当然相差很大啦。
数据库的知识太多了,这里就简单描述一下Android SQLite最基础的操作。