private void saveToDatabase( float[] tempValues )
{
ContentValues values = new ContentValues();
// WM: TODO: add patient id and sensor type
for (float tempVal : tempValues){
values.put( DataTable.COLUMN_DATA, tempVal );
}
ContentValues[] cvArray = new ContentValues[1];
cvArray[0] = values;
ContentResolver resolver = getContentResolver();
resolver.bulkInsert( HealthDevContentProvider.CONTENT_URI_DATA, cvArray);
public int bulkInsert(Uri uri, ContentValues[] values){
int numInserted = 0;
String table = null;
int uriType = sURIMatcher.match(uri);
switch (uriType) {
case RAWINPUT_TABLE:
table = RAWINPUT_TABLE_PATH;
break;
}
db.beginTransaction();
try {
for (ContentValues cv : values) {
long newID = db.insertOrThrow(table, null, cv);
if (newID <= 0) {
throw new SQLException("Failed to insert row into " + uri);
}
}
db.setTransactionSuccessful();
getContext().getContentResolver().notifyChange(uri, null);
numInserted = values.length;
} finally {
db.endTransaction();
}
return numInserted;
}
答案 0 :(得分:3)
我知道这会很粗鲁,但只是扔掉这段代码。提供程序具有处理大多数SQLite操作的主要方法,并且您尝试将其中的三个(insert(),bulkInsert()和applyBatch())混合到某种类型的Frankenstein中。以下是主要错误:
1)此行values.put(DataTable.COLUMN_DATA, tempVal)
未在每次迭代中插入新条目;它压倒了他们。在所有迭代之后,values
仅包含数组的第700个浮点值。
2)正如@Karakuri所记得的那样,ContentValues
内只有一个cvArray
个实例。 bulkInsert()
doc说明了它的第二个参数:
An array of sets of column_name/value pairs to add to the database. This must not be null.
因此cvArray
必须包含要插入数据库的每个条目的ContentValues实例(一组)。
3)不完全是一个错误,但你应该注意一些事情。无法保证mTables
将存在,并且尝试在不指定表的情况下进行操作将抛出SQLException
。
4)这三行基本没用:
if (newId <= 0) {
throw new SQLException("Failed to insert row into " + uri);
}
如果在插入操作期间发生某些错误, insertOrThrow()
已经抛出异常。如果您想手动检查错误,请尝试insert()
或insertWithOnConflict()
(或在try块中添加一个catch并在那里处理异常)。
5)最后,问题是numInserted
@petey指向(并且没有必要重复)。
最后一条建议:忘记bulkInsert()
存在。我知道这将需要更多行代码,但使用applyBatch()
可以获得更好的结果(更容易,因为您不必实现它)。 Wolfram Rittmeyer写了一系列关于交易的优秀文章,检查你是否有任何疑问。
最后但并非最不重要(是的,我今天心情很好),这就是我将如何基本实现您的代码:
@Override
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db // TODO: retrieve writable database
final int match = matcher.match(uri);
switch(match) {
case RAWINPUT_TABLE:
long id = db.insert(RAWINPUT_TABLE, null, values); // TODO: add catch block to deal.
getContext().getContentResolver().notifyChange(uri, null, false);
return ContentUris.withAppendedId(uri, id);
default:
throw new UnsupportedOperationException("Unknown uri: " + uri);
}
}
private void saveToDatabase( float[] tempValues ) {
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
for (float tempVal : tempValues){
operations.add(ContentProviderOperation
.newInsert(HealthDevContentProvider.CONTENT_URI_DATA)
.withValue(DataTable.COLUMN_DATA, tempVal).build();
.withValue() // TODO: add patient id
.withValue() // TODO: add sensor type);
}
// WARNING!! Provider operations (except query if you are using loaders) happen by default in the main thread!!
getContentResolver().applyBatch(operations);
}
答案 1 :(得分:2)
我使用批量插入,不确定批量和批次之间的区别是什么,但我所做的只是这个
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
for(int j=0;j<locationAry.length;j++){
ContentValues values2 = new ContentValues();
values2.put(MapPoints.ELEMENT_ECM2ID, ecm2id);
values2.put(MapPoints.ELEMENT_ID, newElementId);
values2.put(MapPoints.LATITUDE, locationAry[j+1]);
values2.put(MapPoints.LONGITUDE, locationAry[j]);
values2.put(MapPoints.LAYER_ID, layerID);
operations2.add(ContentProviderOperation.newInsert(MapPoints.CONTENT_URI).withValues(values2).build());
}
getContentResolver().applyBatch(MapElements.AUTHORITY, operations);
您是否覆盖了ContentProvider中的bulkInsert
方法?
答案 2 :(得分:2)
如果您希望每个浮点数在您的数据库中拥有它自己的记录,则每个新记录都需要一个ContentValues实例。现在你有一个ContentValues实例,你正在写相同的密钥(意味着你正在写这个值)700次。
private void saveToDatabase( float[] tempValues ) {
final int count = tempValues.legnth;
ContentValues[] cvArray = new ContentValues[count];
for (int i = 0; i < count; i++) {
float tempVal = tempValues[i];
ContentValues values = new ContentValues();
values.put( DataTable.COLUMN_DATA, tempVal );
cvArray[i] = values;
}
/* all the rest */
}
答案 3 :(得分:0)
如果一次插入失败,则整个事务失败。如果没有看到用于唯一键的表create语句,请在插入失败后尝试替换。无论插入/替换失败,您的numInserted将始终与values.length相同。这似乎也不正确。
...
db.beginTransaction();
int numInserted = 0;
try {
for (ContentValues cv : values) {
long newID;
try {
newID = database.insertOrThrow(table, null, cv);
} catch (SQLException ignore) {
newID = database.replace(table, null, cv);
}
if (newID <= 0) {
Log.e("TAG, "Failed to insert or replace row into " + uri);
} else {
// you are good...increment numInserted
numInserted++;
}
}
db.setTransactionSuccessful();
getContext().getContentResolver().notifyChange(uri, null);
} finally {
db.endTransaction();
}
return numInserted;