【问题标题】:How to create nested projection of one to many mapping in spring data jpa如何在spring data jpa中创建一对多映射的嵌套投影
【发布时间】:2020-06-23 17:41:45
【问题描述】:

我有一个与 post 和 post_cmets 表的一对多映射,我们的要求是只检索两个表中的几个值,然后像 postDTO 那样作为一对多映射发送回调用者。下面是我们的代码。

发布实体

@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 --> 我们需要的响应格式。

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

    String title;

    @Builder.Default
    List<PostCommentsDTO> comments;
}

PostCommentsDTO --> 一对多嵌套投影值。

@Data
@Builder
public class PostCommentsDTO {

    String review;

}

因为我们无法直接使用 spring data jpa 来实现这一点。使用替代映射实现。

PostRepository 我们只需要从 post 表中获取标题,并从 postcomment 表中获取所需的评论作为 postDTO 类,因为我们无法在单个实例中执行映射我在 Java 中委托映射如下创建中间投影。

@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 项目?

【问题讨论】:

    标签: java hibernate jpa spring-data-jpa


    【解决方案1】:

    由于您手头已经有了标题,因此您只缺少评论,因此只搜索评论,然后将它们与标题结合起来。

    另外,您按标题搜索 cmets 有点奇怪。标题不是唯一的,可能有 10 个不同的帖子具有相同的标题,因此您将获取所有 10 个帖子的 cmets。建议你按post id搜索cmets。

    @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);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-10
      • 2022-12-02
      • 1970-01-01
      • 2020-02-02
      • 2018-08-07
      • 2021-06-19
      • 1970-01-01
      相关资源
      最近更新 更多