我需要在一個事務中插入幾行。我可以用ContentProvider做到嗎?用ContentProvider插入多行
回答
在客戶端,ContentResolver
支持bulkInsert()
方法。這些將不一定由ContentProvider
在一筆交易中處理,僅僅是因爲ContentProvider
可能沒有執行任何交易。
據我所知,如果不是o verrriden - 它只會叫幾個standrt'插入'方法? – earsonheart
正確。你不知道是否有給定的'ContentProvider'重載'bulkInsert()',除非它是你自己的'ContentProvider'。 – 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;
}
結果是考慮到下一步的操作。當我其實是想在這單交易我遍歷我的內容改變的東西在數據庫中,做的東西是這樣的:
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個bulkInsert執行100毫秒。 –
我也用替換模式,插入行 - db.insertWithOnConflict(EVENT_TABLE_NAME,空,值,SQLiteDatabase.CONFLICT_REPLACE); 它會擺脫衝突的,如果記錄已經存在
在DatabaseHelper添加UNIQUE INDEX
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;
}
並調用bulkInsert這樣的:
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. 使用ContentProvider插入到多個表格
- 2. 使用插入或ContentProvider的
- 3. 使用ContentProvider插入數組
- 4. ContentProvider插入失敗
- 5. ContentProvider插入不插入數據到SQLiteDatabase
- 6. 插入失敗與ContentProvider
- 7. 從contentprovider中刪除多行
- 8. 插入多行插入表和插入
- 9. 插入多行
- 10. 插入多行
- 11. 插入多行
- 12. 有多少ContentProvider?
- 13. 用SQL/PHP插入多行
- 14. 用PHP PDO插入多行
- 15. 使用implode插入多行
- 16. 使用select插入多行
- 17. 使用psycopg2插入多行
- 18. 用PHP插入多行
- 19. 使用JdbcTemplate插入多行
- 20. Oracle插入多行
- 21. Sed插入多行
- 22. SQL插入多行
- 23. PHP插入多行
- 24. 插入多行RockMongo
- 25. Linq多行插入
- 26. 插入多行SQL
- 27. ZF2插入多行
- 28. SQL插入多行
- 29. ContentProvider和多線程
- 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