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
相关产品推荐
相关产品推荐

