我想知道,如果是这样,为什么实体框架不提供逻辑来创建具有相同属性的新对象以在层之间传输数据?
我使用在实体框架中生成的实体对象。
我想知道,如果是这样,为什么实体框架不提供逻辑来创建具有相同属性的新对象以在层之间传输数据?
我使用在实体框架中生成的实体对象。
Answers:
它是由你决定。
大多数人会告诉您这不是一个好习惯,但在某些情况下您可以避免。
EF从来没有与DDD很好地结合使用,原因有很多,但有两个很突出:您不能在实体上使用参数化的构造函数,也不能封装集合。DDD依赖于此,因为域模型应同时包含数据和行为。
在某种程度上,EF会强制您使用贫血领域模型,在这种情况下,您可以将实体用作DTO。如果使用导航属性,则可能会遇到一些问题,但是您可以序列化这些实体并通过网络发送它们。不过,这可能不切实际。您将必须控制具有不需要传递属性的每个实体的序列化。更简单的方法是简单地设计为数据传输量身定制的单独的类。为此创建了类似AutoMapper的库。
例如:假设您有一个Person
具有以下定义的类:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; get; }
// plus a bunch of other properties relevant about a person
}
假设你想不想找个显示员工列表,它可能是实际只是发送Id
,FirstName
和LastName
。但是,您必须发送所有其他不相关的属性。如果您不关心响应的大小,那么这并不是什么大问题,但是通常的想法是仅发送相关数据。另一方面,您可以设计一个API,该API返回人员列表,在这种情况下,可能需要发送所有属性,从而可以序列化和发送实体。在这种情况下,创建DTO类是有争议的。有些人喜欢混合实体和DTO,有些则不喜欢。
为了回答您的最新问题,EF是一个ORM。它的工作是将数据库记录映射到对象,反之亦然。在通过EF之前和之后对这些对象执行的操作不是其关注的一部分。也不应该。
不它不是。
理想情况下,DTO将与您的持久性存储库(也就是您的数据库表)匹配。
但是您的业务类别不一定匹配。您可能需要其他类,或者将分离的类或加入的类添加到数据库中。如果您的应用程序很小,则可能不会真正看到这种问题,但是在大中型应用程序中,这种情况经常发生。
另一件事是,DTO是处理持久性的领域的一部分,而您的业务层对此一无所知。
这实际上是一个非常糟糕的主意。马丁·福勒(Martin Fowler)撰写了有关本地DTO的文章。
长话短说,DTO
Pattern用于在流程外(例如,通过电线而不是在同一流程内的各层之间)传输数据。
不,这是一个坏习惯。
原因如下:
@JsonIgnore
来自Java世界),但这会导致下一个问题...get
实体的方法。因此,使用某种映射器工具可以更轻松,更安全地帮助您完成此任务,将实体字段映射到Dto。
为了完成@Dherik所说的,将实体对象用作数据传输对象的主要问题是:
在事务中,您冒着提交对实体所做的更改的风险,因为您将其用作DTO(即使您可以在事务中分离会话的实体,大多数情况下,您需要先检查此状态才能实体-DTO上的任何修改,并确保您不参与交易或如果您不希望这些修改被保留,则确保会话已关闭)。
您在客户端和服务器之间共享的数据大小:有时,您不想将实体的所有内容发送到客户端,以最大程度地减少请求响应的大小。将DTO与实体分开更加灵活,从而可以在某些用例中专门化要发送的数据。
可见性和维护性:您必须在实体的字段上管理jpa / hibernate批注,并维护jackson批注以在json的同一位置进行序列化(即使您可以将它们与实体实现分开,也可以将它们放入由继承的接口中)实体)。然后,如果您在添加新字段时更改了DTO内容,那么另一个人可能会认为这是实体的字段,因此可能是数据库中相关表的字段(即使您可以@Transient
在所有DTO字段上使用注释)对于这种情况..!)。
我认为,当您阅读实体时,它会产生噪音,但是我的观点肯定是主观的。