天天看點

Android資料庫小技巧

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,如需轉載請自行聯系原作者