具有 OneToMany 关系并希望使用 DTO 的 JPA 实体

JPA Entity that has a OneToMany relationship and want to use DTO

我有一个名为“Review”的实体,它与“User”实体具有 OneToOne 关系,与“ReviewStage”实体具有 OneToMany 关系。我已经实现了一个 DTO 模式,所以我也有 ReviewDTO,它实际上是发送到 UI 的内容。我正在使用 mapstruct 将实体映射到 dto。一切正常,但是,我宁愿在关系映射中使用 UserDTO 和 ReviewStageDTO。

效果很好:

@Entity
@Getter @Setter @NoArgsConstructor
public class Review {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long reviewId;
    
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "ownerId")
    private User owner;

    @OneToMany(mappedBy = "reviewId")
    private Set<ReviewStage> stages;

}

为了好玩,我尝试了这个,但显然行不通:

@Entity
@Getter @Setter @NoArgsConstructor
public class Review {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long reviewId;
    
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "ownerId")
    private UserDTO owner;

    @OneToMany(mappedBy = "reviewId")
    private Set<ReviewStageDTO> stages;

}

我只需要在正确的方向上轻推一下。谢谢,

relationships 应该只在 entities 之间,如果你想为 Review 创建一个 dto 并且在这个 dto 里面你想 return UserDto 例如你应该创建一个 mapstruct class 来映射 UserEntityUserDTO

例子

class UserDto {
    /// put any fields here that you want to map
}

class ReviewDto {
    UserDto user;
}

@Mapper(componentModel = "spring")
class UserMapper {
    UserDto map(User user);
}

@Mapper(componentModel = "spring", uses={UserMapper.class})
class ReviewMapper {
    ReviewDto map(Review review);
}

如果您关心性能,我建议您看一下 Blaze-Persistence Entity Views 提供的内容。

我创建了库以允许在 JPA 模型和自定义接口或抽象 class 定义的模型之间轻松映射,类似于 Spring 类固醇数据投影。这个想法是您按照自己喜欢的方式定义目标结构(领域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

您的用例的 DTO 模型与 Blaze-Persistence 实体视图类似:

@EntityView(Review.class)
public interface ReviewDTO {
    @IdMapping
    Long getReviewId();
    UserDTO getOwner();
    Set<ReviewStageDTO> getStages();

    @EntityView(User.class)
    interface UserDTO {
        @IdMapping
        Long getId();
        String getName();
    }

    @EntityView(ReviewStage.class)
    interface ReviewStageDTO {
        @IdMapping
        Long getId();
        String getName();
    }
}

查询就是将实体视图应用于查询,最简单的就是通过 id 进行查询。

ReviewDTO a = entityViewManager.find(entityManager, ReviewDTO.class, id);

Spring 数据集成让您几乎可以像 Spring 数据投影一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Optional<ReviewDTO> findByReviewId(long reviewId);

请注意,这只会获取实际需要的状态。使用 MapStruct 或其他 bean 映射解决方案,您必须自己处理高效的提取。