2

我有 3 个表,,USERENTRY用于输入的产品,不需要创建 PRODUCT 表),和USER_COLLECTION,这是一个介于USER和之间的表ENTRY,因为一个条目可以有多个用户。

基本上:

用户 =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,有 3 个用户链接到它,Foo、Bar 和 Foobar。

现在,我想在我的应用程序中使用它并获取数据;除了我不知道从哪里开始。我尝试选择条目数据,使用该 ID 循环遍历集合数据,但这意味着我打开了两个游标并且它不起作用。尝试创建一个连接,但我不能真正做出一个好的连接,主要是因为:

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());
}

如果我使用它,我会创建 Item 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)。但是连接查询是一种有效的方法,所以保留你所做的,只需添加两个缺失的 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 框架(例如 Hibernate,即使我不知道这是否适用于 Android)。

于 2012-12-10T16:11:53.810 回答