Android小技巧(二):爲ContentProvider添加數據庫事務支持

轉載請註明出處。博客地址:http://blog.csdn.net/mylzc
java

介紹:數據庫事務是由一組數據庫操做序列組成,事務做爲一個總體被執行。sql

事務的原子性:包含在其中的對數據庫的操做序列最終要麼所有執行,要麼所有不執行。當所有執行時,事務對數據庫的修改將生效;當所有不執行時,數據庫維持原有的狀態,不會被修改。數據庫

問題:最近在作一個從sdcard導入數據到數據庫的功能,當導入失敗時,數據庫要恢復到導入前的狀態。使用數據庫事務處理能很好地知足到咱們的需求。設計模式

咱們知道Android平臺上使用的sqlite數據庫是支持事務處理功能的,實現的代碼以下:app

[java] view plain copy
  1. SQLiteDatabase db =mOpenHelper.getWritableDatabase();  
  2.                    db.beginTransaction();//開始事務  
  3. //進行insertdelete update等數據庫操做  
  4. db.setTransactionSuccessful();//設置事務標記爲Successful  
  5. db.endTransaction();//提交事務  

但是,對於已經封裝成ContentProvider的Sqlite咱們應該如何讓其支持事務處理功能呢?ide

解決辦法:查看ContentProvider的API說明文檔,咱們驚喜地發現 applyBatch(String authority,ArrayList<ContentProviderOperation> operations)這個方法,難道只須要直接使用這個方法就能夠實現事務了?ui

謹慎起見咱們先來看看ContentProvider的源碼,最後追蹤到這個方法:this

[java] view plain copy
  1. public ContentProviderResult[]applyBatch(ArrayList<ContentProviderOperation> operations)  
  2.             throwsOperationApplicationException {  
  3.        final int numOperations = operations.size();  
  4.        final ContentProviderResult[] results = newContentProviderResult[numOperations];  
  5.        for (int i = 0; i < numOperations; i++) {//遍歷數據庫操做序列  
  6.             results[i] =operations.get(i).apply(this, results, i);//執行數據庫操做  
  7.        }  
  8.        return results;//返回結果  
  9.    }  


從上面的代碼中,咱們找不到和db.beginTransaction()、db.endTransaction()類似的方法,也就是說,這個方法只是進行簡單的批處理,並無保障這些數據庫操做的原子性。spa

好吧。咱們稍微動下腦筋,覆寫ContentProvider的applyBatch()方法,爲其添加事務處理功能。代碼以下:.net

[java] view plain copy
  1. @Override  
  2. publicContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation>operations)  
  3.             throwsOperationApplicationException{  
  4.           SQLiteDatabasedb = mOpenHelper.getWritableDatabase();  
  5.           db.beginTransaction();//開始事務  
  6.           try{  
  7.                    ContentProviderResult[]results = super.applyBatch(operations);  
  8.                    db.setTransactionSuccessful();//設置事務標記爲successful  
  9.                    returnresults;  
  10.           }finally {  
  11.                    db.endTransaction();//結束事務  
  12.           }  
  13. }  


而後,咱們該如何使用這個applyBatch()方法呢?applyBatch()的第一個參數實現事務的Provider的authority 屬性,第二個參數是數據庫操做序列,構建數據庫操做的對象使用了builder設計模式,下面是一個使用applyBatch()的例子:

[java] view plain copy
  1. ArrayList<ContentProviderOperation>ops = new ArrayList<ContentProviderOperation>();  
  2. ops.add(ContentProviderOperation.newDelete(Person.CONTENT_URI).build());//添加一個刪除Person表的操做  
  3. ops.add(ContentProviderOperation.newInsert(Home.CONTENT_URI).withValues(values).build());//添加一條記錄到Home表  
  4. getContentResolver().applyBatch(PROVIDER.AUTHORITY,ops);//處理事務  

總結:

一、sqlite支持事務處理操做

二、對於封裝成ContentProvider的sqlite數據庫,咱們能夠經過覆寫ContentProvider的applyBatch(Stringauthority, ArrayList<ContentProviderOperation> operations)方法來實現對事務處理的支持

相關文章
相關標籤/搜索