获取Spring Data JPA DTO投影的第二种最佳方式

212 阅读1分钟

我刚刚偶然发现了Vlad Mihalcea的这篇伟大的文章,题目是《获取Spring Data JPA DTO投影的最佳方式》。它在reddit上也得到了一些不错的关注。这是一个很好的用例和合适的解决方案,我想快速展示第二种 最好的方法,这次是用jOOQ来做同样的事情。

提示: 你可以很容易地将jOOQ与Spring Data JPA一起使用,只需使用Spring Boot的jOOQ启动器,将DataSource ,然后将所有资源库查询委托给jOOQ。

我将直接跳到帖子中的分层DTO投射,将事物投射到这个类型层次中:

public record PostCommentDTO (
    Long id,
    String review
) {}

public record PostDTO (
    Long id,
    String title,
    List<PostCommentDTO> comments
) {}

所以,我们会像这样使用jOOQ,使用MULTISET 值构造器

List<PostDTO> result =
ctx.select(
        POST.ID,
        POST.TITLE,
        multiset(
            select(POST_COMMENT.ID, POST_COMMENT.REVIEW)
            .from(POST_COMMENT)
            .where(POST_COMMENT.POST_ID.eq(POST.ID))
        ).convertFrom(r -> r.map(mapping(PostCommentDTO::new)))
   )
   .from(POST)
   .where(POST.TITLE.like(postTitle))
   .fetch(mapping(PostDTO::new));

或者,使用MULTISET_AGG 聚合函数,如果这更适合你的话(如果你嵌套的集合不超过1层)。

List<PostDTO> result =
ctx.select(
        POST_COMMENT.post().ID,
        POST_COMMENT.post().TITLE,
        multisetAgg(POST_COMMENT.ID, POST_COMMENT.REVIEW)
            .convertFrom(r -> r.map(mapping(PostCommentDTO::new)))
   .from(POST_COMMENT)
   .where(POST_COMMENT.post().TITLE.like(postTitle))
   .fetch(mapping(PostDTO::new));

这两种解决方案都是完全类型安全的,使用临时的记录转换。你改变了模式,重新生成了代码,你的代码就不再能编译了。

除了查询本身,你不需要写任何额外的基础设施逻辑。

很酷,对吗?)