Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

inserting to multiple tables with ContentProvider

I'm implementing a PRIVATE ContentProvider which has few tables with relationships (one to many, many to many). In my current implementation all of the tables are accessible by URIs. how can I simplify the interface so the inner 'through' tables won't have to be accessed by URIs ?

for example, I have a POSTS table, each POST has many TAGS through the TAGGINGS table. I want to interact only with the POSTS URI and do the 'private' work inside of the ContentProvider.

for query its simple to return a cursor with joined tables, but how do I do this with insert ? is bulkInsert what I should look into ?

like image 763
Gal Ben-Haim Avatar asked Jan 16 '23 02:01

Gal Ben-Haim


1 Answers

It is a limitation of ContentProvider. If you are not exposing your data to other applications you can use your custom database adapter implementation with methods and queries straight hitting your requirements.

bulkInsert() won't help in this situation as it inserts rows only into one table at once. But take a look at ContentProvider.applyBatch() method and ContentProviderOperation, ContentProviderOperation.Builder classes (you may need withValueBackReference() for one-to-many inserting).

These links should help you understand how to use them:

http://www.grokkingandroid.com/better-performance-with-contentprovideroperation/ http://www.grokkingandroid.com/androids-contentprovideroperation-withbackreference-explained/ What are the semantics of withValueBackReference?

But notice, using ContentProviderOperation is much slower than bulkInsert() if you are inserting many rows at once, as it parses Uri (string comparisions) each time the operation is going to be performed. Doing this way you still have to expose Uri for inserting into child table.

If you decide to use applyBatch(), overwrite it in your provider so it performs all operations in one transaction, so you retain consistency in data and speed up database operations:

@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
        throws OperationApplicationException {
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    db.beginTransaction();
    try {
        ContentProviderResult[] results = super.applyBatch(operations);
        db.setTransactionSuccessful();
        return results;
    } finally {
        db.endTransaction();
    }
}
like image 66
biegleux Avatar answered Jan 28 '23 05:01

biegleux