You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring中使用DTO时服务间数据交互的最佳实践咨询

Spring中DTO场景下服务间协同的最佳实践问题

刚接触Spring框架,在使用DTO时对服务间的协同逻辑存在困惑,以下通过示例代码说明问题:

@Entity
public class Author {
    private int id;
    private String name;
}

public class AuthorDto {
    private int id;
    private String name;
}

@Entity
public class Book {
    private int id;
    private String title;
    private Author author;
}

public class BookDto {
    private int id;
    private String title;
    private String authorName;
}

// AuthorRepository extends CrudRepository
// BookRepository extends CrudRepository

@Service
public class AuthorService {

    public AuthorDto getByName(String name) {
        Assert.nonNull(name, "name is null");

        Author author = this.authorRepository.getByName(name).orElseThrow(() -> new AuthorNotFoundException(name));
        return AuthorMapper.toDto(author);
    }

}

@Service
public class BookService {

    public BookDto register(BookDto book) {
        // Check book validity.
        Book bookEntity = BookMapper.toEntity(book);

        // How do I get the Author information for entity persistence ?
        Author author = ???
        bookEntity.setAuthor(author);

        bookEntity = this.bookRepository.save(bookEntity);
        return BookMapper.toDto(bookEntity);
    }

}

在BookService的register方法中,需获取Author实体以完成Book的持久化,尝试了三种实现方式但均存在疑虑:

尝试的三种实现方式及疑虑

① 直接使用AuthorRepository

public BookDto register(BookDto book) {
    //…
    Author author = this.authorRepository.getByName(book.getAuthorName())
        .orElseThrow(() -> new AuthorNotFoundException(book.getAuthorName()));
    //…
}

此方式会重复AuthorService中的代码,复杂场景下易引发错误。

② 使用AuthorService

public BookDto register(BookDto book) {
    //…
    Author author = AuthorMapper.toEntity(this.authorService.getByName(book.getAuthorName()));
    //…
}

此方式会产生不必要的实体与DTO转换,且转换后的实体可能脱离底层EntityManager,增加额外处理步骤。

③ 利用protected作用域实现服务通信

@Service
public class AuthorServiceImpl implements AuthorService {

    protected Author _getByName(String name) {
        Assert.nonNull(name, "name is null");

        return this.authorRepository.getByName(name)
            .orElseThrow(() -> new AuthorNotFoundException(name));
    }

    public AuthorDto getByName(String name) {
        return AuthorMapper.toDto(this._getByName(name));
    }

}

@Service
public class BookServiceImpl implements BookService {

    public BookDto register(BookDto book) {
        // Do check for book validity.
        Book bookEntity = BookMapper.toEntity(book);

        Author author = this.authorServiceImpl._getByName(book.getAuthorName());
        bookEntity.setAuthor(author);

        bookEntity = this.bookRepository.save(bookEntity);
        return BookMapper.toDto(bookEntity);
    }

}

此方式让各服务管理自身实体,但不确定是否为良好实践。

目前未找到适配该场景的明确方案,特咨询最佳实现方式。


内容的提问来源于stack exchange,提问作者Amaury S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:21:05