4

リレーションシップを持つテーブルがほとんどないプライベートContentProviderを実装しています(1対多、多対多)。私の現在の実装では、すべてのテーブルに URI でアクセスできます。内部の「スルー」テーブルに URI でアクセスする必要がないように、インターフェイスを単純化するにはどうすればよいですか?

たとえば、POSTS テーブルがあり、各 POST には TAGGINGS テーブルを介して多くの TAGS があります。私は POSTS URI とのみ対話し、ContentProvider.

結合されたテーブルでカーソルを返すのは簡単ですqueryが、どうすればこれを行うことができinsertますか? bulkInsert私が調べるべきことは何ですか?

4

4 に答える 4

7

の限定ですContentProvider。データを他のアプリケーションに公開していない場合は、カスタム データベース アダプターの実装を使用して、メソッドとクエリを直接要件に適合させることができます。

bulkInsert()一度に 1 つのテーブルにのみ行を挿入するため、この状況では役に立ちません。ただし、ContentProvider.applyBatch()メソッドとContentProviderOperationContentProviderOperation.Builderクラスを見てください (1 対多の挿入が必要withValueBackReference()になる場合があります)。

これらのリンクは、それらの使用方法を理解するのに役立ちます:

http://www.grokkingandroid.com/better-performance-with-contentprovideroperation/ http://www.grokkingandroid.com/androids-contentprovideroperation-withbackreference-explained/ withValueBackReference のセマンティクスは何ですか?

ただし、操作が実行されるたびに構文解析 (文字列比較) が行われるため、一度に多数の行を挿入する場合ContentProviderOperationよりもはるかに時間がかかることに注意してください。このようにして、子テーブルに挿入するために Uri を公開する必要があります。bulkInsert()Uri

を使用する場合applyBatch()は、プロバイダーで上書きして、すべての操作を 1 つのトランザクションで実行するようにします。これにより、データの一貫性が維持され、データベース操作が高速化されます。

@Override
public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
        throws OperationApplicationException {
    final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
    db.beginTransaction();
    try {
        ContentProviderResult[] results = super.applyBatch(operations);
        db.setTransactionSuccessful();
        return results;
    } finally {
        db.endTransaction();
    }
}
于 2012-07-15T13:30:57.900 に答える
1

これを正しく理解するには: URI を 1 つにして、ContentProvider への 1 回の挿入呼び出しで投稿とそのすべてのタグを挿入したいですか? 正しい?

問題は、ContentValues オブジェクトにすべての値が必要なことです。データベースの正規化には理由があります。それでも、それは実行可能かもしれません。タグの場合、これは簡単なはずです。すべてのタグに1 つの文字列を使用するだけです。たとえば、「android、ios、bada、wp7」のように挿入メソッドでこの文字列を解析します。

命名規則と整数規則を使用することもできます。そして、tag1、tag2、... tagX がある限り、ContentProvider の挿入メソッド内からこれらの値を読み取ります。

どちらもエレガントではありませんが、機能します。

この場合、bulkInsert または applyBatch はコード内に存在しません。これらは、一度に 1 つのトランザクション内で ContentProvider への複数の呼び出しを使用する場合にのみ機能します。

しかし、より良い解決策は、biegleux で説明されているように、実際に複数の操作を使用することだと思います。

于 2012-07-17T16:22:28.083 に答える
1

必要な値が提供されている限り、乗算テーブルに自由に挿入できます。

例えば:

ContentValues v = new ContentValues();
v.put("title","post1");
v.put("tag","tag1");
getProvider().insert(POST_URI,v);

の実装ではinsert、他のテーブルに属するフィールド ( tag) が存在するかどうかを確認できます。存在する場合は、追加の作業を行う必要があることを意味します。存在しない場合は最初にタグを挿入し、タグと投稿の間の正しい関連付けを設定します。挿入しただけ。

参照用の Android 連絡先のソース コードを確認できます。

アップデート:

複数のタグを挿入するには、カンマ区切りの文字列を挿入するというハックな方法があります。これはエレガントではありませんが、機能します。

于 2012-07-15T13:30:22.580 に答える
0

複数のテーブルに挿入するため、通常のSQLiteDatabase.insertヘルパー関数は機能しません。しかし、これはパフォーマンスと優れた方法で完全に実行可能です。

自分だけであっても、ContentProvider に挿入しようとしているユーザーのエンドポイントからこれを見る必要があります。したがって、最初にすべてのフィールドの名前またはキーを定義します。を使用SQLiteDatabase.insertしないので、実際にはデータベース フィールドと同じ名前を付ける必要はありません。どの名前も重複してはなりません。たとえば、2 つの異なるテーブルのフィールドがおそらくと でtag重複している場合、それらのフィールドの名前をととして定義できます。または、衝突しないよりわかりやすい名前にセマンティック ネーミングを使用します。TableATableBTableA.tagTableB.tag

SQLiteStatement次に、 per this answerを使用して挿入クエリを作成する必要があります。で使用する名前がcreateInsert、ContentProvider の呼び出し元が ContentValues のキーとして使用するものと同じであることを確認してください。

于 2014-09-11T07:21:33.950 に答える