dto与dto相互转换
但是,当今许多项目正在使用贫血数据模型方法( 我认为 ),并且仍在使用DTO。 每当对象“离开”服务层或“离开”系统时(通过Web服务,rmi等),都将使用它们。 有三种方法:
- 每个实体至少具有一个对应的DTO。 对于视图层中的不同方案,通常不止一个。 在列表中显示用户时,您会有一个DTO,而在“用户详细信息”窗口中显示时,则需要一个扩展的DTO。 我不赞成这种方法,因为在很多情况下,DTO和域结构具有完全相同的结构,因此,存在很多重复的代码+冗余映射。 另一件事是多个DTO的可变性。 即使它们与实体不同,它们在一个或两个字段之间也彼此不同。 为什么重复是一件坏事? 因为要在两个地方进行更改,所以当数据通过多个对象时,很难跟踪问题,并且因为它是重复的。 在同一项目中复制和粘贴是一种罪过。
- 仅当DTO的结构与实体的结构明显不同时才创建DTO。 在所有其他情况下,都使用实体本身。 您不希望显示某些字段的情况(尤其是在通过Web服务公开给第三方的情况下)存在,但并不常见。 有时可以通过序列化机制来处理(例如,将其标记为@JsonIgnore或@XmlTransient) ,但在其他情况下,结构则有所不同。 在这些情况下,应有DTO。 例如,您有一个User和UserDetails,其中UserDetails保存详细信息+当前登录用户与给定用户的关系。 后者与实体无关,因此您创建一个DTO。 但是,对于DirectMessage,在数据库和UI中都具有发件人,收件人,文本和日期时间。 无需DTO。
使用此方法的一个警告(以及下一个警告)。 贫血的实体通常带有ORM(对于Java,则为JPA)。 每当它们退出服务层时,由于需要开放会话的惰性集合,它们可能无效。 您在这里有两个选择:
- 使用OpenSessionInView / OpenEntityManagerInView –这样,会话将保持打开状态,直到您准备好响应为止。 这很容易配置,但不是我的首选-它以一种微妙的方式违反了层边界,这有时会导致问题,特别是对于新手开发人员
- 不要使用惰性集合。 不需要延迟收集。 如果他们应该保留一小部分项目(例如,用户角色列表),或者如果数据可能会增长而使用查询,要么让他们渴望。 是的,无论如何您都不会显示1000条记录,您必须对其进行分页。 如果没有惰性关联(默认情况下@@ ToOne渴望),则在关闭会话时不会有无效的对象
- 完全不使用DTO。 没有明显变化的结构,请尽快应用。 对于较小的项目,这通常是一个好方法。 上面提到的所有内容都适用于此。
因此,我首选的方法是“ 中间方法 ”。 但是在每种情况下都需要考虑很多因素,这可能不适用于规模较大和/或经验较少的团队。 因此,应该选择两个“极端”之一。 由于还需要考虑“无DTO”方法-做@Transient是什么,惰性集合如何影响流量等,因此通常选择“所有DTO”。 但是,尽管这似乎是最安全的方法,但仍有很多陷阱。
首先,您如何从DTO映射到实体,反之亦然? 三种选择:
- 专用的映射器类
- 构造函数– DTO构造函数接受实体并填充自身,反之亦然(记住也要提供默认的构造函数)
- 声明性映射(例如Dozer )。 这实际上与第一个选项相同–它外部化了映射。 它甚至可以与专用的映射器类一起使用
- 串联映射它们(必要时)。 这可能会生成无法维护的代码,因此不是首选
我更喜欢构造方法,至少是因为创建的类更少。 但是它们本质上是相同的(DTO并不以封装闻名,因此您的所有属性无论如何都公开)。 这是使用DTO和两种“映射”方法时的准则列表:
- 不要生成过多的冗余代码。 如果两种情况需要稍微不同的DTO,请重用。 无需为一两个字段之间的差异创建新的DTO
- 不要将表示逻辑放在映射器/构造函数中。 例如,如果( entity.isActive() ) dto.setStatus(“ Active”); 这应该在视图层中发生
- 不要将实体与DTO一起偷偷摸摸。 DTO不应具有作为实体的成员。 通常,不应在服务层之外使用实体(这有点极端,但是如果我们在所有地方都使用DTO,则应该保持一致并坚持这种做法)
- 不要在控制器中使用mappers / entity-to-dto构造函数,而在服务层中使用它们。 首先使用DTO的原因是实体可能是ORM绑定的,并且它们可能在会话外部(即服务层外部)无效。
- 如果使用映射器,则首选静态映射器方法。 映射器没有状态,因此不需要实例化它们。 (而且不必嘲笑,包装等)。
- 如果使用映射器,则无需为每个实体(+多个DTO)使用单独的映射器。 可以将相关实体分组在一个映射器中。 例如Company , CompanyProfile , CompanySubsidiary可以使用相同的映射器类
只需确保在项目开始时就做出所有这些决定,然后确定哪种情况适用于您的方案(团队规模和经验,项目规模,领域复杂性)。
参考: 在的DTO从我们JCG伙伴 Bozho在Bozho的科技博客 。
相关文章 :
- Spring和AspectJ的领域驱动设计
- 在域驱动设计中使用状态模式
- ORM问题
- 什么是依赖倒置? 是IoC吗?
- 框架使开发人员愚蠢吗?
- 每个程序员都应该知道的事情
- JDK中的设计模式
- Java最佳实践
翻译自: https://www.javacodegeeks.com/2011/09/on-dtos.html
dto与dto相互转换