2012-12-05 90 views
9

我正在使用數據映射器模式,我想知道處理與該模式的關係的最佳方法是什麼。我花了很多時間在谷歌和堆棧溢出中尋找解決方案,我發現了一些,但我仍然不完全滿意它們,特別是在我將嘗試解釋的一個特例中。處理與數據映射器模式的關係

我正在使用PHP,所以我將放在PHP代碼的示例。假設我有一個表「team」(id,name)和一個表「player」(id,name,team_id)。這是1-N關係。 通過實現Data Mapper模式,我們將擁有以下類:Team,TeamMapper,Player和PlayerMapper。

到目前爲止,一切都很簡單。如果我們想要從一個團隊中獲得所有的玩家怎麼辦?

我發現的第一個解決方案是在Team類中創建一個方法getAllPlayers(),它將使用延遲加載和代理來處理該方法。然後,我們可以檢索一個團隊一樣,球員:

$players = $team->getAllPlayers(); 

我發現的第二種解決方案是直接使用PlayerMapper並通過團隊ID作爲參數。喜歡的東西:

$playerMapper->findAll(array('team_id' => $team->getId())); 

但現在,讓我們說,我想和所有的車隊,並與所有的各隊球員列「玩家」來顯示一個HTML表格。如果我們使用我描述的第一個解決方案,那麼我們將不得不執行一次SQL查詢以獲得每個團隊的隊列表和一個查詢以獲取隊員,這意味着N + 1個SQL查詢,其中N是隊的數量。

如果我們使用我介紹的第二個解決方案,我們可以先檢索所有團隊的ID,把它們放在一個數組,然後把它傳遞給玩家映射器的的findAll方法,這樣的事情:

$playerMapper->findAll(array('team_id' => $teamIds)); 

在這種情況下,我們只需要運行2個查詢。好多了。但是我對這個解決方案仍然不滿意,因爲這些關係沒有被描述到模型中,而是開發者必須瞭解它們。

所以我的問題是:有數據映射器模式的其他選擇嗎?通過我給出的例子,是否有一種很好的方法可以在只有兩個查詢的情況下選擇所有球員與所有球員進行關係模型的描述?

預先感謝您!

回答

2

如果您看看Martin Fowler描述DataMapper如何工作的文本,您會看到您可以使用一個查詢來獲取所需的所有數據,然後將該數據傳遞給每個映射器,從而允許映射器選擇只輸出它需要的數據。

對你來說,這將是一個從Team到Player的連接查詢,爲每個唯一播放器返回一個包含重複Team數據的結果集。

然後,您必須通過在數據更改時創建新對象來滿足映射代碼中的重複。

我已經做了類似的東西在那裏相當於是在結果集的團隊映射迭代,併爲每個獨特的團隊通過將結果集的播放器映射器,以便它可以創建一個球員,那麼球員加入到團隊的收藏。

雖然這會工作,有進一步下行這種方法的問題...

+0

您引用了哪一個Martin Fowler的文字?我發現的唯一一個是(http://www.martinfowler.com/eaaCatalog/dataMapper.html),我沒有看到你說什麼。無論如何,這種方法並不能說服我。這意味着你必須做一個查詢,返回NxM行(N是團隊數量,M是玩家數量),並且有很多重複的數據。這也意味着通過團隊映射器映射球員,這聽起來不太好。正如你所說,我相信這種方法在下游還有問題... – Vincent

+0

它在PoEAA書中。該網站只提供一個概述。您的查詢不返回NxM行,僅返回M行。它確實帶回了大量數據,但這是重點。儘可能多地往返一次。此外,您的團隊映射程序不會映射玩家,它會要求玩家映射程序爲其映射玩家。 –

+0

是的,對不起,M行。那麼,這是一個解決方案,但我仍然不完全相信。讓我們來看看我的問題是否會帶來更多的答案... – Vincent

0

我有一個可能的解決這個問題,我已經在我的一個項目順利實施。它並不複雜,在上述示例中僅使用2個查詢。

解決方案是添加另一層負責處理關係的代碼。例如,我們可以把它放在一個服務類(它也可以用於其他的東西,不僅處理關係)。 假設我們在Team和TeamMapper之上有一個類TeamService。 TeamService將有一個方法getTeamsWithRelationships(),它將返回一個Team對象的數組。 getTeamsWithRelationships()將使用TeamMapper獲取團隊列表。然後,通過使用PlayerMapper,它將只在一個查詢中獲得這些球隊的球員列表,並通過使用Team類中的setPlayers()方法將球員設置爲球隊。

該解決方案非常簡單,易於實現,並且適用於所有類型的數據庫關係。我想有些人可能會有反對的東西。如果是這樣,我想知道有什麼問題?