2009-12-28 79 views
20

我幾乎完成了我的數據映射器,但現在我處於關係關係的階段。數據映射器和關係:實施策略?

我會盡力在這裏說明我的想法。我無法找到關於這個主題的好文章/信息,所以也許我正在重新發明輪子(當然,我可以使用一個大框架 - 但我想通過這樣做來學習)。

1:1間的關係

首先,讓我們來看看1:1的關係。一般來說,當我們有一個名爲「Company」的域類和一個名爲「Address」的域類時,我們的公司類將具有類似address_id的內容。可以說,在大多數情況下,我們只顯示一個公司名單,只有當有人查看細節時才需要地址。在這種情況下,我的Data Mapper(CompanyDataMapper)只是簡單地加載,意味着它只會從數據庫中獲取address_id,但不會進行連接以獲取地址數據。

一般來說,我有一個每個關係的getter方法。所以在這種情況下,有一個getAddress(公司companyObject)方法。它需要一個公司對象,查找它的地址屬性,如果它是NULL,則從數據庫中獲取相應的Address對象,使用該Address對象的Mapper類(AddressDataMapper),並將該地址對象分配給指定的地址屬性公司對象。

重要提示:數據映射器是否允許使用其他數據映射器?

可以說在大多數情況下,您需要公司對象和地址對象,因爲您總是一起顯示它在一個列表中。在這種情況下,CompanyDataMapper不僅獲取公司對象,而且通過JOIN執行SQL查詢以獲取地址對象的所有字段。最後,它遍歷記錄集併爲新對象提供相應的值,並將地址對象分配給公司對象。

聽起來很簡單,到目前爲止。

1:N的關係

這些怎麼樣?與1:1唯一的區別是,公司可能有多個地址對象。讓我們看看:當我們大多數時間只對公司感興趣時,Data Mapper會將公司對象的地址屬性設置爲NULL。地址屬性是可以引用無,一個或多個地址的數組。但是我們還不知道,因爲我們懶洋洋地加載,所以它只是NULL。但是,如果我們在大多數情況下需要所有的地址,那又如何呢?如果我們將所有公司的大名單連同他們的所有地址一起顯示?在這種情況下,事情開始變得非常難看。首先,我們不能爲每個地址對象加入地址表五十次(我堅信這是不可能的,如果是的話,性能會低於零)。所以,當我們進一步思考這個問題時,在這種情況下不可能不加載。

重要提示:這是真的嗎?我必須發送100個查詢才能獲得100個地址對象,如果我有10家公司,每個地址有10個地址?

M:N的關係

比方說一個地址對象只包含國家,州,城市,道路和門牌號碼。但是,一間房子可能是一個大型商業大廈,其中有很多公司。就像那些現代化的辦公大樓之一一樣,任何人都可以租用一個小型的ROM來炫耀它的網站上的塔。所以:許多公司可以共享相同的地址。

我還沒有計劃來處理這類問題。

重要提示:也許這不是比1一個更大的問題:N的關係?

如果有誰知道一個良好的ressource即進入關於解決/實現這個細節,我會很高興的鏈接!

回答

3

我期待着你會得到關於這個主題的答案,但在此期間爲什麼不跳了亞馬遜(或當地經銷商的書籍),最後買

這些書包含您已經指出原來的模式在你的各種問題中,並被認爲是設計模式和軟件體系結構中的參考工作。

0

我也在解決這個問題。首先,我調整了Matt Zandstra的PHP Objects,Patterns和Practice(第2版)中的Data Mapper模式。我現在看到的是一個new edition已經走出

也許設置的最巧妙的部分是「集合」的對象。我不確定你使用的是什麼語言,所以我會告訴你細節。只要說PHP有一個Iterator接口,它就可以首先加載一個數組(地圖,用其他語言),並在循環的同時將原始數據轉換爲對象(水合物?)。

和你一樣,我正在努力如何加載關係。到目前爲止我發現的是,我可以在Mapper類中編寫我的大量JOIN查詢,並同時爲目標對象創建一個脫水集合並潛入相關對象的數據。

我真的不喜歡「延遲加載」,因爲它導致瞭如此多的數據庫查詢。它冒犯了我完美主義的敏感性,知道我使用數十或數百個查詢來完成任務,可以一次完成。

我也期待着更多的答案。

16

在我開始之前,我會假設你從頭到尾都讀過福勒的PoEAA書。 =) 另外,我會考慮你已經想到了在處理ORM時遇到的第一個初始問題。我可以強調一個簡單的方法,例如使用相同的標識符多次調用DataMapper,並始終返回相同的對象(讀取爲IdentityMap)。

重要提示:數據映射器是否允許使用其他數據映射器?

如果第二個DataMapper是第二個弱引用,那麼只有一個DataMapper可以訪問另一個DataMapper。

可以說在大多數情況下,你需要公司對象和地址對象,因爲你總是一起顯示它在一個列表中。在這種情況下,CompanyDataMapper不僅獲取公司對象,而且通過JOIN執行SQL查詢以獲取地址對象的所有字段。最後,它遍歷記錄集併爲新對象提供相應的值,並將地址對象分配給公司對象。

這裏試圖討論的問題在實踐中聽起來很簡單,但在幕後有點複雜。

首先,你不應該有一個getAddress(公司),而是有代理對象的好處。 代理是給定實例的非初始化表示。在這種情況下,代理包含對您要查找的條目的引用。它必須從原始對象擴展,並且需要提供一個初始化方法,以及一個相關的DataMapper來加載它。

關於一次加入和加載多個對象的第二部分稱爲Hydrator。 Hydrators接收線和列的平面結構並轉換爲對象圖。但它真的進入了一個單獨的問題:如果你純粹處理對象,你爲什麼抓取表?嘗試採用對象提取方法會導致您實現一種OQL(對象查詢語言)。

重要提示:這是真的嗎?我必須發送100個查詢才能獲得100個地址對象,如果我有10家公司,每個地址有10個地址?

處理對象集合是PHP中的噩夢。是的,這種語言由於缺乏強大的集合實現而吸引很多。基本上,你需要在這裏處理不同的情況: - 新的實例和元素列表中的所有元素都是新的 - 新的實例和這個元素列表中的所有元素都是預先存在的 - 這個新的實例和元素元素的列表中之間新的混合和預先存在的 - 預先存在的實例和元素的 名單上沒有碰到任何東西 - 預先存在的實例,並在列表

我是非常簡單的在這裏操作的項目,但我想強調的主要觀點是需要一個Collection對象。其中有兩個:一個處理新列表和一個處理現有列表。處理現有列表的應用程序需要能夠在您嘗試訪問內部任何內容時加載收集。這是沒有n + 1問題的唯一方法。

這裏還突出了你必須處理的下一個大問題。關聯可以是單向的或雙向的。這意味着公司知道地址但地址不知道公司是單向的,而用戶是許多組和組的一部分,並且組包含許多用戶是雙向關聯。 事情很容易變成這裏的噩夢,這就是爲什麼你需要映射模式來正確理解發生了什麼。

處理多對多就像處理一般的集合一樣。

還有一個你尚未考慮過的重要部分。如果我構建我的整個對象圖(公司和地址),並決定堅持它們,它需要堅持這兩個對象,或者我必須手動告訴我想要堅持什麼?兩種方式都有不同的問題。 我們假設你想要第一種方法。你剛剛進入了我認爲是最複雜的設計模式之一:UnitOfWork。然後,你必須處理排序實體的順序,以不產生約束問題(閱讀拓撲排序如何解決這個問題)。 如果採取第二種方法,您可能很容易進入感覺工具已損壞的情況,主要是因爲很容易讓對象圖形處於不一致的狀態。

終於......你打算對繼承做任何支持嗎?如果是積極的,你的整個計劃就進入了一個全新的水平。 =(試圖解釋會帶我一本書,但我可以指出一些設計模式,你可以看看:具體表繼承(1類,1表),單表繼承(N類,1表)和類表繼承(N 。班,男表)

我可以深入去很多不同點在這裏,但奧姆斯通常導致頭部爆炸我會停下來,現在

PS:我的核心開發者之一除非你是爲了學習目的而這樣做,否則不要費心去創建另一個,這是一個非常複雜,耗時的事情,它需要很多很多的事情計劃,甚至在你編碼第一個代碼之前 事實上,我們計劃了ORM主義2年,花了1年的時間來實施有力的核心功能。 我並不氣餒你,但正如福勒在他的ORM討厭文章中所說的,對於一個複雜的問題來說,這是一個複雜的解決方案。