1回のトランザクションで少数の行を挿入する必要があります。 ContentProviderでこれを行うことはできますか?ContentProviderを使用した複数行の挿入
答えて
クライアント側では、ContentResolver
がbulkInsert()
メソッドをサポートしています。 ContentProvider
によって実行される取引がない可能性があるため、これらは必ずContentProvider
によって1回の取引で処理されるとは限りません。
私が理解しているように、 verrriden - それはちょうどstandrt '挿入'メソッドを呼び出しませんか? – earsonheart
正しい。与えられた 'ContentProvider'があなた自身の' ContentProvider'でない限り、 'bulkInsert()'をオーバーライドするかどうか分かりません。 – CommonsWare
私はContentProviderOperationsと一緒に行くべきだと思っています。このチュートリアルhttp://www.grokkingandroid.com/better-performance-with-contentprovideroperation/ –
私はこれを私のアプリで実装していますが、ここでは私が使用するコードの要点です。私のコンテンツプロバイダで
、私はapplyBatch()メソッドをオーバーライドして、それは上書きすることは非常に簡単な方法です:あなたが参照をバックサポートしたいので
/**
* 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;
}
結果は、次の動作に与えられています。私は実際に私のコンテンツに対するこの単一のトランザクションIループ内のデータベースで何かを変更し、このようなものをしたいときは:
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());
あなただけ呼び出すことによって終了する覚えておく必要があります。
provider.applyBatch(operations);
この以前の挿入物からのIDが問題なく必要な場合は、単一のトランザクションであなたのものを実行し、逆参照をサポートします。
ここbulkInsertため例:
/**
* Perform bulkInsert with use of transaction
*/
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
int uriType = 0;
int insertCount = 0;
try {
uriType = sURIMatcher.match(uri);
SQLiteDatabase sqlDB = dbHelper.getWritableDatabase();
switch (uriType) {
case MEASUREMENTS:
try {
sqlDB.beginTransaction();
for (ContentValues value : values) {
long id = sqlDB.insert(Tab_Measurements.TABLE_NAME, null, value);
if (id > 0)
insertCount++;
}
sqlDB.setTransactionSuccessful();
} catch (Exception e) {
// Your error handling
} finally {
sqlDB.endTransaction();
}
break;
default:
throw new IllegalArgumentException("Unknown URI: " + uri);
}
// getContext().getContentResolver().notifyChange(uri, null);
} catch (Exception e) {
// Your error handling
}
return insertCount;
}
そして、あなたのコードのようなもの:
/**
* Inserts new measurement information.
*
* @param ArrayList of measurements
* @return number of inserted entries
*/
public static long bulkInsertEntries(ArrayList<Item_Measurement> readings) {
// insert only if data is set correctly
if (readings.size() == 0)
return 0;
long insertCount = 0;
try {
// insert new entries
// ArrayList<ContentValues> valueList = new ArrayList<ContentValues>();
ContentValues[] valueList = new ContentValues[readings.size()];
int i = 0;
for (Item_Measurement reading : readings) {
ContentValues values = new ContentValues();
values.put(COL_TIME_READING, reading.getTimeReading());
// ...
valueList[i++] = values;
}
// returns ID
insertCount = ContentProviderOwn.getAppContext().getContentResolver()
.bulkInsert(ContentProviderOwn.MEASUREMENTS_URI_BASE, valueList);
} catch (Exception e) {
// Your error handling
}
return insertCount;
}
を元のデータ配列からループ内の正規の挿入物を呼び出すよりもどのように優れていますか? BulkInsertを使用するとパフォーマンス上の利点はありますか? –
@AndrewS bulkInsert()は大きな操作ではるかに優れています。私のアプリでちょうど完成した最適化:applyBatch()はいくつかのテーブルで2000回の操作で2000ミリ秒かかるが、10バルクインサートは100ミリ秒かかる。 –
私はまた、挿入行のモードを置き換える使用 - ヌル db.insertWithOnConflict(EVENT_TABLE_NAME、 、値、SQLiteDatabase.CONFLICT_REPLACE);レコードは、このようbulkInsertを
public class DataProvider extends ContentProvider {
private static class DatabaseHelper extends SQLiteOpenHelper {
DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db){
db.execSQL(CREATE_EVENT_TABLE);
db.execSQL("CREATE UNIQUE INDEX event_idx ON " + EVENT_TABLE_NAME + " (" + EventTable.EVENT_ID + ")");
// ...
...
@Override
public int bulkInsert(Uri uri, ContentValues[] values) {
Log.i(TAG, "bulkInsert");
if (values.length == 0)
return 0;
int insertCount = 0;
try {
switch (uriMatcher.match(uri)) {
case EVENT_LIST:
try {
db.beginTransaction();
for (ContentValues value : values) {
long id = db.insertWithOnConflict(EVENT_TABLE_NAME, null, value, SQLiteDatabase.CONFLICT_REPLACE);
if (id > 0)
insertCount++;
}
db.setTransactionSuccessful();
} catch (Exception e) {
// Your error handling
} finally {
db.endTransaction();
}
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
} catch (Exception e) {
Log.i(TAG, "Exception : " + e);
}
return insertCount;
}
をUNIQUE INDEXを追加し、呼すでにDatabaseHelperで
存在している場合 その競合を排除します:
ContentValues[] cvArr = new ContentValues[eventList.size()];
long insertCount = 0;
int i = 0;
for (Event event : eventList) {
ContentValues cv = new ContentValues();
cv.put(DataProvider.EventTable.EVENT_ID, event.id);
cv.put(DataProvider.EventTable.SENSOR_ID, event.sensor_id);
cv.put(DataProvider.EventTable.TIMESTAMP, event.time);
cvArr[i++] = cv;
}
// returns ID
insertCount = context.getContentResolver()
.bulkInsert(DataProvider.CONTENT_EVENT_LIST, cvArr);
- 1. oracleは、1つの挿入クエリを使用して複数の表に複数の行を挿入します。
- 2. 複数行の挿入の挿入
- 3. pdoのを使用してデータベースに複数行を挿入
- 4. 爆縮を使用して複数の行を挿入する
- 5. 挿入複数行
- 6. PHPを使用して複数行をデータベースに挿入
- 7. 挿入複数の行()
- 8. 複数行のテキストをOpenXMLを使用したリッチテキストコンテンツコントロールに挿入する
- 9. Smooks複数の挿入ポイントを使用したXML-XML変換
- 10. laravel 5.2複数のAJAXリクエストを使用した複数のAJAXリクエストを使用したバルク挿入toSql()のエラー
- 11. プリペインドステートメントを使用して空白行を挿入せずにMySQLに複数の行を挿入する方法
- 12. Android Contentprovider - 挿入メソッド内の更新
- 13. ORACLE ColdFusionにリストを使用して複数の行を挿入しますか?
- 14. 複数のContentProviderのCursorLoader
- 15. 複数のテキストボックスをLINQを使用して別の行にSQLテーブルに挿入
- 16. 複数の行を挿入するRockMongo
- 17. データベースLINQに複数の行を挿入
- 18. 複数の行をmysql DBに挿入
- 19. 複数の行を挿入する
- 20. Sed複数の行を挿入
- 21. PHP Mysql Ajax複数の行を挿入
- 22. Avroを使用して複数の列を含む行をBigQueryに挿入
- 23. PHPを使用してテーブルに複数の行を挿入する
- 24. 'for'ループを使用せずにグリッドビューに複数の行を挿入します。
- 25. Vimコマンドを使用して複数の行にテキストを挿入する
- 26. サブクエリを使用してMySQLに複数の行を挿入する
- 27. parallel.foreachを使用してデータベースに複数のレコードを挿入
- 28. Meteor.callを使用して複数のフィールドを挿入する
- 29. Android - push()を使用して複数のマーカーを挿入する
- 30. オブジェクトセットを使用して複数のレコードを挿入する
質問は不明..ですとにかくあなたがここのhttp見ることができます://developer.android.com/guide/topics/providers/content-providers.html#modifying –
http://stackoverflow.com/questions/5596354/insertion-of-thousands-of-contact-entries-using-applybatch -is-slow – Selvin