在java中使用Mapstruct如何将内部Entity映射到Entity?

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

我有以下数据(为了简洁和清晰,删除了其他字段):

    @Entity
    class CategoryEntity {
        private Long id;
        private String name;
    }
    
    @Entity
    class ProductEntity {
        private Long id;
        private String name;
        private CategoryEntity category;
    }

输入的是

record ProductDto(String name, String categoryName) { }

Service 中的代码如下所示:

    public ProductEntity processProduct(ProductDto productDto) {
        // find and check it exists
        CategoryEntity categoryEntity = categoryService.findCategoryByName(productDto.categoryName());

        ProductEntity productEntity = productMapper.toEntity(productDto);
        productEntity.setCategory(categoryEntity);

        // do some processing
        // ... 
        return productEntity;
    }

如何实现映射器将 Product dto 转换为实体并使用提供的 Category 实体而无需手动设置?

我尝试将类别实体实例作为参数传递:

@Mapper
interface ProductMapper {
    @Mapping(target = "category", source = "categoryEntity")
    ProductEntity toEntity(ProductDto dto, CategoryEntity categoryEntity);
}

但在这种情况下,categoryEntity.id 用于设置结果productEntity.id 这是完全错误的。

这是带有 MapStruct 1.5.5 的 Quarkus 项目。

java mapstruct
1个回答
0
投票

请记住,采用两个参数(没有

@MappingTarget
注释)的映射方法用于将合并对象到新对象中,因此,与源之一匹配的任何目标属性都用于映射。

在上面(简化的)情况下,您可以使用这种注释组合来达到您想要的目标:

@Mapping(target = "category", source = "categoryEntity")
@Mapping(target = "name", source = "dto.name")
@Mapping(target = "id", ignore = true)
ProductEntity toEntity(ProductDto dto, CategoryEntity categoryEntity);

第一个和你的一样;第二个是必要的,因为有两个

name
属性,您必须设置哪个属性必须用于目标。第三个是不使用
id
来设置
categoryEntity

生成的代码是这样的:

@Override
public ProductEntity toEntity(ProductDto dto, CategoryEntity categoryEntity) {
    if ( dto == null && categoryEntity == null ) {
        return null;
    }

    ProductEntity.ProductEntityBuilder productEntity = ProductEntity.builder();

    if ( dto != null ) {
        productEntity.name( dto.name() );
    }
    productEntity.category( categoryEntity );

    return productEntity.build();
}

当然,这种方法可能无法扩展到您的情况,我的意思是:为了使其实现您想要的逻辑,您必须手动将源之间的每个冲突属性设置为手动映射,以及您不想要的每个属性被覆盖而被忽略。

也许在这种情况下,使用 mapstruct 并不是将

category
注入
product
实体的最佳解决方案,但我不知道您的应用程序的真正复杂性。

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