Potrzebuję wstawić kilka wierszy w jednej transakcji. Czy mogę to zrobić za pomocą ContentProvider?Wstawianie wielu wierszy za pomocą ContentProvider
Odpowiedz
Po stronie klienta ContentResolver
obsługuje metodę bulkInsert()
. Te nie koniecznie będą przetwarzane w pojedynczej transakcji przez ContentProvider
, po prostu dlatego, że nie mogą być przeprowadzane żadne transakcje przez ContentProvider
.
Jak rozumiem, jeśli to nie jest o verrriden - po prostu wywoła kilka metod "wstawiania" standardu? – earsonheart
Prawidłowo. Nie masz pojęcia, czy dany 'ContentProvider' nadpisuje' bulkInsert() ', chyba że jest to twój własny" ContentProvider ". – CommonsWare
Myślę, że powinieneś pójść z ContentProviderOperations, przeczytaj ten samouczek: http://www.grokkingandroid.com/better-performance- with-contentprovideroperation/ –
Zaimplementowałem to w mojej aplikacji i tutaj jest sens kodu, którego używam.
W moim dostawcy treści, mam przesłonięte metody applyBatch() i jest to bardzo prosta metoda, aby zastąpić:
/**
* 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;
}
Wynik podawany jest do następnej operacji, ponieważ chcemy, aby wesprzeć powrót referencje. Kiedy rzeczywiście chcesz zmienić rzeczy w bazie danych, w tym jednej pętli transakcja I nad moim zawartości i robić rzeczy tak:
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());
Trzeba tylko pamiętać, aby zakończyć przez wywołanie:
provider.applyBatch(operations);
ten wykona twoje rzeczy w pojedynczej transakcji i obsługuje odsyłacze wstecz, jeśli potrzebujesz identyfikatora z wcześniejszej wstawki bez problemu.
tutaj jakiś przykładem 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;
}
I w kodzie coś takiego:
/**
* 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;
}
Jak to jest lepsze niż wywoływanie zwykłego wstawienia w pętli z oryginalnej tablicy danych? Czy wydajność w korzystaniu z BulkInsert jest lepsza? –
@AndrewS bulkInsert() jest znacznie lepszy w dużych operacjach. Właśnie zakończyłem optymalizację w mojej aplikacji: applyBatch() z 2000 operacjami na kilku tabelach zajmuje 2000 ms, 10 bulkInsert's trwa 100 ms. –
ja również użyć trybu wymienić na wkładkę rzędu - db.insertWithOnConflict (EVENT_TABLE_NAME, null , wartość, SQLiteDatabase.CONFLICT_REPLACE); ITS będzie pozbyć konfliktu jeśli płyta jest już istnieją
W DatabaseHelper dodać unikatowy indeks
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;
}
I zadzwonić bulkInsert tak:
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. ZF2 wstawianie wielu wierszy
- 2. Wstawianie wielu wierszy w mysql
- 3. wstawianie wielu wierszy z jednym poleceniem wstawienia
- 4. Wstawianie wielu wierszy przy użyciu JdbcTemplate
- 5. Wstawianie wielu wierszy z jednym zapytaniem MySQL
- 6. MySql - Wstawianie wielu wierszy z połączonym podzapytaniem?
- 7. wstawianie wielu wierszy z 1 kwerendy
- 8. Tworzenie wielu wierszy tekstu za pomocą Snap.svg
- 9. Limit wstawiania wielu wierszy
- 10. Wstawianie wielu wartości za pomocą INSERT INTO (SQL Server 2005)
- 11. wstawianie wielu dokumentów za pomocą mongoengine do mongodb
- 12. Wstawianie danych za pomocą Node.js
- 13. Równoczesne wstawianie za pomocą MySQL
- 14. wstawianie PDO wsadowego wielu wierszy z symbolami zastępczymi
- 15. SQL - Wstawianie wartości wielu wierszy do pojedynczej kolumny
- 16. aktualizacja wielu wierszy za pomocą limitu w mysql?
- 17. Perl: Aktualizacja wielu wierszy za pomocą jednego połączenia MySQL
- 18. Wybieranie wielu wierszy JTable
- 19. Wstawianie wielu wierszy -> instrukcja przekracza maksymalną dozwoloną liczbę wartości 1000 wierszy
- 20. Wstawianie wierszy bez wybierania niczego?
- 21. Jak zaimplementować prostą architekturę REST i ContentProvider za pomocą modeli?
- 22. Wstawianie podziały wierszy do wiadomości IRC
- 23. Wstawianie wiązania "za"?
- 24. Wstawianie zbiorcze LUB aktualizowanie za pomocą hibernacji?
- 25. Wstawianie luzem w MongoDB za pomocą mangusty
- 26. Wstawianie znaczników HTML za pomocą Meteora
- 27. Scalanie wielu wierszy w jedną kolumnę za pomocą wierszy z wierszami powrotu karetki
- 28. Równoległe wstawianie zbiorcze za pomocą SqlBulkCopy i Azure
- 29. Wstawianie danych i ustawianie kluczy obcych za pomocą Postgreatora
- 30. Android ContentProvider Performance
Pytanie jest jasne .. zresztą można sprawdzić tutaj http : //developer.android.com/guide/topics/providers/content-providers.html#modifying –
http://stackoverflow.com/questions/5596354/insertion-thousands-of-contact-entries-using-applybatch -jest-wolny – Selvin