3

約700個のフロートのバッチ挿入をしようとしています。私が使用している方法は以下にあり、コンテンツ プロバイダーの bulkInsert と同様です。問題は、すべての浮動小数点値を ContentValues に入れても何も起こらないことです。これらの浮動小数点値を ContentValues オブジェクトに挿入するより良い方法は何ですか?

    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;
}
4

4 に答える 4

3

これが失礼になることはわかっていますが、このコードは破棄してください。プロバイダーにはほとんどの SQLite 操作を処理する主要なメソッドがあり、そのうちの 3 つ (insert()、bulkInsert()、および applyBatch()) をある種のフランケンシュタインにブレンドしようとしました。主な間違いは次のとおりです。

1) この行values.put(DataTable.COLUMN_DATA, tempVal)は、反復ごとに新しいエントリを挿入していません。それらをオーバーライドしています。すべての反復の後values、配列の 700 番目の float 値のみが含まれます。

ContentValues2) @Karakuri が思い出したように、内部には 1 つのインスタンスしかありませんcvArraybulkInsert()doc は、2 番目のパラメーターについて次のように述べています。

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) これらの 3 行は基本的に役に立ちません。

if (newId <= 0) {
    throw new SQLException("Failed to insert row into " + uri);
}

insertOrThrow()挿入操作中に何らかのエラーが発生した場合、すでに例外がスローされます。エラーを手動でチェックしたい場合は、insert()orを試してくださいinsertWithOnConflict()(または try ブロックに catch を追加して、そこで例外を処理してください)。

numInserted5) そして最後に、 @petey が指摘した問題があります(繰り返す必要はありません)。

最後のアドバイス:bulkInsert()存在することを忘れてください。これにはより多くのコード行が必要になることはわかっていますが、 applyBatch()you を使用すると、より良い結果が得られます (実装する必要がないため、より簡単になります)。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); 
} 
于 2013-09-20T18:23:33.830 に答える
2

各 float がデータベースに独自のレコードを持つようにする場合は、新しいレコードごとに ContentValues のインスタンスが必要です。現在、ContentValues のインスタンスが 1 つあり、それに同じキーを書き込んでいます (値を上書きしていることを意味します) 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 */
}
于 2013-09-06T20:27:11.280 に答える