[英]Micronaut Data DTO projection with properties from joined entities
I use Micronaut Data with JPA and have two entities.我将 Micronaut Data 与 JPA 一起使用,并有两个实体。 The first one is
Recipe
:第一个是
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
}
The second one is ParseError
which refers to Recipe
:第二个是
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
}
Now I would like to provide DTO in API with ParseError
properties but not with whole Recipe
entity because it contains ManyToOne and OneToMany relations which are not needed in this case.现在我想在 API 中提供带有
ParseError
属性的 DTO,但不提供整个Recipe
实体,因为它包含在这种情况下不需要的 ManyToOne 和 OneToMany 关系。 So I created projection DTO for that:所以我为此创建了投影DTO:
@Introspected
public class ParseErrorDto {
private Integer recipeId;
private String recipeName;
private ParseError.ProblemArea problemArea;
private String message;
// + getters and setters
}
And added listAll()
method into ParseErrorRepository
:并将
listAll()
方法添加到ParseErrorRepository
:
@Repository
public interface ParseErrorRepository extends CrudRepository<ParseError, Integer> {
List<ParseErrorDto> listAll();
}
But it seems that Micronaut Data is not able to project properties from nested entities or I missed something in the DTO or the repository method:但似乎 Micronaut Data 无法从嵌套实体中投影属性,或者我错过了 DTO 或存储库方法中的某些内容:
ParseErrorRepository.java:22: error: Unable to implement Repository method: ParseErrorRepository.listAll().
ParseErrorRepository.java:22:错误:无法实现存储库方法:ParseErrorRepository.listAll()。 Property recipeId is not present in entity: ParseError
实体中不存在属性 recipeId:ParseError
I also tried to create RecipeDto
:我还尝试创建
RecipeDto
:
@Introspected
public class RecipeDto {
private Integer id;
private String name;
// + getters and setters
}
And updated ParseErrorDto
accordingly:并相应地更新
ParseErrorDto
:
@Introspected
public class ParseErrorDto {
private RecipeDto recipe;
private ParseError.ProblemArea problemArea;
private String message;
// + getters and setters
}
Again no success:再次没有成功:
ParseErrorRepository.java:22: error: Unable to implement Repository method: ParseErrorRepository.listAll().
ParseErrorRepository.java:22:错误:无法实现存储库方法:ParseErrorRepository.listAll()。 Property [recipe] of type [RecipeDto] is not compatible with equivalent property declared in entity: ParseError
[RecipeDto] 类型的属性 [recipe] 与实体中声明的等效属性不兼容:ParseError
Is Micronaut Data able to handle this use case by DTO projection? Micronaut Data 是否能够通过 DTO 投影处理此用例? If not then is there another way how can I solve it in Micronaut Data?
如果没有,那么还有另一种方法如何在 Micronaut Data 中解决它?
Now (in latest version 1.0.0.M1) it is not possible.现在(在最新版本 1.0.0.M1 中)这是不可能的。 So I created feature request issue for that:https://github.com/micronaut-projects/micronaut-data/issues/184
所以我为此创建了功能请求问题:https://github.com/micronaut-projects/micronaut-data/issues/184
Current workaround is to map entity bean into DTO bean in Java stream or reactive stream for example and do the properties mapping manually or by Mapstruct. Current workaround is to map entity bean into DTO bean in Java stream or reactive stream for example and do the properties mapping manually or by Mapstruct.
Update: Here is an answer to question from comments with an example how to do the workaround using Mapstruct:更新:这是对评论中问题的回答,并附有如何使用 Mapstruct 解决方法的示例:
Add Mapstruct dependency into build.gradle :将 Mapstruct 依赖项添加到build.gradle 中:
implementation "org.mapstruct:mapstruct:$mapstructVersion"
annotationProcessor "org.mapstruct:mapstruct-processor:$mapstructVersion"
testAnnotationProcessor "org.mapstruct:mapstruct-processor:$mapstructVersion"
Define mapper:定义映射器:
import org.mapstruct.Mapper;
@Mapper(
componentModel = "jsr330"
)
public interface ParseErrorMapper {
ParseErrorDto entityToDto(@NotNull ParseError parseError);
EntityReference recipeToDto(@NotNull Recipe recipe);
}
And here is a usage of that mapper in the controller:这是 controller 中该映射器的用法:
@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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.