我有一个具有post和post_comments表的一对多映射,我们的要求是在两个表中仅检索很少的值,并像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数据jpa直接实现此目的。使用替代映射实现。
PostRepository我们只需要从post表中获取标题,并从postDemo类中所需的postcomment表中获取评论,因为我们无法在单个实例中执行映射,所以我通过创建中间投影来委托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项目?
您按标题搜索评论有点奇怪。标题不是唯一的,同一标题可能有10个不同的帖子,因此您将获取所有10个帖子的评论。我建议您按帖子ID搜索评论。
@Repository
public interface PostCommentRepository extends JpaRepository<PostComment, Long> {
//not entirely sure if that is valid jpql, should work.
// Otherwise accept "Long postId", then sql: select review from post_comment where post_id = :postId
@Query("select c.review from PostComment c where c.post = :post")
List<String> findAllByPost(Post post);
}
... main() {
...
List<String> reviews = commentRepo.findAllByPost(post);
PostDTO dto = new PostDTO(post.getTitle(), reviews);
}