Hibernate - 限制嵌套集合的大小

2024-04-21

我有以下型号:

@Entity
@Data
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String author;
    private String title;
    @OneToMany(cascade = CascadeType.MERGE)
    private List<Comment> comments;
}

@Entity
@Data
public class Comment {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String body;
    private LocalDateTime timestamp;
}

我正在努力实现的是获取所有带分页的书籍,但所有这些书籍的评论集合都应限制为 5 个最新条目。我想出了以下本机查询(mssql):

select *
from book b
         left join book_comments bc on bc.book_id = b.id and bc.comments_id in (
    select top 5 c2.id
    from comment c2
             join book_comments bc2 on c2.id = bc2.comments_id
             join book b2 on bc2.book_id = b2.id
    where bc2.book_id = b.id
    order by c2.timestamp desc
)
         left join comment c
                   on bc.comments_id = c.id

当我在控制台中运行该查询时,该查询返回正确的结果集,但当它由应用程序运行时,如下所示:

public interface BookRepository extends JpaRepository<Book, Long> {
    @Query(value = "select * " +
            "from book b " +
            "         left join book_comments bc on bc.book_id = b.id and bc.comments_id in ( " +
            "    select top 5 c2.id " +
            "    from comment c2 " +
            "             join book_comments bc2 on c2.id = bc2.comments_id " +
            "             join book b2 on bc2.book_id = b2.id " +
            "    where bc2.book_id = b.id " +
            "    order by c2.timestamp desc " +
            ") " +
            "         left join comment c " +
            "                   on bc.comments_id = c.id",
            nativeQuery = true)
    Page<Book> findAll(Pageable pageable);
}

抛出语法错误:

    "localizedMessage": "Incorrect syntax near 'id'.",
    "message": "Incorrect syntax near 'id'.",
    "suppressed": []
},
"localizedMessage": "could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet",

我观察到执行计数查询时出现此语法错误。我还尝试提供 countQuery 属性(相同的查询,但不是 *,而是 count(*))。这样我就不会出现语法错误,但它返回不正确的结果集 - 书被重复 N 次,其中 N 是评论集合的大小。

我该如何解决这个问题?对于这个案例,有没有更好的处理方法呢?

edit:

计数查询:

select count(*)
from book b
         left join book_comments bc on bc.book_id = b.id and bc.comments_id in (
    select top 5 c2.id
    from comment c2
             join book_comments bc2 on c2.id = bc2.comments_id
             join book b2 on bc2.book_id = b2.id
    where bc2.book_id = b.id
    order by c2.timestamp desc
)
         left join comment c
                   on bc.comments_id = c.id

编辑(获取查询):

select comments0_.book_id as book_id1_1_0_, comments0_.comments_id as comments2_1_0_, comment1_.id as id1_2_1_, comment1_.body as body2_2_1_, comment1_.timestamp as timestam3_2_1_ from book_comments comments0_ inner join comment comment1_ on comments0_.comments_id=comment1_.id where comments0_.book_id=?

这是一个完美的用例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();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate - 限制嵌套集合的大小 的相关文章

  • Postgresql 中的 id 列位置重要吗?

    我正在测试删除主键列 id 的迁移 我想使用外键作为主键 当我运行并恢复迁移时 我看到表的状态是相同的 只是 id 列现在是最后一个 它会以任何方式改变我的数据库的行为吗 我是否应该费心去恢复迁移恢复代码中的列顺序 理论上一切都应该没问题
  • 如何使用 Selenium WebDriver 和 Java 滚动特定的 DIV?

    WebDriver 无法识别某些 WebElement WebDriver 无法找到浏览器可见区域中不可见的元素 In order to make the WebElement viewable by WebDriver We need t
  • 对 Java Servlet 进行单元测试

    我想知道对 servlet 进行单元测试的最佳方法是什么 只要内部方法不引用 servlet 上下文 测试内部方法就不是问题 但是测试 doGet doPost 方法以及引用上下文或使用会话参数的内部方法呢 有没有办法简单地使用经典工具 例
  • 原型组件的 Spring 事件处理

    假设我有两个组件 X 和 Y 其中 X 是单例 而 Y 不是 当我发布XUpdateEvent时 没有问题 我可以捕获该事件 但是 对于 YUpdateEvent 我无法捕获事件 Spring 为每个触发的事件创建新实例 而不是使用已经创建
  • 如何在Netbeans中自定义jTable标题列字体大小?

    我尝试改变jtable标题字体大小Netbeans 但还不能 无论如何 表行字体大小已成功更改 这是我使用的方法 更改后的输出 问题 标题字体大小未更改 但我也想改变这一点 所以请帮助我该怎么做 一种方法是使用UIManager并替换默认的
  • 如何在 TestNG 报告中包含 Log4j2 消息

    我希望在所有测试用例的 TestNG 报告中提供 Log4j2 日志记录信息 TestNG 使用一个名为 Reporter java 的特殊记录器类来跟踪日志输出并将其保存在其结果 XML 中 在 log4j 中 可以简单地创建一个路由到
  • 结果显示图像上有衬里

    我正在使用 opencv 和 android ndk 下面是我的 jni 代码 void Vignete Mat img1 Mat img2 Mat out resize img1 img1 img2 size img1 convertTo
  • 自 Java 7 以来 HttpServer 延迟 1 秒

    我们正在使用内部HttpServer项目中的类 用于通过 HTTP 在客户端和服务器之间交换数据 当我们切换到 Java 7 时 我们意识到结果交付存在延迟 我们可以将问题简化为以下示例 Class EchoServer创建上下文 echo
  • javax.validation 的 @AssertTrue - 它不应该创建错误消息吗?

    我在 Spring MVC 命令 bean 中有以下代码 AssertTrue public boolean isConditionTrue return false private boolean conditionTrue 我的 JSP
  • 使用 Spring 的 SimpleNamingContextBuilder 的应用程序如何知道在其目录中搜索资源?

    使用 Spring 的应用程序如何SimpleNamingContextBuilder http static springsource org spring docs 3 0 x api org springframework mock
  • 有没有办法使用 SauceLabs 的 RemoteWebDriver 禁用 CORS 检查

    问题说明了一切 我正在尝试在 SauceLabs 上执行一些硒测试 该测试加载一个发出跨域请求的网页 我在想是否有一种方法可以通过代码以独立于平台的方式禁用 CORS 使用时Chrome驱动程序 Chrome组合禁用cors questio
  • 如何使用二叉树中的递归来完成回溯

    我正在尝试插入一个二进制节点 我的代码很复杂 没有希望挽救它 所以我计划重写它 基本上我没有考虑回溯 也没有仔细考虑算法 我正在尝试使用顺序遍历插入二进制节点 但我不明白应该如何回溯 D B E A C F 我如何搜索根 D 的左子树 然后
  • RecyclerView:禁用焦点变化引起的滚动

    TL DR我有一个RecyclerView of EditTexts 当用户注意力集中时EditText 1并点击EditText 2 我想EditText 2获得焦点 但我不想要ReyclerView滚动 我怎样才能实现这个目标 我正在尝
  • 如何指示 yum 安装特定版本的 OpenJDK

    我尝试安装openjdk in the redhat服务器 如何安装指定版本 我要安装的版本是 11 0 4 使用以下命令安装的版本是11 0 6 yum install java 11 openjdk devel 曾与 yum showd
  • 来自 Janino 和 Commons-Compiler 的 Spark java.lang.NoSuchMethodError

    我正在构建一个使用 Spark 进行基于随机森林分类的 应用程序 当尝试运行该程序时 我从该行收到异常 StringIndexerModel labelIndexer new StringIndexer setInputCol label
  • Java中精确的时间测量

    Java 提供了两种获取当前时间的方法 System nanoTime and System currentTimeMillis 第一个给出的结果以纳秒为单位 但实际精度比这要差得多 许多微秒 JVM 是否已经为每台特定机器提供了最佳的价值
  • 从存储过程中的动态 SQL 获取结果

    我正在编写一个存储过程 需要在过程中动态构造 SQL 语句以引用传入的表名称 我需要让这个 SQL 语句返回一个结果 然后我可以在整个过程的其余部分中使用该结果 我尝试过使用临时表和所有内容 但我不断收到一条消息 提示我需要声明变量等 例如
  • 获取给定字符串日期中该月的最后一天

    我的输入字符串日期如下 String date 1 13 2012 我得到的月份如下 SimpleDateFormat dateFormat new SimpleDateFormat MM dd yyyy Date convertedDat
  • Java 中的下载管理器 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我需要通过 FTP HTTP 从 Java 获取几个大文件 几个演出 有现成的库 java 命令行工具
  • 在 Oracle 中使用触发器记录对表的更改

    我的一门课有一个项目 当我们的两个表发生更改时 我们需要创建一个日志 插入 更新 删除 我们需要使用Oracle触发器和PL SQL 在日志文件中 我们需要记录用户ID 日期时间 IP地址和事件 插入 更新 删除 我知道如何设置触发器 但我

随机推荐

  • npm start 如何在端口 8000 上运行服务器

    我最近使用 github 上的 Angular Seed 文件夹进行 Angular 应用程序开发 在之前的一些 AngularJS 教程中 Angular Seed 文件夹中有一个脚本文件夹和一个 server js 文件 其中包含运行节
  • 是否可以将 UIView 的顶部固定到导航栏的底部?

    我试图将 UIView 定位在导航栏下方 20pt 但是当我相对于视图控制器上的视图设置它时 它仍然位于导航栏下方 20pt 并且我不想对其进行硬编码 是否可以将其放置在远离导航栏的位置 要以编程方式执行此操作 请使用topLayoutGu
  • Powershell 以块的形式读取文件

    我有一个用 Powershell 编写的脚本 它通过 FTP 传输文件 使用以下命令可以正常工作 content System IO File ReadAllBytes backup app data 但是 一旦文件大小达到 2Gb 此方法
  • 标题正确,但 Chrome 显示“资源解释为文档”

    我读了很多这样的问题 但我真的无法弄清楚 我用archiver https www npmjs com package archiver and express https www npmjs com package expressNode
  • 如果电子邮件/密码输入错误,无法显示错误消息

    如果电子邮件 密码输入错误 我希望出现一个消息框 我正在使用 else 语句 但如果登录不正确 它不会显示消息 MyConn New OleDbConnection MyConn ConnectionString connString My
  • 删除 ThreadPoolExecutor 的所有排队任务

    我有一个相当简单的问题线程池执行器 http java sun com javase 6 docs api java util concurrent ThreadPoolExecutor html 我遇到以下情况 我必须使用队列中的对象 为
  • DynamoDB:键及其含义

    我对如何使用 DynamoDB 表键感到困惑 该文档提到了 HASH 似乎也称为分区 键和 RANGE 或排序 键 我试图将这些与我之前对数据库索引理论的理解大致保持一致 我目前主要基于猜测的理解是 HASH 键本质上是主键 它必须是唯一的
  • Spring 部分更新对象数据绑定

    我们正在尝试在 Spring 3 2 中实现一个特殊的部分更新功能 我们使用 Spring 作为后端 并有一个简单的 Javascript 前端 我无法找到满足我们要求的直接解决方案 即update 函数应该接受任意数量的 field va
  • 我可以在乳胶文档的标题中使用 knitr 内联表达式吗?

    我想使用 Knit Sweave 内联调用 Sexpr 在 LaTeX 文档的标题中 在 begin document 命令之后但在 maketitle 命令之前 内联 R 代码将从我嵌入 LaTeX 的 R 脚本早期创建的 R 数据帧中提
  • sqlite只支持1笔交易?

    在使用 ADO NET 时 也许我错了 我不知道它叫什么 我注意到我只能通过连接开始事务 并且命令似乎有 command Transaction 获取事务数据但不启动事务本身 实际上 在查看时我在 System Data SQLite 中看
  • typeid 运算符的奇怪行为?

    使用 XCode 3 2 3 64 位 我得到以下奇怪的输出 我究竟做错了什么 include
  • Willpopscope 无法在 Web 上拦截浏览器后退按钮

    我尝试过拦截网络上的后退按钮 但它不会被触发 我怎样才能让它发挥作用 WillPopScope onWillPop print will pop on web Get offNamed orders return new Future gt
  • grunt-wiredep 对具有不同依赖关系的多个文件

    目前的项目结构有点像这样 index html bower json bower components 建议的项目结构将在项目根目录中添加更多静态 html 文件 到目前为止 我一直在管理 Bower json 中的所有前端依赖项 并使用
  • 在多个自定义模块支持的多个脚本中使用 python 的 argparse

    我正在构建一组用于管理我们的基础设施的脚本和模块 为了让事情井井有条 我想整合尽可能多的努力 并尽量减少新脚本的样板代码 特别是这里的问题是整合 ArgumentParser 模块 一个示例结构是让脚本和库组织如下 bin script1
  • 如何在 C++ 中调用不同项目的方法?

    使用 Visual Studio 时 我通常使用 C 工作 因此 C 中的某些内容让我感到困惑 概念看起来如此不同 但名称几乎相同 我创建了一个控制台项目 我想在其中运行另一个项目以进行测试 我将该项目添加为控制台应用程序的引用 然后陷入困
  • 如何将图像文件从文档目录上传到iphone中的php服务器

    我目前正在开发画廊类的 iPhone 应用程序 根据我的要求 我需要将所有相机捕获的图像存储到文档目录中 文档文件夹中有一些 10 20 个图像文件 之后我必须使用单个 php url 将应用程序资源文档文件夹推送到服务器上 我已附加屏幕截
  • C# 中的省略号表示法?

    我在哪里可以获得有关实现我自己的带有省略号符号的方法的信息 e g static void my printf char format 这也是所谓的省略符号还是有一个更奇特的名字 看看参数关键字 https learn microsoft
  • 多边形来自折线?

    我正在尝试自动从折线创建多边形 到目前为止 我一直在正确计算折线每个部分的外推边 条件 基线和边之间的距离是常数 如何从基点 红色点 计算边 蓝色点 的角点 这是我在 Qt 中的代码 这对我来说很好用 QPolygonF projectPL
  • 使用 BeautifulSoup 抓取网页中的链接标题和 URL

    我有一个流行文章的网页 我想抓取每个引用网页的超链接及其所显示文章的标题 我的脚本所需的输出是一个 CSV 文件 其中在一行中列出了每个标题和文章内容 因此 如果该网页上有 50 篇文章 我想要一个包含 50 行和 100 个数据点的文件
  • Hibernate - 限制嵌套集合的大小

    我有以下型号 Entity Data public class Book Id GeneratedValue strategy GenerationType IDENTITY private Long id private String a