Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> android中的數據存取-方式三:SQLite

android中的數據存取-方式三:SQLite

編輯:Android開發實例

1.Android中通過SQLite數據庫引擎來實現結構化數據存儲。SQLite是一個嵌入式數據庫引擎,針對內存等資源有限的設備,提供的是一種高效的數據庫引擎。
  2.Android提供了創建和使用SQLite數據庫的API。SQLiteDatabase代表一個數據庫對象,提供了操作數據庫的一些方法,另外還有一個SQLiteOpenHelper工具類提供更簡潔的功能。
  3. SQLiteOpenHelper是SQliteDatabase的一個幫助類,用來管理數據庫的創建和版本更新。一般用法是定義一個類繼承之,並實現兩個抽象方法onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion)類創建和跟新數據庫。

 

Android中操作數據庫首先要通過一個 類:android.database.sqlite.SQLiteOpenHelper。它封裝了如何打開一個數據庫,其中當然也包含如果數據庫不存在 就創建這樣的邏輯。看一個例子:

 
pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "com.roiding.simple.note";
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = "notes";

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME
+ " (id integer primary key autoincrement, name text);");
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}

這裡面,如下的語句需要解釋:

  • super(context, DATABASE_NAME, null, DATABASE_VERSION)
    數據庫連接的初始化,中間的那個null,是一個CursorFactory參數,沒有仔細研究這個參數,暫時置空吧。
  • public void onCreate(SQLiteDatabase db)
    這裡面的onCreate是指數據庫onCreate時,而不是DatabaseHelper的onCreate。也就是說,如果已經指定 database已經存在,那麼在重新運行程序的時候,就不會執行這個方法了。要不然,豈不是每次重新啟動程序都要重新創建一次數據庫了!在這個方法中,完成了數據庫的創建工作。也就是那個execSQL()方法。
  • public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
    在程序的開發維護過程中,數據庫的結構可能會有變化,那麼這個方法就有用處了。在DatabaseHelper這個對象一創建時,就已經把參數 DATABASE_VERSION傳入,這樣,如果Android發現此版本與現有版本不一致,就會調用這個onUpgrate方法。於是,可以在這裡面實現一些數據的upgrade工作,比如說創建一個臨時表,將數據由臨時表中轉到新的表結構中。需要注意的是,這裡面的onUpgrade是在版本不一致時調用,也就是說不管當前需要的版本高於現有版本還是低於現有版本,都會出發這個方法,類似的這種情況,就需要對oldVersion和 newVersion進行判斷之後再決定使用什麼策略來更新數據。

在Android中,數據庫存放在 /data/data/PACKAGE_NAME/databases 目錄下。

接下來就可以使用這個Helper來操作數據庫了,操作數據庫也就無非是增、刪、改、查。先看一個增的例子:

 

 

public static void insert(Context context, String s) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String nullColumnHack = "id";

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

long id = mOpenHelper.getReadableDatabase().insert(table,
nullColumnHack, values);

mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    如果和JDBC例子的話,這一步貌似就像是獲得了一個Statement,用它就可以操作數據庫了。
  • ContentValues values = new ContentValues();
    Android在向數據庫中插入數據的時候,要求數據存放到ContentValues中,這裡面的ContentValues其實就是一個 Map,Key值是字段名稱,Value值是字段的值。這樣,也許你會發現一個問題,那數據類型怎麼辦?其實在SQLite數據庫中就是沒有數據類型的, 一切都是字符串。
  • mOpenHelper.getReadableDatabase().insert(table,nullColumnHack, values);
    將數據入庫,注意這裡面有一個nullColumnHack,看文檔是和所有字段都是空的記錄有關系,我沒有去實驗他具體的效果,只是隨便給他一個字段名稱。

再看一個查的例子:

public static void select(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String[] columns = new String[] { "id", "name" };
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String groupBy = null;
String having = null;
String orderBy = "id desc";
String limit = "1";

Cursor c = mOpenHelper.getReadableDatabase().query(table,
columns, selection, selectionArgs, groupBy, having, orderBy, limit);

c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
String s = c.getString(1);
c.moveToNext();
}
c.close();
mOpenHelper.getReadableDatabase().close();
}
  • DatabaseHelper mOpenHelper = new DatabaseHelper(context);
    於前文中的相同
  • mOpenHelper.getReadableDatabase().query();
    通過mOpenHelper.getReadableDatabase(),會得到一個SQLiteDatabase類型的只讀的數據庫連接,在這裡直接調用了他的query方法。這個query方法相對復雜,因為他將一個完整的SQL語句拆成了若干個部分:

     

    • table:表名。相當於SQL的from後面的部分。那如果是多表聯合查詢怎麼辦?那就用逗號將兩個表名分開,拼成一個字符串作為table的值。
    • columns:要查詢出來的列名。相當於SQL的select後面的部分。
    • selection:查詢條件,相當於SQL的where後面的部分,在這個語句中允許使用“?”,也就是說這個用法和JDBC中的PreparedStatement的用法相似。
    • selectionArgs:對應於selection的值,selection有幾個問號,這裡就得用幾個值。兩者必須一致,否則就會有異常。
    • groupBy:相當於SQL的group by後面的部分
    • having:相當於SQL的having後面的部分
    • orderBy:相當於SQL的order by後面的部分,如果是倒序,或者是聯合排序,可以寫成類似這樣:String orderBy = “id desc, name”;
    • limit:指定結果集的大小,它和Mysql的limit用法不太一樣,mysql可以指定從多少行開始之後取多少條,例如“limit 100,10”,但是這裡只支持一個數值。
  • c.moveToFirst();
    這一句也比較重要,如果讀取數據之前,沒有這一句,會有異常。
  • c.getString(1);
    與JDBC一致了,Android不支持按字段名來取值,只能用序號。

再看一個刪除和修改的例子:

 
public static void delete(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

有了上面的基礎這裡就容易理解了,這裡的whereClause相當於前面的selection,whereArgs相當於前面的selectionArgs。

 

 

public static void update(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);

String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;

ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");

mOpenHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}

這個update的用法,綜合select和delete就可以理解。

注意:

  • Cursor和Databases要及時關閉,不然也會有異常。
  • getWritableDatabase()和getReadableDatabase()在當前的Android版本中貌似可以通用,像上面的insert,用的就是getReadableDatabase。

在真實的應用中,會對上面這些基本操作做更高一級的抽象和封裝,使之更容易使用。在select時,除了用上述的方法,將分段的SQL語句傳進去之外,Android還支持一種方法:使用SQLiteQueryBuilder。如果使用的是上述的分段SQL語句的方法,在Android的內部實現中,也是先將分段的SQL使用SQLiteQueryBuilder的靜態方法來生成一個真正的SQL的,而且,我沒有看出來使用SQLiteQueryBuilder的優勢。

 

/Chapter09_Data_03/src/com/amaker/test/MainActivity.java

  

package com.amaker.test;

import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;

public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

SQLiteDatabase db = createDatabase();
//createTable(db);
//insert(db);
//insert2(db);
//update(db);
// update2(db);
// delete(db);
delete2(db);
query(db);
db.close();

}
// 創建數據庫,注意這裡要指定全路徑
private SQLiteDatabase createDatabase(){
return SQLiteDatabase.openOrCreateDatabase("/data/data/com.amaker.test/databases/temp2.db", null);
}
// 創建表
private void createTable(SQLiteDatabase db){
String sql = " create table UserTbl(_id integer primary key autoincrement,username text,password text)";
db.execSQL(sql);
}
// 插入數據
private void insert(SQLiteDatabase db){
String sql = " insert into UserTbl(username,password) values('amaker','123') ";
db.execSQL(sql);
}
// 插入2
private void insert2(SQLiteDatabase db){
ContentValues cv =new ContentValues();
cv.put("username","ghz");
cv.put("password", "456");
db.insert("UserTbl", null, cv);
}
// 查詢
private void query(SQLiteDatabase db){
Cursor c = db.query("UserTbl", null, null, null, null, null, null);
if(c.moveToFirst()){
for (int i = 0; i < c.getCount(); i++) {
c.move(i);
int id = c.getInt(0);
String username = c.getString(1);
String password = c.getString(2);
System.out.println(id+":"+username+":"+password);
}
}
}
// 修改
private void update(SQLiteDatabase db){
String sql = " update UserTbl set password=888 where _id=1 ";
db.execSQL(sql);
}
// 修改2
private void update2(SQLiteDatabase db){
ContentValues values = new ContentValues();
values.put("password", "999");
String whereClause = "_id=?";
String[] whereArgs = {String.valueOf(1)};
db.update("UserTbl", values, whereClause, whereArgs);
}

// 刪除
private void delete(SQLiteDatabase db){
String sql = " delete from UserTbl where _id=2 ";
db.execSQL(sql);
}
// 刪除2
private void delete2(SQLiteDatabase db){
String whereClause = "_id=?";
String[] whereArgs = {String.valueOf(1)};
db.delete("UserTbl", whereClause, whereArgs);
}


}

 

/Chapter09_Data_03/res/layout/main.xml

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
</LinearLayout>

 

/Chapter09_Data_03/AndroidManifest.xml

 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amaker.test"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
<uses-sdk android:minSdkVersion="3" />

</manifest>
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved