如何在Spring Data JPA中创建一对多映射的嵌套投影 [英] How to create nested projection of one to many mapping in spring data jpa

查看:198
本文介绍了如何在Spring Data JPA中创建一对多映射的嵌套投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有post和post_comments表的一对多映射,我们的要求是仅检索两个表中的几个值,然后像postDTO一样以一对多映射的形式发送回调用方.下面是我们的代码.

I have a one to many mapping with post and post_comments table,our requirement is to retrieve only few values in both the tables and send back to caller as one to Many Mapping like postDTO. Below is our code.

发布实体

@Entity(name = "Post")
@Getter
@Setter
public class Post {

    @Id
    private Long id;

    private String title;

    private LocalDateTime createdOn;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "post", orphanRemoval = true)
    private List<PostComment> comments = new ArrayList<>();

    public void addComment(PostComment comment) {
       this.comments.add(comment);
       comment.setPost(this);
    }

}

PostCommentEntity

@Getter
@Setter
public class PostComment {

    @Id
    private Long id;

    private String review;

    private LocalDateTime createdOn;

    public PostComment(String review) {
        this.review = review;
        this.createdOn = LocalDateTime.now();
    }

    @ManyToOne
    private Post post;

}

postDTO ->我们需要的期望响应格式.

postDTO --> Desired response format which we need.

@Getter
@Setter
@Builder
@ToString
public class PostDTO {

    String title;

    @Builder.Default
    List<PostCommentsDTO> comments;
}

PostCommentsDTO ->一对多的嵌套投影值.

PostCommentsDTO --> One to many nested projection value.

@Data
@Builder
public class PostCommentsDTO {

    String review;

}

由于我们无法使用spring数据jpa直接实现此目的.使用替代映射实现.

As we couldn't achieve this directly using spring data jpa. Achieved using alternative mapping.

PostRepository 我们只需要从post表中获取标题,并从postDemo类中所需的postcomment表中获取评论,因为我们无法在单个实例中执行映射,所以我在Java中通过以下方式委派了映射:创建中间投影.

PostRepository We need to get only title from post table and reviews from postcomment table desired as postDTO class, as We cannot perform mapping in a single instance I'm delegating the mapping in Java as below by creating intermediary projection.

@Repository
public interface PostRepository extends JpaRepository<Post, Long> {

    @Query("SELECT p.title as title, c.review as review FROM Post p JOIN p.comments c where p.title = :title")
    List<PostCommentProjection> findByTitle(@Param("title") String title);
}

PostCommentProjection

public interface PostCommentProjection {

    String getTitle();

    String getReview();

}

然后终于用Java

    List<PostCommentProjection> postCommentProjections = this.postRepository.findByTitle("Post Title");

    final Function<Entry<String, List<PostComments>>, PostDTO> mapToPostDTO = entry -> PostDTO.builder()
            .title(entry.getKey()).comments(entry.getValue()).build();
    final Function<PostCommentProjection, String> titleClassifier = PostCommentProjection::getTitle;
    final Function<PostCommentProjection, PostComments> mapToPostComments = postCommentProjection -> PostComments
            .builder().review(postCommentProjection.getReview()).build();
    final Collector<PostCommentProjection, ?, List<PostComments>> downStreamCollector = Collectors
            .mapping(mapToPostComments, Collectors.toList());

    List<PostDTO> postDTOS = postCommentProjections.stream()
            .collect(groupingBy(titleClassifier, downStreamCollector)).entrySet().stream().map(mapToPostDTO)
            .collect(toUnmodifiableList());

是否存在一种直接从存储库中直接获取 POSTDTO 项目的有效或自动方法?

Is there an effective or automatic way to fetch the POSTDTO project directly from repository?

推荐答案

由于您已经有了标题,因此您仅缺少评论,因此仅搜索评论,然后将其与标题结合起来.

Since you already have the title on hand, you're only lacking the reviews, so search the reviews only and then combine them with the title.

此外,您正在按标题搜索评论也有点奇怪.标题不是唯一的,同一标题可能有10个不同的帖子,因此您将获取所有10个帖子的评论.我建议您按帖子ID搜索评论.

Also, it's a bit strange that you are searching for comments by title. The title is not unique, there may be 10 different posts with the same title, so you will fetch the comments for all 10 posts. I suggest you search for comments by post id.

@Repository
public interface PostCommentRepository extends JpaRepository<PostComment, Long> {
    
    @Query("select review from PostComment where post.id = :postId")
    List<String> findAllReviewsByPostId(Long postId);
}

... main() {
   ...
   List<String> reviews = commentRepo.findAllReviewsByPostId(post.getId());
   PostDTO dto = new PostDTO(post.getTitle(), reviews);
}

这篇关于如何在Spring Data JPA中创建一对多映射的嵌套投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆