2012-01-07 91 views
8

我正在爲Web應用程序使用Java + Spring框架。我沒有使用任何ORM工具。相反,我試圖使用簡單的DAO/DTO模式將db關係建模爲Java對象。只要DTO完全對應於數據庫中的單個表,它就非常簡單。但是如果有使用外鍵引用其他表的表,我不確定最佳方法是什麼。在Stackoverflow中看到了類似的答案,但找不到滿足我需求的答案。我想舉一個非常具體的例子 - 假設有兩個實體User和Group。我有一個用戶DTO和組DTO,每個用戶都有UserDao(JdbcUserDao)和GroupDao(JdbcGroupDao)。設計具有外鍵關係的DTO

現在我在DB中有一個連接用戶和組的關係。一個用戶可以屬於多個組。表名是User_Group_Association,它具有以下數據庫定義:

user_id | group_id

這裏user_id是引用用戶表的外鍵。同樣,group_id指的是組表。當我在Java中,這DTO模式,我應該做這樣的事情:

public class UserGroupAssoc { 
    private int userId; 
    private int groupId; 

    //Setters and getters follow 
} 

還是應該是這樣的:

public class UserGroupAssoc { 
    private User user; 
    private Group group; 

    //Setters and getters follow 
} 

特定UI使用案例:我想顯示用戶名和相應的組它們所屬的名稱。像這個 -

名稱 - >組名

凱沙夫 - >聯繫,最終用戶,ReportAdmin
基蘭 - > ReportAdmin
Pranav - >終端用戶

在第一種方法DTO的設計,我將需要再次從數據庫中獲取用戶詳細信息(名稱)和組詳細信息(名稱)。在第二種方法中,當我構造UserGroupAssoc對象時,我需要獲取User和Group對象。

大概在第三種方法我可以設計UserGroupAssoc DTO如下:

public class UserGroupAssoc { 
    private String userName; 
    private String groupName; 
    private int userId; 
    private int groupId; 

    //Setters and getters follow 
} 

在這第三種方法,我同表中的SQL只獲得了用例所需的字段,然後建模相應的DTO。

哪種標準方法可以實現這種情況?在DTO設計中加入表格是否正確?有些人認爲,一個DTO應該只對應於一個表,並且關聯的對象應該聚合在應用層中。那對於從DB執行多個對象提取是否有開銷?對於正確的方法過於困惑,抱歉這麼長時間的解釋!

回答

6

免責聲明:我不是一個ORM專家...

...但在一個典型的many-to-many relations你不需要第三個數據模型(UserGroupAssoc)。該User類將包含的Group個集合:

public class User { 
    // ... user fields ... 
    List<Group> groups; 
    // ... getters/setters ... 
} 

如果您還需要反向關係(一組包含用戶)Group類將是這樣的:

public class Group { 
    // ... group fields ... 
    List<User> users; 
    // ... getters/setters ... 
} 

周而復始,這樣做的經典方法是收集(UserGroup代替userIdgroupId)在使用「域對象」(DTO的你)。

您通常需要只有在關聯表(User_Group_Association)含有比user_idgroup_id別的東西(也許這允許用戶添加到組的一些授權碼,等等)第三域對象:

user_id | group_id | auth_code 

在這種情況下,UserGroupAssoc類可能有這樣的結構:

public class UserGroupAssoc { 
    private User user; 
    private Group group; 
    private String authorizationCode; 

    // ... setters/getters ... 
} 

而且User和之間的許多一對多的關係將轉換爲與此新域對象的兩個多對一關係。通常域對象是優選使用(UserGroup代替userIdgroupId)。

這是實現此方案的標準方法?

那麼,如果您使用的是ORM框架,它將會是框架的標準方式。但是由於您有自定義的ORM解決方案,因此很難說

在DTO設計中加入表格是否正確?

爲什麼應用層中的DTO設計應該受數據庫中表連接的影響?這是object-relational impedance mismatch的情況,也可能是law of leaky abstraction,因爲您無法將關係域完全抽象爲保持1:1對應關係的對象域。

有人認爲一個DTO應該只對應於一個表,並且關聯的對象應該聚合在應用層中。那對於從DB執行多個對象提取是否有開銷?

ORM有一些限制(對於可能遇到的一些問題,請再次查看對象關係阻抗不匹配),並且很難模擬您的域對象以適應關係數據庫的約束,反之亦然。報告就是這方面的典範。

報表通常彙總來自多個表的數據。對於某些SQL連接,這當然沒有問題,但是如何將結果映射到DTO?正如你自己說的那樣......

每當DTO正好對應於數據庫中的一個表,它是非常簡單的

...但報告結果將不會映射到一個單一的表,它必須映射到更多表的片段。

根據你在應用程序中的需求,你最終可能會看到一些奇怪的類或看起來很尷尬的SQL。您最終可能會運行更多的查詢,而不是獲取適當的對象模型以及它們之間的關聯;或者您可能會使用更多類似的DTO來限制訪問數據庫的次數並獲得更好的性能。

所以我想說的(再一次聲明,我不是一個ORM專家)是不是所有的應用程序都是ORM的好候選人;但是如果你考慮繼續研究它,可能會研究Hibernate/JPA如何解決這些問題,甚至可以繼續使用它們。