这是一个完美的用例Blaze-持久性实体视图 https://github.com/Blazebit/blaze-persistence#entity-view-usage.
Blaze-Persitence 是基于 JPA 的查询生成器,它支持基于 JPA 模型的许多高级 DBMS 功能。我在其之上创建了实体视图,以允许在 JPA 模型和自定义接口定义的模型之间轻松映射,就像类固醇上的 Spring Data Projections 一样。这个想法是,您按照自己喜欢的方式定义目标结构,并通过 JPQL 表达式将属性(getter)映射到实体模型。由于属性名称用作默认映射,因此您通常不需要显式映射,因为 80% 的用例都具有作为实体模型子集的 DTO。
您的模型的映射可能看起来像下面一样简单
@EntityView(Book.class)
interface BookDto {
@IdMapping
Long getId();
String getAuthor();
String getTitle();
@Limit(limit = 5, order = { "timestamp DESC", "id DESC"})
List<CommentDto> getComments();
}
@EntityView(Comment.class)
interface CommentDto {
@IdMapping
Long getId();
String getBody();
}
查询是将实体视图应用于查询,最简单的就是通过 id 进行查询。
BookDto dto = entityViewManager.find(entityManager, BookDto.class, id);
但是 Spring Data 集成允许您像 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/1.4/entity-view/manual/en_US/#spring-data-features https://persistence.blazebit.com/documentation/1.4/entity-view/manual/en_US/#spring-data-features
The @Limit
注释是在几周前引入的,并将成为新版本 1.5.0-Alpha2 的一部分,该版本将在未来几天内发布。如果您愿意,可以同时使用 1.5.0-SNAPSHOT。
生成的SQL大致是这样的
select b.id, b.author, b.title, c.id, c.body
from book b
cross apply (
select c.id, c.body, c.timestamp
from book_comments bc
join comment c on bc.comments_id = c.id
where bc.book_id = b.id
order by timestamp desc, id desc
limit 5
) c
您还可以使用查询生成器手动编写该查询,大致如下所示
criteriaBuilderFactory.create(entityManager, Tuple.class)
.from(Book.class, "b")
.leftJoinLateralEntitySubquery("b.comments", "c", "subC")
.orderByDesc("subC.timestamp")
.orderByDesc("subC.id")
.setMaxResults(5)
.end()
.getResultList();