android系統內置了數據庫,SQLite做爲一種輕量級的關係型數據庫,它的運算速度很是快。佔用資源不多,一般只須要幾百k的內存就足夠了,以前多介紹的兩種方式只適合去存儲一些簡單的數據和鍵值對,當蓄呀存儲大量的複雜的關係型數據的時候,就會發現以上兩種存儲方式很難應付。下面開始介紹在android中如何使用SQLite數據庫。java
1 建立數據庫android
android爲了讓咱們更加方便的管理數據庫,專門爲咱們提供了一個SQLiteOpenHelper幫助類,藉助這個類就能夠很是簡單的對數據庫盡享建立和升級,下面我主要介紹一下這個類的一些基本用法。sql
SQLiteOpenHelper類是一個抽象類,主要有兩個抽象方法,分別是onCreate和onUpgrade(),咱們必須在本身的幫助類中去重寫這兩個方法,分別在這兩個類中去實現建立和升級數據庫的邏輯。數據庫
SQLiterOpenHelper中還有兩個很是重要的實力方法,getReadableDatabase()和getWritablebase(),這兩個方法均可以建立或打開一個現有的數據庫並返回一個能夠對數據庫進行讀寫操做的對象,須要注意的是,當數據庫不可寫入的時候,getReadableDatabase()方法返回的對象將以只讀的方式去打開數據庫,而getWiterableDatabase()方法則將會出現異常。app
SQLiteOpenHelper中有兩個構造方法可供重寫,通常使用參數少點的那個,這個構造方法接受四個參數,第一個參數Context,這個沒什麼好說的,第二個參數是數據庫名,第三個參數容許咱們在查詢數據的時候返回一個自定義的Cursor,通常都是傳入null,第四個參數表示當前數據庫的版本號。構建出SQLiteOpenHelper的實例以後,再調用他的getReadableDatabase()或getwritableDatabase()方法就可以建立數據庫了,重寫的onCreate()方法也會獲得執行。ide
接下來根據一個例子,建立一個BookStrore.db的數據庫,並對其進行添加(insert),更新(update),刪除(delete),查詢(quary).
this
建立SQLiteOpenHelper類的實例代碼:spa
package com.example.apple.servicetest; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.widget.Toast; /** * Created by apple on 16/3/22. */ public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK="create table Book(" + "id interger primary key autoincrement" + "author text" + "price real" + "pages integer" + "name text)"; public static final String CREATE_CATEGORY="create table Category(" + "id integer primary key autoincrement" + "category_name text," + "category_code integer)"; private Context mContext; public MyDatabaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){ super(context,name,factory,version); mContext=context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(mContext,"successed",Toast.LENGTH_LONG).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists Book"); db.execSQL("drop table if exist Category"); onCreate(db); } }
對數據庫進行操做:code
package com.example.apple.servicetest; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Message; import android.preference.PreferenceManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class MainActivity extends AppCompatActivity { private Button createbtn; private Button adddatabtn; private Button updatabtn; private Button deletebtn; private Button quarybtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); createbtn=(Button)findViewById(R.id.create_btn); final MyDatabaseHelper databaseHelper=new MyDatabaseHelper(this,"BookStore.db",null,2); createbtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { databaseHelper.getWritableDatabase(); } }); //更新數據 updatabtn=(Button)findViewById(R.id.updata_btn); updatabtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db=databaseHelper.getWritableDatabase(); ContentValues values=new ContentValues(); values.put("price", 10.99); db.update("Book", values, "name=?", new String[]{"love is good"}); } }); //刪除數據 deletebtn=(Button)findViewById(R.id.delete_data); deletebtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db=databaseHelper.getWritableDatabase(); db.delete("Book", "pages>?", new String[]{"500"}); } }); //查詢數據 quarybtn=(Button)findViewById(R.id.quary_btn); quarybtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db=databaseHelper.getWritableDatabase(); Cursor cursor=db.query("Book",null,null,null,null,null,null); if (cursor.moveToFirst()){ do { String name=cursor.getString(cursor.getColumnIndex("name")); String author=cursor.getString(cursor.getColumnIndex("author")); Log.d("lallalala",name); Log.d("youyouyouyou",author); }while (cursor.moveToNext()); } cursor.close(); } }); //添加數據 adddatabtn=(Button)findViewById(R.id.add_btn); adddatabtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db=databaseHelper.getWritableDatabase(); ContentValues values=new ContentValues(); values.put("name","love is good"); values.put("author","dan brown"); values.put("pages",454); values.put("price",16.96); db.insert("Book", null, values); values.clear(); values.put("name","love is bad"); values.put("author","dan "); values.put("pages",400); values.put("price", 19.00); db.insert("Book", null, values); } }); } }
這是其中一種方法來操做數據庫,還有一種是使用SQL來操做數據庫,具體代碼實現以下:sqlite
更新數據庫
刪除數據庫
db.execSQL("delete from Book where pages>?",new String[]{"500"});
更新數據庫 db.execSQL("update Book set price =? where name=?",new String[] {"10.99","the name"});
添加數據庫
db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)", new String[] {"the name","the author","454","19.69"});
查找數據庫
db.rawQuery("select * from Book",null);
SQLite數據庫的最佳實踐
1 使用事務
咱們已經知道了SQLite數據庫是支持事務的,事務的特性能夠保證讓某一系列的操做要麼所有完成,要麼一個都不會完成,那麼在什麼狀況下才須要使用事務,據個例子,在盡享一次轉帳操做的時候,銀行會將轉帳的金額先從帳戶中扣除,而後再向收款房的帳戶中添加等量的金額,可是若是當剛剛從 帳戶將錢扣除了以後,因爲一些異常致使了對方收款失敗了,那麼這部分的錢就會憑空消失了,這時候就必須使用事務。
接下來將會在這個例子中使用事務,目的是將刪除舊數據和添加新數據的操做一塊兒完成,不然就必須還原成原來的舊數據。
SQLiteDatabase db=databaseHelper.getWritableDatabase(); db.beginTransaction(); try { db.delete("Book",null,null); if (true){ throw new NullPointerException(); } ContentValues values=new ContentValues(); values.put("name","Game of Throns"); values.put("author","George Martin"); values.put("pages",720); values.put("price",20.85); db.insert("Book", null, values); db.setTransactionSuccessful(); }catch (Exception e){ e.printStackTrace(); }finally { db.endTransaction(); } }
如今能夠運行一下程序,發現表中的數據仍是原先的那些,如今將手動拋出的異常刪除掉,再運行議席,便發現表中的數據已經更新成新的數據了。
升級數據庫的最佳寫法:
再以前的寫法中咱們簡單粗暴的直接刪掉了全部當前的表而後強制從新執行一遍onCreate()方法。咱們須要進行一些合理的控制,讓咱們保證在升級數據庫的時候數據不會丟失,在初版的時候建立兩個,在第二版的時候在book表中添加category_id鍵。代碼以下:
package com.example.apple.servicetest; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.widget.Toast; /** * Created by apple on 16/3/22. */ public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK="create table Book(" + "id interger primary key autoincrement" + "author text" + "price real" + "pages integer" + "name text" + "category_id integer)"; public static final String CREATE_CATEGORY="create table Category(" + "id integer primary key autoincrement" + "category_name text," + "category_code integer)"; private Context mContext; public MyDatabaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){ super(context,name,factory,version); mContext=context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(mContext,"successed",Toast.LENGTH_LONG).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //db.execSQL("drop table if exists Book"); //db.execSQL("drop table if exist Category"); //onCreate(db); switch (oldVersion){ case 1: db.execSQL(CREATE_CATEGORY);case 2: db.execSQL("alter table Book add column category_id integer");//在第二版中添加的數據 default: } } }
請注意一個很是重要的細節,switch中的每個case的最後都沒有使用break的緣由,是爲了保證在跨版本升級的時候,每一次的數據庫修改都能被所有執行到,好比從當前的第二版升級到第三版的時候,case2中的邏輯就會執行,若是用戶從初版程序升級到第三版程序的時候,case1和case2也會被執行。使用這種方式來維護數據庫的升級,無論版本怎樣更新,均可以保證數據庫的表結構是最新的,並且表中的數據也徹底不會丟失了。