2012-12-10 32 views
2

我有3個表,USER,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和3用戶鏈接到它,富,酒吧和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()); 
} 

如果我使用這個,我創建項目i的多個實例。他們都是香蕉,而我應該只有1個項目香蕉,並添加了多個用戶。

+0

爲什麼'COLLECTION.collectionId'不增加?它不應該自動增量? –

+0

我的錯誤。現在編輯 – user1810737

+0

您的連接數據看起來像我所期望的。它說Foo,Bar和Foobar有(買了?)香蕉。遊標會依次擊中每一行,然後處理該行。你期望看到什麼? (也許我在這裏丟失了一些東西) –

回答

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

如果你沒有添加創建的項目,你的HashMap是沒用的;) –

+0

好的呼叫,先生。答案已被編輯。 – wsanville

+0

訣竅。你也爲我打開了一個世界。將來會花費幾個小時來優化我的數據庫... – user1810737

1

您需要維護已經加載到內存中的實體的字典。例如在將被保留的背景片段中。

基本上你會怎麼做:

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

當然,你的查詢還必須返回你需要(ENTRYID和PERSONID)的所有行的ID。但是連接查詢是高效完成的方式,所以請保留你所做的事情,並添加兩個缺失的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)。