Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android基礎之十四數據存儲 之 SQLite數據庫詳解

Android基礎之十四數據存儲 之 SQLite數據庫詳解

編輯:關於Android編程

SQLite 是一款 輕量級的關系型數據庫,它的運算速度非常快,占用資源很少,通常只需要幾百 K 的內存就足夠了,因而特別適合在移動設備上使用。
SQLite 不僅支持標准的 SQL 語法,還遵循了數據庫的 ACID( 原子性(Atomicity) 、一致性(Consistency) 、 隔離性(Isolation) 、 持久性(Durability))事務,所以只要你以前使用過其他的關系型數據庫,就可以很快地上手 SQLite。而 SQLite 又比一般的數據庫要簡單得多,它甚至不用設置用戶名和密碼就可以使用。Android 正是把這個功能極為強大的數據庫嵌入到了系統當中,使得本地持久化的功能有了一次質的飛躍。
  1 創建數據庫 Android 為了讓我們能夠更加方便地管理數據庫,專門提供了一個 SQLiteOpenHelper幫助類, 借助這個類就可以非常簡單地對 數據庫進行創建和升級‘ SQLiteOpenHelper 中有兩個構造方法可供重寫, 一般使用參數少一點的那個構造方法即
可。這個構造方法中接收四個參數,第一個參數是 Context第二個參數是 數據庫名, 創建數據庫時使用的就是這裡指定的名
稱。第三個參數允許我們在查詢數據的時候的 返回一個自定義的 Cursor,一般都是傳入 null。
第四個參數表示 當前數據庫的版本號,可用於 對數據庫進行升級操作
MyDatabaseHelper(context, "BookStore.db", null, 1);
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREATE_BOOK = "create table book ("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, CursorFactory
factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
2 升級數據庫
如果你足夠細心, 一定會發現 MyDatabaseHelper 中還有一個空方法呢! 沒錯, onUpgrade()方法是用於對數據庫進行升級的, 它在整個數據庫的管理工作當中起著非常重要的作用, 可千萬不能忽視它喲。目前 DatabaseTest 項目中已經有一張 Book 表用於存放書的各種詳細數據,如果我們想
張 再添加一張 Category 表用於記錄書籍的分類該怎麼做呢?
package com.example.sqllitehelp;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;

public class MyDatabaseHelper extends SQLiteOpenHelper {
	public static final String CREATE_BOOK="create table Book ("
			+"id integer primary  key autoincrement ,"
			+"author test , "
			+"price real , "
			+"pages integer , "
			+"name text) "
			;
	public static final String CREATE_CATEGORY="create table Category ("
			+"id integer primary  key autoincrement ,"
			+"category_name test , "
			+"category_code integer)"
			;
	private Context mContext;

	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
		mContext=context;
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		db.execSQL(CREATE_BOOK);
		db.execSQL(CREATE_CATEGORY);
		Toast.makeText(mContext, "create successed", Toast.LENGTH_SHORT).show();
	}
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		db.execSQL("drop table if exists Book");
		db.execSQL("drop table if exists Category");
		onCreate(db);
		 Toast.makeText(mContext, "刪除數據", Toast.LENGTH_SHORT).show();
	}

}
MyDatabaseHelper(context, "BookStore.db", null, 1); 把這裡的版本號改成2就可以執行升級方法了
3 添加數據
public class MainActivity extends Activity {
	private MyDatabaseHelper dbHelper;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
		??
		Button addData = (Button) findViewById(R.id.add_data);
		addData.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				ContentValues values = new ContentValues();
				//  開始組裝第一條數據
				values.put("name", "The Da Vinci Code");
				values.put("author", "Dan Brown");
				values.put("pages", 454);
				values.put("price", 16.96);
				db.insert("Book", null, values); //  插入第一條數據
				values.clear();
				//  開始組裝第二條數據
				values.put("name", "The Lost Symbol");
				values.put("author", "Dan Brown");
				values.put("pages", 510);
				values.put("price", 19.95);
				db.insert("Book", null, values); //  插入第二條數據
			}
		});
	}
}
4 更新數據
public class MainActivity extends Activity {
	private MyDatabaseHelper dbHelper;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
		??
		Button updateData = (Button) findViewById(R.id.update_data);
		updateData.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				ContentValues values = new ContentValues();
				values.put("price", 10.99);
				db.update("Book", values, "name = ?", new String[] { "The Da
						Vinci Code" });
				}
			});
		}
	}
db.update("Book", values, "name = ?", new String[] { "The DaVinci Code" }) 這句話相當於 Update Book set price=10.99 where name=’The DaVinci Code"‘   5 刪除數據
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
??
Button deleteButton = (Button) findViewById(R.id.delete_data);
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "500" });
}
});
}
}
db.delete("Book", "pages > ?", new String[] { "500" }); 相當於 delete from Book where pages>500 6 查詢數據
public class MainActivity extends Activity {
	private MyDatabaseHelper dbHelper;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
		??
		Button queryButton = (Button) findViewById(R.id.query_data);
		queryButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				//  查詢Book 表中所有的數據
				Cursor cursor = db.query("Book", null, null, null, null, null, null);
				if (cursor.moveToFirst()) {
					do {
						//  遍歷Cursor 對象,取出數據並打印
						String name = cursor.getString(cursor.
								getColumnIndex("name"));
						String author = cursor.getString(cursor.
								getColumnIndex("author"));
						int pages = cursor.getInt(cursor.getColumnIndex
								("pages"));
						double price = cursor.getDouble(cursor.
								getColumnIndex("price"));
						Log.d("MainActivity", "book name is " + name);
						Log.d("MainActivity", "book author is " + author);
						Log.d("MainActivity", "book pages is " + pages);
						Log.d("MainActivity", "book price is " + price);
					} while (cursor.moveToNext());
				}
				cursor.close();
			}
		});
	}
}
7 使用 SQL 操作數據庫
下面我就來簡略演示一下, 如何直接使用 SQL 來完成前面幾小節中學過的 CRUD 操作。添加數據的方法如下:
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] { "The Da Vinci Code", "Dan Brown", "454", "16.96" });
db.execSQL("insert into Book (name, author, pages, price) values(?, ?, ?, ?)",
new String[] { "The Lost Symbol", "Dan Brown", "510", "19.95" });
更新數據的方法如下:
db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99",
"The Da Vinci Code" });
刪除數據的方法如下:
db.execSQL("delete from Book where pages > ?", new String[] { "500" });
查詢數據的方法如下:
db.rawQuery("select * from Book", null);
可以看到, 除了查詢數據的時候調用的是 SQLiteDatabase 的 rawQuery()方法, 其他的操
作都是調用的 execSQL()方法。以上演示的幾種方式,執行結果會和前面幾小節中我們學習
的 CRUD 操作的結果完全相同,選擇使用哪一種方式就看你個人的喜好了 8.使用事務 想象以下場景,比如你正在進行一次轉賬操作,銀行會將轉賬的金額先從你的賬戶中扣除,然後再向收款方的賬戶中添加等量的金額。 看上去好像沒什麼問題吧?可是, 如果當你賬戶中的金額剛剛被扣除,這時由於一些異常原因導致對方收款失敗,這一部分錢就憑空消失了!當然銀行肯定已經充分考慮到了這種情況, 它會保證扣錢和收款的操作要麼一起成功, 要麼都不會成功,而使用的技術當然就是事務了。
public class MainActivity extends Activity {
	private MyDatabaseHelper dbHelper;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
		??
		Button replaceData = (Button) findViewById(R.id.replace_data);
		replaceData.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				SQLiteDatabase db = dbHelper.getWritableDatabase();
				db.beginTransaction(); //  開啟事務
				try {
					db.delete("Book", null, null);
					if (true) {
						//  在這裡手動拋出一個異常,讓事務失敗
						throw new NullPointerException();
					}
					ContentValues values = new ContentValues();
					values.put("name", "Game of Thrones");
					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(); //  結束事務
				}
			}
		});
	}
}
8. 2升級數據庫的最佳寫法 只需要創建一張 Book 表,MyDatabaseHelper 中的代碼如下所示:
public class MyDatabaseHelper extends SQLiteOpenHelper {
	public static final String CREATE_BOOK = "create table Book ("
			+ "id integer primary key autoincrement, "
			+ "author text, "
			+ "price real, "
			+ "pages integer, "
			+ "name text)";
	public MyDatabaseHelper(Context context, String name, CursorFactory
			factory, int version) {
		super(context, name, factory, version);
	}
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_BOOK);
	}
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	}
}
不過,幾星期之後又有了新需求,這次需要向數據庫中再添加一張 Category 表。於是,修改 MyDatabaseHelper 中的代碼,如下所示:
public class MyDatabaseHelper extends SQLiteOpenHelper {
	public static final String CREATE_BOOK = "create table Book ("
			+ "id integer 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)";
	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
	}
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_BOOK);
		db.execSQL(CREATE_CATEGORY);
	}
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		switch (oldVersion) {
		case 1:
			db.execSQL(CREATE_CATEGORY);
		default:
		}
	}
}
是沒過多久,新的需求又來了,這次要給 Book 表和 Category 表之間建立關聯,需要在 Book 表中添加一個 category_id 的字段。再次修改 MyDatabaseHelper 中的代碼,如下所示
public class MyDatabaseHelper extends SQLiteOpenHelper {
	public static final String CREATE_BOOK = "create table Book ("
			+ "id integer 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)";
	public MyDatabaseHelper(Context context, String name,
			CursorFactory factory, int version) {
		super(context, name, factory, version);
	}
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_BOOK);
		db.execSQL(CREATE_CATEGORY);
	}
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		switch (oldVersion) {
		case 1:
			db.execSQL(CREATE_CATEGORY);
		case 2:
			db.execSQL("alter table Book add column category_id integer");
		default:
		}
	}
}
可以看到,首先我們在 Book 表的建表語句中添加了一個 category_id 列,這樣當用戶直
接安裝第三版的程序時,這個新增的列就已經自動添加成功了。然而,如果用戶之前已經安
裝了某一版本的程序, 現在需要覆蓋安裝, 就會進入到升級數據庫的操作中。 在 onUpgrade()
方法裡,我們添加了一個新的 case,如果當前數據庫的版本號是 2,就會執行 alter 命令來為
Book 表新增一個 category_id 列。

這裡請注意一個非常重要的細節,switch 中每一個 case 的最後都是沒有使用 break 的,
為什麼要這麼做呢?這是為了保證在跨版本升級的時候, 每一次的數據庫修改都能被全部執
行到。比如用戶當前是從第二版程序升級到第三版程序的,那麼 case 2 中的邏輯就會執行。
而如果用戶是直接從第一版程序升級到第三版程序的, 那麼 case 1 和 case 2 中的邏輯都會執
行。使用這種方式來維護數據庫的升級,不管版本怎樣更新,都可以保證數據庫的表結構是
最新的,而且表中的數據也完全不會丟失了。

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