Android – 何时调用db.setTransactionSuccessful()?

我见过的Android SQLite事务的代码示例似乎在db.setTransactionSuccessful()之前自动调用db.endTransaction()

我想知道,如果这实际上是最佳做法或是否应该有一个条件检查之前调用db.setTransactionSuccessful()

在我的情况下,我重写ContentProviderbulkInsert()方法,如果我使用条件检查描述,我的方法将看起来像这样…

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

…这是正确的方法吗?

allInsertAttemptsWereSuccessful == false的情况下,我应该采取什么行动?

(我看过Android文档 ,但提供的信息非常less。)

更新 – 新代码…

感谢laalto的回答 ,这是我的新(正确的)代码…

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

Solutions Collecting From Web of "Android – 何时调用db.setTransactionSuccessful()?"

交易的规范模式:

 beginTransaction(); try { //db operations ... setTransactionSuccessful(); } finally { endTransaction(); } 

这确保了endTransaction()总是被调用(没有悬而未决的事务留下),并且当某些数据库操作发生exception时事务被回滚。 如果您想因为您自己的原因而中止事务,则不要调用setTransactionSuccessful()或抛出exception。

通常setTransactionSuccessful在endTransaction之前完成。

您也可以在所有数据库操作完成后立即调用事务。 但是,延迟endTransaction可能没有任何逻辑的理由。 取决于你的逻辑。 如果要确保在将chages提交到db之前,某些java代码段应该成功执行,则可以将setTransactionSuccessful和endTransaction向下移动。

如果在startTransaction和endTransation之间写入的逻辑中有任何exception,那么它可能会以open transaction和starvation结束(从你的代码中可以清楚的知道dbHelper是成员variables),所以你将在所有的内容提供者调用中使用相同的dbHelper )。 相同的dbHelper实例隐含着相同的SqliteDatabase实例。

所以你必须添加try catch,并最终结束交易。

不需要检查db.setTransactionSuccessful()的条件。 插入语句之后,我们可以编写db.setTransactionSuccessful()语句。 它将处理交易。

示例代码:

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