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

3lxsmp7m  于 2022-12-25  发布在  Android
关注(0)|答案(4)|浏览(147)

我所看到的Android SQLite事务的代码示例似乎在db.endTransaction()之前自动调用db.setTransactionSuccessful()
我想知道这是否是最佳实践,或者在调用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文档,但提供的信息很少。)

更新-新代码...

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

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

new9mtju1#

事务的规范模式:

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

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

这确保了endTransaction()总是被调用(没有悬空事务留下),并且当某个数据库操作中发生异常时,事务会被回滚。如果你因为自己的原因想中止事务,就不要调用setTransactionSuccessful(),或者抛出异常。

tuwxkamq

tuwxkamq2#

通常,setTransactionSuccessful在endTransaction之前完成。
您也可以在对事务执行完所有数据库操作之后调用。但是这样可能就没有任何逻辑原因延迟endTransaction了。这取决于您的逻辑。如果您想确保在将更改提交到数据库之前Java代码的某个部分应该成功执行,您可以将setTransactionSuccessful和endTransaction进一步下移。
如果在startTransaction和endTransation之间编写的逻辑中出现任何异常,则可能以打开事务和饥饿结束(从您的代码中可以清楚地看到dbHelper是成员变量,因此您将在所有内容提供程序调用中使用相同的dbHelper)。相同的dbHelper示例意味着相同的SqliteDatabase示例。
因此,您必须添加try catch并在finally中结束事务。

ttisahbt

ttisahbt3#

不需要检查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(); 
    }   
}
zc0qhyus

zc0qhyus4#

这些方法现在已弃用,因此可以使用以下代码片段:

roomDB.runInTransaction(() -> {
     // do your job here
});

相关问题