Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple rows insert with ContentProvider

I need to make insert of few rows in one transaction. Can I do it with ContentProvider?

like image 439
earsonheart Avatar asked Jul 27 '11 09:07

earsonheart


1 Answers

I have implemented this in my app and here's the gist of the code that I use.

In my content provider, I have overridden the applyBatch() method and it's a very simple method to override:

/**
 * Performs the work provided in a single transaction
 */
@Override
public ContentProviderResult[] applyBatch(
        ArrayList<ContentProviderOperation> operations) {
    ContentProviderResult[] result = new ContentProviderResult[operations
            .size()];
    int i = 0;
    // Opens the database object in "write" mode.
    SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    // Begin a transaction
    db.beginTransaction();
    try {
        for (ContentProviderOperation operation : operations) {
            // Chain the result for back references
            result[i++] = operation.apply(this, result, i);
        }

        db.setTransactionSuccessful();
    } catch (OperationApplicationException e) {
        Log.d(TAG, "batch failed: " + e.getLocalizedMessage());
    } finally {
        db.endTransaction();
    }

    return result;
}

The result is given to the next operation because you want to support back references. When I actually want to change stuff in the database in this single transaction I loop over my content and do stuff like this:

operations.add(ContentProviderOperation
                    .newInsert(
                            Uri.withAppendedPath(
                                    NotePad.Notes.CONTENT_ID_URI_BASE,
                                    Long.toString(task.dbId)))
                    .withValues(task.toNotesContentValues(0, listDbId))
                    .build());
// Now the other table, use back reference to the id the note
// received
noteIdIndex = operations.size() - 1;

operations.add(ContentProviderOperation
                    .newInsert(NotePad.GTasks.CONTENT_URI)
                    .withValues(task.toGTasksContentValues(accountName))
                    .withValueBackReferences(
                            task.toGTasksBackRefContentValues(noteIdIndex))
                    .build());

You just need to remember to finish by calling:

provider.applyBatch(operations);

This will perform your stuff in a single transaction and supports backreferences if you need the id from an earlier insert without issue.

like image 75
Jonas Kalderstam Avatar answered Oct 11 '22 05:10

Jonas Kalderstam