2008-10-20 108 views
12

對象關係映射已經有很好的討論,包括在這裏。我有一些方法和陷阱和妥協的經驗。真正的解決方案似乎需要對OO或關係模型本身進行更改。功能比關係映射更容易比關係對象嗎?

如果使用功能性語言,是否出現同樣的問題?在我看來,這兩個範例應該比OO和RDBMS更好地融合在一起。在RDBMS中集思維的想法似乎與功能方法似乎承諾的自動並行相關。

有沒有人有任何有趣的意見或見解?該行業的狀態如何?

+0

其實,這是否真的有意義?函數式編程沒有提供任何標準的數據建模方式,這可能與關係數據建模或面向對象數據建模有所不同。所以要求「映射」恕我直言,這不是一個有意義的問題。有人可能會問,將功能概念添加到RDBMS是否有意義,實際上SQL已經有了一些功能概念。 – 2012-12-03 12:24:26

回答

5

擴展關係數據庫的難題是擴展事務,數據類型不匹配,自動查詢翻譯以及諸如N+1 Select這些離開關係系統的根本問題,以及在我看來 - 不會因爲更改而改變接收編程範例。

2

我猜想功能到關係映射比OO更容易創建和使用RDBMS。只要你只查詢數據庫,就是。我還沒有真正看到(如何)以好的方式執行沒有副作用的數據庫更新。

我看到的主要問題是性能。今天的RDMS不能用於功能查詢,在很多情況下可能表現不佳。

2

正如Sam所說,我認爲如果數據庫應該更新,就必須面對與面向對象領域相同的併發問題。由於關係數據庫的數據,事務等的狀態,程序的功能性可能甚至比對象本質更有問題。

但對於閱讀,功能性語言可能是某些問題領域更自然的(因爲它似乎是不管DB)的

功能< - > RDBMS映射應該沒有大的差異OO < - > RDMBS映射。但是我認爲這取決於你想使用什麼樣的數據類型,如果你想用全新的數據庫模式開發一個程序,或者對傳統的數據庫模式做些什麼,等等。

例如懶惰提取關聯等可能可以很好地與一些懶惰的評估相關的概念實現。 (即使它們也可以用OO很好地完成)

編輯:一些使用Google搜索時,我發現HaskellDB(Haskell的SQL庫) - 這可能值得嘗試嗎?

2

我還沒有完成功能關係映射,本身,但我已經使用函數式編程技術來加速對RDBMS的訪問。例如,從一個數據集開始,對其進行一些複雜的計算並存儲結果,其中結果是原始子集(包含附加值)的情況非常普遍。命令式的方法決定了你用初始數據集存儲額外的NULL列,做你的計算,然後用計算出的值更新記錄。

似乎合理。但問題在於它可能變得非常緩慢。如果您的計算需要除了更新查詢本身之外的其他SQL語句,或者甚至需要在應用程序代碼中完成,那麼您實際上必須(重新)搜索計算後更改的記錄,以將結果存儲在正確的行中。

您可以通過簡單地創建一個新的結果表來解決這個問題。這樣,您可以始終插入而不是更新。你最終有另一張表,複製密鑰,但你不再需要浪費存儲NULL的列上的空間,只存儲你所擁有的。然後,您將您的結果加入最終選擇。

我(AB)使用RDBMS這種方式,結束了寫作,看上去大多是這樣的SQL語句...

create table temp_foo_1 as select ...; 
create table temp_foo_2 as select ...; 
... 
create table foo_results as 
    select * from temp_foo_n inner join temp_foo_1 ... inner join temp_foo_2 ...; 

這是什麼本質上做的是創造了一堆不變的綁定。不過,好的事情是,你可以一次處理整套設備。有點讓人想起那些讓你使用矩陣的語言,比如Matlab。

我想這也可以讓並行更容易。

額外的好處是,這種方式創建的表的列類型不必指定,因爲它們是從它們從中選擇的列推斷出來的。

+2

這完全不是濫用,它是使用SQL的正確方式。你以一種基於集合的方式工作,這是最好的方式。 Oracle可以並行執行這些SQL語句,我認爲其他數據庫也可以這樣做。 – tuinstoel 2009-07-12 20:02:27

1

這要看你的需求

  1. 如果你想專注於數據結構,如果你想在治療闡明使用ORM像JPA /休眠
  2. ,看看FRM庫:QueryDSL或Jooq
  3. 如果您需要調整您的SQL請求到特定的數據庫,使用JDBC和SQL本地請求

各種「關係映射」技術的那份力量是便攜性:您確保您的應用程序將在大多數ACID數據庫上運行。 否則,當您手動寫入SQL請求時,您將處理各種SQL方言之間的差異。

當然,你可以剋制自己SQL92標準(然後做一些函數式編程),或者你可以重用functionnal編程的一些概念與ORM框架

的ORM strenghs建在一個會話對象,它可以充當作爲瓶頸:

  1. 只要底層數據庫事務正在運行,它就管理對象的生命週期。
  2. 它在Java對象和數據庫行之間保持一對一映射(並使用內部緩存來避免重複的對象)。
  3. 它自動檢測關聯更新和孤兒對象刪除
  4. 它處理樂觀或悲觀鎖定的併發問題。

儘管如此,它的優勢也是它的弱點:

  1. 會話必須能夠所以你需要工具等於/ hashCode方法來比較的對象。 但對象的平等必須植根於「業務鍵」而不是數據庫ID(新的瞬態對象沒有數據庫ID!)。 但是,一些具體化的概念沒有業務平等(例如操作)。 常見的解決方法依賴於傾向於打亂數據庫管理員的GUID。

  2. 會話必須偵測關係更改,但其映射規則會推動使用不適合於業務算法的集合。 有時候你想要使用HashMap,但是ORM將要求密鑰是另一個「富域對象」而不是另一個「輕量級對象」...... 然後,您必須在作爲密鑰的豐富域對象上實現對象相等。 .. 但是,你不能因爲這個對象在商業世界中沒有對應。 所以你回到一個簡單的列表,你必須迭代(和性能問題的結果)。

  3. ORM API有時不適合現實世界的使用。 例如,當您獲取數據時,真實世界的Web應用程序嘗試通過添加一些「WHERE」子句來強制執行會話隔離...然後,「Session.get(id)」不夠用,您需要轉向更復雜DSL(HSQL,Criteria API)或返回到本機SQL數據庫對象與專用於其他框架的其他對象(如OXM框架=對象/ XML映射)相沖突。 例如,如果您的REST服務使用jackson庫來序列化業務對象。但是這個傑克遜恰好映射到一個Hibernate One。 則要麼合併兩個和你的API和數據庫之間的強耦合出現 或者您必須實現一個翻譯,所有你從ORM保存代碼丟失那裏......

在另一邊FRM是「對象關係映射」(ORM)和原生SQL查詢(使用JDBC)之間的一種折衷方案。解釋FRM和ORM之間差異的最佳方法是採用DDD方法。

  • 對象關係映射授權使用「富域對象」,這是Java類,其狀態是數據庫事務
  • 功能關係映射依靠這是不可改變的「可憐的域對象」(以至於在可變的你必須在每次你想改變它的內容的時候克隆一個新的)

它釋放了ORM會話上的約束,並且依賴於SQL上的大部分時間在DSL上(因此可移植性無關緊要) 但另一方面,您必須查看交易細節,concurrenc y問題

List<Person> persons = queryFactory.selectFrom(person) 
    .where(
    person.firstName.eq("John"), 
    person.lastName.eq("Doe")) 
    .fetch();