2014-11-05 12 views
9

Przykłady kodów transakcji Android SQLite, które widziałem, wydają się automatycznie wywoływać db.setTransactionSuccessful() tuż przed db.endTransaction().Android - kiedy zadzwonić do db.setTransactionSuccessful()?

Zastanawiam się, czy to rzeczywiście najlepsza praktyka lub czy przed wybraniem numeru db.setTransactionSuccessful() powinno nastąpić sprawdzenie warunkowe.

W moim przypadku, ja nadrzędnymi bulkInsert() metodę ContentProvider „s i jeśli mogę użyć czek warunkowego, jak opisano, moja metoda będzie wyglądać następująco ...

@Override 
public int bulkInsert(Uri uri, ContentValues[] valuesArray) { 

    // Open a read/write database to support the transaction. 
    SQLiteDatabase db = dbHelper.getWritableDatabase(); 

    switch (uriMatcher.match(uri)) { 
     case BRANDS_SEARCH: 

      int numInserts = 0; 

      db.beginTransaction(); 

      for (int i = 0; i < valuesArray.length; i++) { 

       // Insert the values into the table 
       long rowId = db.insert(BRAND_NAMES_TABLE, null, valuesArray[i]); 

       if (rowId > -1) { 

        // Increment numInserts 
        numInserts++; 

        // Construct the URI of the newly inserted row. 
        Uri insertedId = ContentUris.withAppendedId(CONTENT_URI_BRANDS, rowId); 

        // Notify any observers of the change in the data set. 
        getContext().getContentResolver().notifyChange(insertedId, null); 

       } 

      } 

      boolean allInsertAttemptsWereSuccessful = (numInserts == valuesArray.length); 

      if (allInsertAttemptsWereSuccessful) { 
       db.setTransactionSuccessful(); //todo - should this be conditional? 
      } 
      else { 
       //todo - ??? 
      } 

      db.endTransaction(); 

      return numInserts; 

     default: 
      //break; 
      throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
} 

... czy to jest prawidłowe podejście ?

A jakie działania należy podjąć w przypadku, gdy allInsertAttemptsWereSuccessful == false?

(Szukałem w Android docs, ale bardzo mało informacji jest przewidziane.)

Update - New Code ...

Dzięki laalto's answer, to moja nowa (poprawna) kod. ..

/** 
* Attempts a bulk insert. Outcome will either be all inserts succeeded 
* or all inserts failed. 
*/ 
@Override 
public int bulkInsert(Uri uri, ContentValues[] valuesArray) { 

    /* 
    * Open a read/write database to support the transaction. 
    */ 
    SQLiteDatabase db = dbHelper.getWritableDatabase(); 

    switch (uriMatcher.match(uri)) { 
     case BRANDS_SEARCH: 

      /* 
      * Begin the transaction 
      */ 
      db.beginTransaction(); 

      try { 

       for (int i = 0; i < valuesArray.length; i++) { 

        /* 
        * Insert the values into the table 
        */ 
        long rowId = db.insert(BRAND_NAMES_TABLE, null, valuesArray[i]); 

        if (rowId > -1) { 

         /* 
         * Construct the URI of the newly inserted row. 
         */ 
         Uri insertedId = ContentUris.withAppendedId(CONTENT_URI_BRANDS, rowId); 

         /* 
         * Notify any observers of the change in the data set. 
         */ 
         getContext().getContentResolver().notifyChange(insertedId, null); 

        } 
        else { 

         /* 
         * Give up (as we need all insert attempts to succeed) 
         */ 
         throw new Exception("Could not insert row"); 
        } 

       } 

       /* 
       * All insert attempts succeeded 
       */ 
       db.setTransactionSuccessful(); 

       return valuesArray.length; 
      } 
      catch(Exception e) { 

       /* 
       * If any insert attempt failed, then setTransactionSuccessful() will not be called so no rows will actually be inserted 
       */ 
       return 0; 

      } 
      finally { 

       /* 
       * Always end the transaction 
       */ 
       db.endTransaction(); 
      } 

     default: 
      //break; 
      throw new IllegalArgumentException("Unsupported URI: " + uri); 
    } 
} 

Odpowiedz

9

Kanoniczna wzór dla transakcji:

beginTransaction(); 
try { 
    //db operations ... 

    setTransactionSuccessful(); 
} finally { 
    endTransaction(); 
} 

Gwarantuje to, że nie zawsze jest nazywany endTransaction() (żadne transakcje wiszące pozostawił), a transakcja zostanie wycofana, gdy wystąpi wyjątek w jakiejś operacji bazy danych. Jeśli chcesz przerwać transakcję z własnego powodu, po prostu nie dzwoń pod numer setTransactionSuccessful() lub wyślij wyjątek.

+0

Dzięki za wszystkie odpowiedzi. Laalto, zaktualizowałem swój kod (i dodałem go do mojego pytania) zgodnie z twoimi danymi wejściowymi. Twoje zdrowie. –

0

Normalnie setTransaction zakończyło się sukcesem tuż przed endTransaction.

Możesz także zadzwonić zaraz po wykonaniu wszystkich operacji db dla transakcji. Ale może nie być żadnego logicznego powodu opóźnienia endTransaction. Zależy od twojej logiki. Jeśli chcesz się upewnić, że pewna sekcja kodu java powinna zostać pomyślnie wykonana przed zatwierdzeniem danych w db, możesz przenieść setTransactionSuccessful i endTransaction furthur w dół.

W przypadku jakiegokolwiek wyjątku w logice zapisanej między startTransaction i endTransation, może to skończyć się otwartą transakcją i głodem (z twojego kodu jest jasne, że dbHelper jest zmienną składową, więc będziesz używał tego samego dbHelper we wszystkich połączenia z dostawcą treści). ta sama instancja dbHelper implikuje taką samą instancję SqliteDatabase.

Musisz więc dodać try catch i zakończyć transakcję w końcu.

0

Nie trzeba sprawdzać stanu dla db.setTransactionSuccessful(). Po instrukcji insert możemy napisać instrukcję db.setTransactionSuccessful(). Będzie obsługiwać transakcję.

Przykładowy kod:

public void insertActivity(ActivityModel mModel){ 
    db = getWritableDatabase(); 
    ContentValues cv = new ContentValues(); 
    try { 
     db.beginTransaction(); 

     cv.put("id",mModel.getForm_id()); 
     cv.put("_name",mModel.getForm_name()); 
     cv.put("version_id",mModel.getLog_version_id()); 

     db.insert("activity_type_status_mapping", null, cv); 
     db.setTransactionSuccessful(); 

    } catch (Exception e){ 
     e.printStackTrace(); 
    } finally { 
     db.endTransaction(); 
     db.close(); 
    } 
} 
Powiązane problemy