DTO 到实体,反之亦然,控制器和服务之间的哪一层应该处理转换?

问题描述 投票:0回答:2

我通常在 DTO 中实现方法以将它们转换为实体。我这样做是因为我的目标是使实体的代码尽可能干净。但是,我收到的反馈表明实体接受 DTO 作为参数并创建实体更为自然。 我读了这篇文章如何将DTO转换为实体,但即使读了它我也不太理解。

DTO

public record MemberRegistRequestDto(
@NotBlank String oauthId,
@NotBlank String oauthPlatform,
@NotBlank String name,
@NotBlank String profileImg,
@NotBlank String nickname,
@NotNull int birth,
@NotBlank String gender,
@NotBlank String profession,
@NotBlank String signatureColor,
@NotBlank String contentType
) {

    public Member of() {
        return Member.builder()
                .oauthId(oauthId)
                .oauthPlatform(getOAuthProviderFromString(oauthPlatform))
                .name(name)
                .profileImg(profileImg)
                .nickname(nickname)
                .birth(birth)
                .gender(gender)
                .profession(profession)
                .signatureColor(signatureColor)
                .profileImg(profileImg)
                .build();
    }

...

}

实体


@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Table(indexes = @Index(name = "oauth_id", columnList = "oauthId", unique = true))
public class Member extends BaseTimeEntity implements UserDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(nullable = false)
    private String oauthId;
    @Enumerated(EnumType.STRING)
    private OAuthProvider oauthPlatform;
    @Column(nullable = false)
    private String name;
    private String profileImg;
    @Column(nullable = false)
    private String nickname;
    private Integer birth;
    private String gender;
    private String profession;
    @Column(nullable = false)
    private String signatureColor;
    // 로그인 정보 식별 값, 프로필 사진, 필명, 이름, 성별, 생년월일, 이메일
    
    @OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
    private List<Adate> adates;

...

}

将 Dto 转换为实体(服务层)


    @Transactional
    public void registMember(MemberRegistRequestDto memberRegistRequestDto) {
        Member member = memberRegistRequestDto.of();
        memberRepository.save(member);
    }

建议实体接受 DTO 作为参数。

var member = Member.of(memberRegistRequestDto);
  1. 哪一层最好?控制器或服务 我实现了控制器将 DTO 传递给服务并接收它的模式。这是因为我将控制器视为接收用户输入并将其传递给服务的层。

我读过很多 Stack Overflow 上的文章,但一直没能很好地理解它们。

我读过的 干净的编码器博客

创建数据传输对象

java dto
2个回答
0
投票

将 DTO 转换为 DTO 类中的实体会在 DTO 和实体之间引入一定程度的依赖关系(增加耦合),因为 DTO 必须了解实体的内部结构。 Dto 应尽可能简单,并且映射应由有助于创建对象的单独映射器类在控制器中处理。


0
投票

解决问题的一种方法是通过映射器类。

在 DTO 模式中,您拥有包含所有业务逻辑类的域模型和 DTO,它们是简单的 POJO,允许您在单点中仅公开所需的内容。这种模式具有许多优点,例如:减少到服务器的往返次数、最小化网络开销以及将域模型与表示层解耦。

但是,要将域模型的对象转换为 DTO,您应该使用映射器类。这种方法允许您将实体与 DTO 分离,因为实体没有(也不应该)了解 DTO 的内部实现,反之亦然。这种设计还遵循德米特法则(或最少知识原则),即类应该只知道它需要知道的内容。

在您的情况下,您应该拥有

MemberMapper
类,其中包含服务
public static  MemberRegistRequestDto toMemberRegistRequestDto(Member)
,该服务从
MemberRegistRequestDto
实体返回 DTO
Member

这是 Baeldung 的一篇文章,可以帮助您对问题有更多见解和示例 https://www.baeldung.com/java-dto-pattern

© www.soinside.com 2019 - 2024. All rights reserved.