【问题标题】:Micronaut Data DTO projection with properties from joined entities具有来自连接实体的属性的 Micronaut 数据 DTO 投影
【发布时间】:2020-01-28 08:50:29
【问题描述】:

我将 Micronaut Data 与 JPA 一起使用,并且有两个实体。第一个是Recipe

@Entity
public class Recipe {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    @ManyToOne
    private Category category;

    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private Set<Step> steps;

// + other fields, getters and setters
}

第二个是ParseError,指的是Recipe

@Entity
@Table(name = "parse_error")
public class ParseError implements Serializable {
    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    private Recipe recipe;

    @Id
    @Enumerated(EnumType.ORDINAL)
    @Column(name = "problem_area")
    private ProblemArea problemArea;

    private String message;

// + other fields, getters and setters
}

现在我想在 API 中提供具有 ParseError 属性的 DTO,但不提供整个 Recipe 实体,因为它包含在这种情况下不需要的 ManyToOne 和 OneToMany 关系。所以我为此创建了投影 DTO:

@Introspected
public class ParseErrorDto {
    private Integer recipeId;

    private String recipeName;

    private ParseError.ProblemArea problemArea;

    private String message;

// + getters and setters
}

并将listAll()方法添加到ParseErrorRepository中:

@Repository
public interface ParseErrorRepository extends CrudRepository<ParseError, Integer> {
    List<ParseErrorDto> listAll();
}

但似乎 Micronaut Data 无法从嵌套实体投射属性,或者我错过了 DTO 或存储库方法中的某些内容:

ParseErrorRepository.java:22:错误:无法实现存储库 方法:ParseErrorRepository.listAll()。属性 recipeId 不是 存在于实体中:ParseError

我也尝试创建RecipeDto:

@Introspected
public class RecipeDto {
    private Integer id;

    private String name;

    // + getters and setters
}

并相应更新ParseErrorDto

@Introspected
public class ParseErrorDto {
    private RecipeDto recipe;

    private ParseError.ProblemArea problemArea;

    private String message;

    // + getters and setters
}

再次没有成功:

ParseErrorRepository.java:22:错误:无法实现存储库 方法:ParseErrorRepository.listAll()。类型的属性 [recipe] [RecipeDto] 与中声明的等效属性不兼容 实体:ParseError

Micronaut Data 是否能够通过 DTO 投影处理此用例?如果没有,还有其他方法可以在 Micronaut Data 中解决吗?

【问题讨论】:

标签: java jpa micronaut micronaut-data


【解决方案1】:

现在(在最新版本 1.0.0.M1 中)这是不可能的。所以我为此创建了功能请求问题:https://github.com/micronaut-projects/micronaut-data/issues/184

当前的解决方法是将实体 bean 映射到 Java 流或反应流中的 DTO bean,例如手动或通过 Mapstruct 进行属性映射。


更新:这是对来自 cmets 问题的回答,并附有如何使用 Mapstruct 解决方法的示例:

将 Mapstruct 依赖添加到 build.gradle

implementation "org.mapstruct:mapstruct:$mapstructVersion"
annotationProcessor "org.mapstruct:mapstruct-processor:$mapstructVersion"
testAnnotationProcessor "org.mapstruct:mapstruct-processor:$mapstructVersion"

定义映射器:

import org.mapstruct.Mapper;

@Mapper(
    componentModel = "jsr330"
)
public interface ParseErrorMapper {
    ParseErrorDto entityToDto(@NotNull ParseError parseError);

    EntityReference recipeToDto(@NotNull Recipe recipe);
}

这是控制器中该映射器的用法:

@Controller("/parse-error")
public class ParseErrorController {
    private final ParseErrorRepository repository;
    private final ParseErrorMapper mapper;

    public ParseErrorController(ParseErrorRepository repository, ParseErrorMapper mapper) {
        this.repository = repository;
        this.mapper = mapper;
    }

    @Get("all")
    @Transactional
    public Page<ParseErrorDto> getAll(final Pageable pageable) {
        return repository.findAll(pageable).map(mapper::entityToDto);
    }
}

【讨论】:

  • 嘿,我目前有同样的问题,...你能提供一个'手动'映射的例子吗?我的应用程序中有几个部分需要转换器之类的东西,但我不知道“什么是最好的方法”。
  • 我添加了使用 Mapstruct 解决该问题的示例。
猜你喜欢
  • 2021-09-10
  • 2017-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 1970-01-01
  • 2017-03-21
相关资源
最近更新 更多