Android資料庫小技巧
<b>一、執行SQL</b>
相對于封裝過的ContentProvider,使用原生SQL執行效率高,是以建議使用rawQuery、execSQL。
<b>二、代理事務</b>
假設繼承SQLiteOpenHelper的資料庫操作類為DatabaseHelper。當它有比較多的方法都需要事務操作時,可以提取這些方法為一個接口,如ITransactionHandler,之後讓DatabaseHelper實作。這樣即可通過代理來統一完成事務操作!
/*
* 代理執行需要事物處理的資料庫操作方法
*
* 使用方式如下:
* DatabaseHelper mHelper = new DatabaseHelper(context);
* ITransactionHandler proxyHandler = (ITransactionHandler) TransactionHandler
* .newProxyInstance(mHelper);
* proxyHandler.resetDB();
*/
public class TransactionHandler implements InvocationHandler {
private static final String TAG = "TransactionHandler";
public static final boolean LOGD = true;
// 資料庫操作幫助類
private DatabaseHelper mDatabaseHelper;
public TransactionHandler(DatabaseHelper helper) {
this.mDatabaseHelper = helper;
}
// 傳回代理類的執行個體
public static Object newProxyInstance(DatabaseHelper helper) {
// 直接使用Proxy的靜态方法,傳回代理執行個體
return Proxy.newProxyInstance(helper.getClass().getClassLoader(),
helper.getClass().getInterfaces(), new TransactionHandler(
helper));
// 實作InvocationHandler接口方法,做自己的處理操作
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
long start = System.currentTimeMillis(); // 開始時間戳
Object result = null; // 方法傳回結果
SQLiteDatabase mDatabase = mDatabaseHelper.getWritableDatabase(); // 資料庫操作對象
mDatabase.beginTransaction(); // 開始事務
try {
// 代理執行資料庫操作方法
result = method.invoke(mDatabaseHelper, args);
// 執行事務操作(到結束事務間不能再進行資料庫操作)
mDatabase.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
/*
* 注意:這裡設false是由于我每個操作資料方法都傳回的是boolean。
* 1)要增加不同的類型,可以用instanceof判斷
* 2)在invoke内出問題沒傳回result對象的情況,可考慮把異常分開捕獲,或者判null
*/
result = false;
} finally {
mDatabase.endTransaction(); // 結束事務
}
long end = System.currentTimeMillis(); // 結束時間戳
if (LOGD)
Log.d(TAG, "==" + method.getName() + " method lasts "
+ (end - start) + "ms==");
return result;
}
<b>三、檔案SQL</b>
執行一個SQL檔案,以初始化資料等。可以把sql檔案放在res/raw目錄内。sql文注釋方式,簡易為“—”開頭的行或“/*”“*/”開始的兩行中間。
public class SqlUtil {
private final String commentPrefix = "--";
private final String prefix = "/*";
private final String suffix = "*/";
private boolean isComment = false;
private Context mContext;
private SQLiteDatabase db;
public SqlUtil(Context context, SQLiteDatabase db) {
mContext = context;
this.db = db;
// 執行raw内的簡易sql檔案
public void execute(int rawId) {
BufferedReader reader = null;
InputStream is = mContext.getResources().openRawResource(rawId);
reader = new BufferedReader(new InputStreamReader(is));
for (String s; (s = reader.readLine()) != null;) {
if (s.startsWith(commentPrefix)) {
continue;
}
if (s.startsWith(prefix)) {
isComment = true;
if (s.startsWith(suffix)) {
isComment = false;
if (isComment) {
db.execSQL(s);
}
} catch (IOException e) {
try {
if (null != reader) {
reader.close();
} catch (IOException e) {
<b>四、後記</b>
其他的話,暫時應該沒什麼了…
本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/900853,如需轉載請自行聯系原作者