數(shù)據(jù)庫(kù)是Android的一種數(shù)據(jù)存儲(chǔ)方式,但是SQLiteOpenHelper是抽象類,我們需要自己寫(xiě)一個(gè)實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)onCreate方法和onUpgrade方法,這兩個(gè)方法分別會(huì)在數(shù)據(jù)庫(kù)創(chuàng)建和更新的時(shí)候調(diào)用到。
getWritableDatabase方法和getReadableDatabase方法分別返回一個(gè)可寫(xiě)的數(shù)據(jù)庫(kù)和一個(gè)可讀的數(shù)據(jù)庫(kù)。如果發(fā)現(xiàn)數(shù)據(jù)庫(kù)不存在,就會(huì)調(diào)用onCreate方法創(chuàng)建一個(gè)數(shù)據(jù)庫(kù),如果版本號(hào)升級(jí)就調(diào)用onUpgrade升級(jí)數(shù)據(jù)庫(kù)。創(chuàng)建的數(shù)據(jù)庫(kù)在/data/data/xxx(package)/xxx.dbSQLiteOpenHelper:如下是一個(gè)SQLiteOpenHelper的實(shí)現(xiàn)類,創(chuàng)建的時(shí)候生成兩張表,更新的時(shí)候生成一張表。
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 { //數(shù)據(jù)庫(kù)版本號(hào) PRivate static final int DATABASE_VERSION = 1; //數(shù)據(jù)庫(kù)名 private static final String DATABASE_NAME = "Test.db"; //數(shù)據(jù)庫(kù)表名 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"); //創(chuàng)建表一語(yǔ)句 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,"); //創(chuàng)建表二語(yǔ)句 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,"); // 執(zhí)行SQL語(yǔ)句 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); //獲取一個(gè)可寫(xiě)的數(shù)據(jù)庫(kù),如果不存在就創(chuàng)建,如果版本更新就升級(jí) Log.d("dbLog","getWritableDatabase"); db = myOpenHelper.getWritableDatabase(); }}Log:
從以上日志可以發(fā)現(xiàn)數(shù)據(jù)庫(kù)創(chuàng)建和升級(jí)的流程。
創(chuàng)建之后對(duì)數(shù)據(jù)庫(kù)的增刪改查可以用execSQL來(lái)執(zhí)行SQL語(yǔ)句,也可以分別用insert、delete、update、query來(lái)執(zhí)行。
批量處理
在數(shù)據(jù)庫(kù)的使用過(guò)程中,常常需要一次性操作大量的數(shù)據(jù),如果用循環(huán)一次一次的操作肯定是很消耗事件的,這時(shí)候我們就需要用到開(kāi)啟一個(gè)事務(wù)來(lái)做批處理。做個(gè)實(shí)驗(yàn)驗(yàn)證一下一次性插入5000條數(shù)據(jù)的時(shí)間消耗。
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 + "條數(shù)據(jù)"); } }//----------------------------------我是一條分割線------------------------------------//
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 + "條數(shù)據(jù)"); } }不采用事務(wù)來(lái)執(zhí)行人5000次的插入操作,從日志中可以看到,start到finish的時(shí)間差是34.53秒。
而采用事務(wù)來(lái)執(zhí)行人5000次的插入操作,從日志中可以看到,start到finish的時(shí)間差是1.16秒。
這里的性能差別真是太大啦。
我們都知道磁盤(pán)的讀寫(xiě)是很耗時(shí)的,簡(jiǎn)單來(lái)說(shuō),每一次的插入都是一個(gè)事務(wù),執(zhí)行5000插入操作相當(dāng)于執(zhí)行了5000次的磁盤(pán)讀寫(xiě),而采用事務(wù)包裝的話就把5000次的插入操作當(dāng)作一次事務(wù),也就是一次磁盤(pán)讀寫(xiě),時(shí)間上當(dāng)然相差很大啦。
數(shù)據(jù)庫(kù)的知識(shí)太多了,這里就簡(jiǎn)單描述一下Android SQLite最基礎(chǔ)的操作。
新聞熱點(diǎn)
疑難解答
圖片精選