2014-11-05 13 views
9

Codebeispiele von Android SQLite-Transaktionen, die ich gesehen habe, scheinen automatisch db.setTransactionSuccessful() kurz vor db.endTransaction() aufzurufen.Android - wann db.setTransactionSuccessful() aufrufen?

Ich frage mich, ob das tatsächlich Best Practice oder ob es eine bedingte Überprüfung vor dem Aufruf db.setTransactionSuccessful() sein sollte.

In meinem Fall bin ich zwingende ContentProvider ‚s bulkInsert() Methode, und wenn ich eine bedingte Scheck verwenden, wie beschrieben, wird meine Methode wie folgt aussehen ...

@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); 
    } 
} 

... dann ist dies der richtige Ansatz ?

Und welche Aktion sollte ich in dem Fall, wo allInsertAttemptsWereSuccessful == false ??

(Ich habe in den Android docs gesucht, aber nur sehr wenig Informationen zur Verfügung gestellt.)

Update - Neuer Code ...

Dank laalto's answer, dies ist mein neuer (richtiger) Code. ..

/** 
* 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); 
    } 
} 

Antwort

9

Die kanonische Muster für Transaktionen:

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

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

Dies stellt sicher, dass es immer endTransaction() (keine baumelnden Transaktionen zurückgelassenen) genannt wird, und die Transaktion wird rückgängig gemacht, wenn eine Ausnahme in einigen Datenbankoperation auftritt. Wenn Sie die Transaktion aus einem eigenen Grund abbrechen möchten, rufen Sie nicht setTransactionSuccessful() auf, oder werfen Sie eine Ausnahme aus.

+0

Danke für alle Antworten. Laalto, ich habe meinen Code aktualisiert (und ihn zu meiner Frage hinzugefügt) in Übereinstimmung mit Ihrer Eingabe. Prost. –

0

Normalerweise setTransactionSuccessful ist getan kurz vor endTransaction.

Sie können auch aufrufen, nachdem alle Ihre db-Operation für die Transaktion abgeschlossen sind. Aber dann kann es keinen logischen Grund geben, die endTransaction zu verzögern. Hängt von deiner Logik ab. Wenn Sie sicherstellen möchten, dass ein Teil des Java-Codes erfolgreich ausgeführt werden soll, bevor Sie die Änderungen an db übergeben, können Sie setTransactionSuccessful und endTransaction forthur nach unten verschieben.

Im Falle einer Ausnahme in der Logik zwischen startTransaction und endTransation, kann es am Ende mit offener Transaktion und Verhungern enden (aus Ihrem Code ist klar, dass dbHelper Mitgliedvariable ist. Sie werden also den gleichen dbHelper in allen verwenden) Ihr Inhaltsanbieter ruft an). Die gleiche dbHelper-Instanz impliziert dieselbe SqliteDatabase-Instanz.

Also müssen Sie versuchen, fangen und beenden Sie die Transaktion schließlich.

0

Keine Notwendigkeit, den Zustand für db.setTransactionSuccessful() zu überprüfen. Nach der Anweisung einfügen können wir db.setTransactionSuccessful() Anweisung schreiben. Es wird die Transaktion abwickeln.

Beispielcode:

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(); 
    } 
} 
Verwandte Themen