2

エントリには複数のユーザーがいる可能性があるため、USER3つのテーブルENTRY(入力された製品の場合、PRODUCTテーブルを作成する必要はありません)と、USER_COLLECTIONとの間のテーブルがあります。USERENTRY

基本的に:

ユーザー=USERID | USER_NAME

エントリ=ENTRYID | ENTRY_NAME | ENTRYPRICE | ENTRY_DATE

コレクション=COLLECTIONID | ENTRYID | USERID

プロジェクト全体を通して存続するユーザーのテーブルがあります。エントリ(通常は価格のある製品の一種)を作成し、複数のユーザーを特定のエントリ(リストから選択できるため、ユーザーはプロジェクト全体で存続します)にリンクできます。

たとえば、私のテーブルは次のようになります。

User
--------------------------
user_id   |   user_name
--------------------------
   1      |    'FOO'
   2      |    'BAR'
   3      |    'FOOBAR'


ENTRY
-----------------------------------------------------------------------
entryid  |   entry_name     |  entry_price |      entry_date     
-----------------------------------------------------------------------
   0     |    'Banana'      | 2.50         |  12/12/2012


COLLECTION
---------------------------------------
collectionid |   entryid    |  userid     
----------------------------------------
   0         |    1         | 1
   1         |    1         | 2
   2         |    1         | 3

私はバナナを持っています。価格は2.50で、Foo、Bar、Foobarの3人のユーザーがリンクしています。

今、私はこれを私のアプリで使用してデータを取得したいと思います。どこから始めればいいのかわからないことを除いて。そのIDを使用してコレクションデータをループしてエントリデータを選択しようとしましたが、2つのカーソルが開いていて、機能しませんでした。結合を作成しようとしましたが、主に次の理由で、実際に良い結合を作成できませんでした。

JOIN
---------------------------------------
collectionid |   entryname |  username
----------------------------------------
   0         |    Banana   | FOO
   1         |    Banana   | BAR
   2         |    Banana   | FOOBAR

Androidコードで同じエントリオブジェクトを複数作成するため、これを繰り返すことはできません...

私がこれを明確にしていることを願っています。

if (cursor2.moveToFirst()) {
    do {
        Item i = new Item(<GET STUFF FROM CURSOR>);
        i.addUser(new Person(<GET STUFF FROM CURSOR>)));
        Log.d("TAG", i.getUsersPaying().size() + "");
    } while (cursor2.moveToNext());
}

これを使用すると、アイテムiの複数のインスタンスを作成します。それらはすべてバナナになりますが、複数のユーザーが追加されたバナナは1つだけにする必要があります。

4

2 に答える 2

2

まず、結合クエリでテーブルからIDを返すことを検討することをお勧めします。コラムを返却すると、状況は少し簡単になりentryidます。

Map<Integer, Item>ループ内ですでに見たアイテムを保存するためにを作成するだけです。各カーソルを調べるときは、マップをチェックして、すでにインスタンスがあるかどうかを確認してください。そうでない場合は、新しいものを作成して挿入してください。

クエリ結果が次のようになっていると仮定します。

JOIN
----------------------------------------------------
collectionid |   entryname |   entryname |  username
----------------------------------------------------
   0         |    1        |    Banana   | FOO
   1         |    1        |    Banana   | BAR
   2         |    1        |    Banana   | FOOBAR
   2         |    2        |    Apple    | FOOBAR

次のようにコードを変更できます。

Map<Integer, Item> items = new HashMap<Integer, Item>();
if (cursor2.moveToFirst()) {
    do {
        int itemId = cursor2.getInt(1);
        Item i;
        if (items.containsKey(itemId))
            i = items.get(itemId);
        else
        {
            i = new Item(<GET STUFF FROM CURSOR>);
            items.put(itemId, i);
        }
        i.addUser(new Person(<GET STUFF FROM CURSOR>)));
        Log.d("TAG", i.getUsersPaying().size() + "");
    } while (cursor2.moveToNext());
}
于 2012-12-10T16:16:49.110 に答える
1

すでにメモリにロードされているエンティティの辞書を維持する必要があります。たとえば、保持されるバックグラウンドフラグメント。

基本的にあなたはするでしょう:

Item i = cacheFragment.createOrGetEntry( cursor.getLong( ENTRY_ID_COLUMN_INDEX ) );
Person p = cacheFragment.createOrGetPerson( cursor.getLong( PERSON_ID_COLUMN_INDEX ) );

もちろん、クエリは必要なすべての行のID(entryIdとpersonId)も返す必要があります。ただし、結合クエリはそれを効率的に行う方法であるため、それについて行ったことを維持し、欠落している2つのID列を追加するだけです。

createOrGetPersonメソッドは次のようになります。

public Person createOrGetPerson(long id) {
    Entry<Long, Person> p = personDictionnary.get( id ); // can be a HashMap or even better, a SparseArray
    if (p==null) {
      p = new Person(id);
      personDictionnary.put(p); // Remember it for next time
    }
    return p;
}

また、この種の問題に対処するために作成されたデータ永続化フレームワークまたはORMフレームワークも確認する必要があります(たとえば、Androidで機能しているかどうかはわかりませんが、Hibernate)。

于 2012-12-10T16:11:53.810 に答える