我有一个实体作者,它拥有一系列具有publishedDate属性的书籍。
每个作者都有一本收藏书,它们的映射如下:
public class Author {
@Id
private Long id;
private String name;
@JsonBackReference
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "author")
private List<Book> listBook = new ArrayList<>();
// other fields
// getters and setters
书
public class Book {
@Id
private Long id;
@ManyToOne(fetch = FetchType.EAGER, optional = false)
private Author author;
private LocalDateTime publishedDateTime;
我想通过 ID 获取作者,并将最新书籍作为 Dto,即
@Data
public AuthorNewestBookDto {
Long authorId;
String name;
Book newestBook;
将查询结果直接投射到 Dto 中。不需要映射器。高效交易 数据库。类似于这里。
使用mapstruct映射器返回一个包含书籍集合的作者实体并使用@Before 注释仅返回集合中最新的一本书。类似于这里。
是否有更好的方法来进行到 AuthorNewestBookDto 的转换,我需要将集合的单个最新成员检索到嵌套的单数 Dto 中。
我考虑过是否可以在休眠阶段使用 DtoResultTransformer (Hibernate 6)来完成此操作。
希望这对于 Stack Overflow 来说不是太固执己见。
MapStruct 有多种工具可用于处理此类情况:
Qualifier
我们可以提供实体字段类型
List<Book>
和DTO字段类型Book
:之间的自定义映射逻辑
interface BookingMapping {
@Mapping(target = "newestBook", source = "listBook", qualifiedBy=NewestBookQualifier.class)
//.. other fields
AuthorNewestBookDto toDtoQualifiedBy(Author entity);
}
...
public class BookingMappingUtil {
@NewestBookQualifier
BookDto toNewestBook(List<Book> listBook) {
return listBook.stream()
.max(Comparator.comparing(Book::getPublishedDateTime))
.orElse(null)
}
...
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface NewestBookQualifier{
}
可迭代到不可迭代的示例(官方 MapStruct-Example 项目)。
@Named
在这种情况下,我们不需要创建新的注释。 命名注释文档
@Mapping(target = "newestBook", source = "listBook", qualifiedByName="toNewestBook" )
//.. other fields
AuthorNewestBookDto toDtoQualifiedByName(Author entity);
@Named("toNewestBook")
default BookDto toNewestBook(List<Book> listBook) {
return listBook.stream()
.max(Comparator.comparing(Book::getPublishedDateTime))
.orElse(null)
}
@Mapping(.. expression=".." ..)
我们能够将业务逻辑存储为字符串。这种方法可能不可读,但很容易实现。 表达式文档
@Mapping(target = "newestBook",
source = "listBook",
expression = "java( listBook.stream().max(java.util.Comparator.comparing(Book::getPublishedDateTime)).orElse(null) )" )
//.. other fields
AuthorNewestBookDto toDtoQualifiedByName(Author entity);