Android - 什么时候调用db.setTransactionSuccessful()?

时间:2014-11-05 11:26:57

标签: android sqlite transactions

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

我想知道这是否是最佳做法,或者在致电db.setTransactionSuccessful()之前是否应该进行一些有条件的检查。

在我的情况下,我正在覆盖ContentProvider的{​​{1}}方法,如果我按照描述使用条件检查,我的方法将如下所示......

bulkInsert()

......这是正确的方法吗?

@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 ??

的情况下,我应采取什么行动?

(我查看了Android docs,但提供的信息非常少。)

更新 - 新代码......

感谢laalto's answer,这是我的新(正确)代码......

false

3 个答案:

答案 0 :(得分:12)

交易的规范模式:

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

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

这确保始终调用endTransaction()(不留下悬空事务),并且在某些数据库操作中发生异常时回滚事务。如果您想出于自己的原因而中止交易,请不要致电setTransactionSuccessful()或抛出异常。

答案 1 :(得分:1)

通常setTransactionSuccessful在endTransaction之前完成。

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

如果在startTransaction和endTransation之间写入的逻辑中有任何异常,那么它最终可能会打开事务和饥饿(从您的代码中可以清楚地看到dbHelper是成员变量。所以你将在所有的中使用相同的dbHelper内容提供商电话)。相同的dbHelper实例意味着相同的SqliteDatabase实例。

所以你必须添加try catch并最终结束事务。

答案 2 :(得分:1)

无需检查db.setTransactionSuccessful()的条件。在insert语句之后我们可以编写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(); 
    }   
}