简体   繁体   English

设计具有外键关系的DTO

[英]Designing DTOs that have foreign key relationships

I am using Java + Spring framework for a web-application. 我正在使用Java + Spring框架来处理Web应用程序。 I am not using any ORM tool. 我没有使用任何ORM工具。 Instead I am trying to model the db relations as Java objects using simple DAO/DTO pattern. 相反,我试图使用简单的DAO / DTO模式将db关系建模为Java对象。 Whenever the DTO exactly corresponds to a single table in the database, it is very straight forward. 每当DTO完全对应于数据库中的单个表时,它就非常直接。 But if there are tables that refer to other tables using foreign keys, I am not sure what is the best approach for this. 但是如果有表使用外键引用其他表,我不确定这是什么最好的方法。 Looked in Stackoverflow for similar answers but could not find one to my needs. 在Stackoverflow中查找类似的答案,但找不到我的需求。 I want to give a very specific example- Suppose there are two entities User and Group. 我想举一个非常具体的例子 - 假设有两个实体User和Group。 I have a User DTO and Group DTO, each one having UserDao(JdbcUserDao) and GroupDao(JdbcGroupDao) respectively. 我有一个User DTO和Group DTO,每个都有UserDao(JdbcUserDao)和GroupDao(JdbcGroupDao)。

Now I have a relation in DB that connects the User and Group. 现在我在DB中有一个连接用户和组的关系。 One user can belong to multiple groups. 一个用户可以属于多个组。 The table name is User_Group_Association that has the following DB definition: 表名是User_Group_Association,具有以下数据库定义:

user_id | user_id | group_id GROUP_ID

Here user_id is a foreign key referring to user table. 这里user_id是引用用户表的外键。 Similarly group_id refers to group table. 类似地,group_id指的是组表。 When I model this DTO in Java, should I do something like this: 当我用Java模拟这个DTO时,我应该这样做:

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

    //Setters and getters follow
}

OR should it be like this: 或者它应该是这样的:

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

    //Setters and getters follow
}

Particular UI use case: I want to display usernames and the corresponding group names they belong to. 特定UI用例:我想显示用户名及其所属的相应组名。 Something like this- 像这样的东西 -

Name -> Group Names 名称 - >组名

Keshav -> Admin, EndUser, ReportAdmin Keshav - > Admin,EndUser,ReportAdmin
Kiran -> ReportAdmin Kiran - > ReportAdmin
Pranav -> EndUser Pranav - > EndUser

In the first approach to DTO design, I will need to fetch the user details (names) and group details (names) again from the DB. 在第一种DTO设计方法中,我需要再次从DB中获取用户详细信息(名称)和组详细信息(名称)。 In the second approach, I would need to fetch the User and Group objects when i am constructing the UserGroupAssoc object itself. 在第二种方法中,我需要在构建UserGroupAssoc对象本身时获取User和Group对象。

In probably a third approach I can design the UserGroupAssoc DTO as follows: 在第三种方法中,我可以按如下方式设计UserGroupAssoc DTO:

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

    //Setters and getters follow
}

In this third approach, I join tables in SQL to obtain only the needed fields for the use-case and then model the DTO accordingly. 在第三种方法中,我在SQL中连接表以仅获取用例所需的字段,然后相应地为DTO建模。

Which is the standard approach to achieve this scenario? 实现此方案的标准方法是哪种? Is joining tables alright in the DTO design? 在DTO设计中加入表格是否合适? Some have opinions that one DTO should correspond to only ONE table and the associated objects should be aggregated in the app layer. 有些人认为一个DTO应该只对应一个表,关联的对象应该在应用层聚合。 That has overhead of doing multiple object fetches from DB right? 这有从DB进行多个对象提取的开销吗? Too confused about the right approach, sorry for such a long explanation! 对于正确的方法感到困惑,抱歉这么长的解释!

Disclaimer: I'm not an ORM specialist... 免责声明:我不是ORM专家......

... but in a classic many-to-many relations you don't need the third data model ( UserGroupAssoc ). ...但是在经典的多对多关系中,您不需要第三个数据模型( UserGroupAssoc )。 The User class will contain a collection of Group s: User类将包含Group s的集合:

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

If you need also the inverse relation (a group contains users) the Group class will look like this: 如果还需要反向关系(一个组包含用户), Group类将如下所示:

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

And again, the classic way of doing it is to use "domain objects" (your DTOs) in the collection ( User and Group instead of userId and groupId ). 再一次,这样做的经典方法是在集合中使用“域对象”(您的DTO)( UserGroup而不是userIdgroupId )。

You normally need a third domain object only if the association table ( User_Group_Association ) contains something else than user_id and group_id (maybe some authorization code that allowed a user to be added to the group, whatever): 仅当关联表( User_Group_Association )包含除user_idgroup_id之外的其他group_id (可能是允许将用户添加到组中的某些授权代码,无论如何)时,通常只需要第三个域对象:

user_id | group_id | auth_code

In this case the UserGroupAssoc class might have this structure: 在这种情况下, UserGroupAssoc类可能具有以下结构:

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

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

And the many-to-many relation between User and Group will transform to two many-to-one relations with this new domain object. UserGroup之间的多对多关系将转换为与这个新域对象的两个多对一关系。 Normally the domain objects are preferred to be used ( User and Group instead of userId and groupId ). 通常,首选使用域对象( UserGroup而不是userIdgroupId )。

Which is the standard approach to achieve this scenario? 实现此方案的标准方法是哪种?

Well, if you were using an ORM framework it would have been the standard way the framework was doing it. 好吧,如果您使用的是ORM框架,它将是框架执行它的标准方式。 But since you have a custom ORM solution, it's hard to say. 由于您有自定义ORM解决方案,因此很难说。

Is joining tables alright in the DTO design? 在DTO设计中加入表格是否合适?

Why should the DTO design in the application layer be influenced by joining tables in the database? 为什么应用层中的DTO设计会受到数据库中表的连接的影响? This is a case for the object-relational impedance mismatch and maybe also the law of leaky abstraction as you can't fully abstract the relational domain into an object domain keeping a 1:1 correspondence. 这是对象 - 关系阻抗不匹配的情况 ,也可能是泄漏抽象定律,因为您无法将关系域完全抽象为保持1:1对应关系的对象域。

Some have opinions that one DTO should correspond to only ONE table and the associated objects should be aggregated in the app layer. 有些人认为一个DTO应该只对应一个表,关联的对象应该在应用层聚合。 That has overhead of doing multiple object fetches from DB right? 这有从DB进行多个对象提取的开销吗?

ORM has some limitations (see again the object-relational impedance mismatch for some issues you might run into) and it is hard to model your domain objects to accommodate the constraints of the relational database, or vice-versa. ORM有一些限制(再次看到您可能遇到的某些问题的对象 - 关系阻抗不匹配),并且很难对域对象进行建模以适应关系数据库的约束,反之亦然。 Reports are good example in this direction. 报告就是这个方向的好例子。

A report normally aggregates data from multiple tables. 报告通常聚合来自多个表的数据。 This is of course no problem for some SQL joins, but how are you going to map the result to DTOs? 对于某些SQL连接,这当然没有问题,但是如何将结果映射到DTO? As you said it yourself... 正如你自己说的那样......

Whenever the DTO exactly corresponds to a single table in the database, it is very straight forward 每当DTO完全对应于数据库中的单个表时,它就非常直接

... but the report result won't map to a single table, it will have to map to fragments from more tables. ...但是报告结果不会映射到单个表,它必须映射到更多表中的片段。

Depending on what your needs are in the application, you might end up with some weird looking classes or with awkward looking SQLs. 根据您在应用程序中的需求,您最终可能会看到一些看起来很奇怪的类或者看起来很笨拙的SQL。 You might end up running more queries than needed to obtain the proper object models and associations between them; 您最终可能会运行比查询所需的更多查询以获取正确的对象模型和它们之间的关联; or you might have more similar DTOs just to limit the number of trips to the database and gain better performance. 或者你可能有更多类似的DTO只是为了限制到数据库的次数并获得更好的性能。

So what I'm trying to say (again the disclaimer that I'm not an ORM specialist) is that not all applications are a good candidate for ORM; 所以我想说的是(我不是ORM专家的免责声明)并非所有应用程序都是ORM的良好候选者; but if you consider going ahead with it maybe look into how Hibernate/JPA is addressing the issues or even go ahead and use them instead. 但是如果你考虑继续它可能会考虑Hibernate / JPA如何解决这些问题,甚至可以继续使用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有外键关系的Hibernate子类 - Hibernate subclass with foreign key relationships 使用外键关系编排Spring Boot CrudRepositories - Orchestrating Spring Boot CrudRepositories with foreign key relationships 保存具有休眠子关系的Hibernate实体失败,并出现外键错误 - Save Hibernate entity with parend child relationships fails with foreign key error 具有一对多关系的实体不会在表中记录外键 - Entity with one-to-many relationships does not record foreign key in table 如何使用 JPA 在实体关系中避免外键约束违规 - How to avoid foreign key constraint violationin in entity relationships using JPA 我们应该有类似的DTO吗? - Should we have similar DTOs? 外键没有默认值 - Foreign key doesn't have a default value 外键必须与引用的主键具有相同的数字列 - Foreign key must have the same number columns as the referenced primary key 如何跨微服务拥有通用的 DTO 或实体 - How to have common DTOs or entities across Microservices 外键必须与引用的主键错误具有相同的列数,但没有具有复合键的实体 - Foreign key must have same number of columns as the referenced primary key error, but a have no entities with composite key
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM