【发布时间】:2020-08-25 21:41:00
【问题描述】:
我有以下型号:
@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;
}
我正在努力实现的是获取所有带有分页的书籍,但所有书籍都应该将其 cmets 收藏限制为 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(*))。这样我没有语法错误,但它返回不正确的结果集 - book 被重复 N 次,其中 N 是 cmets 集合的大小。
我该如何解决?这个案子有没有更好的办法?
编辑:
计数查询:
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=?
【问题讨论】:
-
可以提供count查询吗?
-
@Erwin 当然,我刚刚更新了问题
-
也许你应该通过设置 hibernate.show_sql=true 来检查 hibernate 运行的查询并检查日志
-
@Erwin 我把它打开了。我再次更新了问题并提供了获取查询,该查询针对页面上的每本书执行(20 次)。那是错误的,因为我已经在本机查询中获取了 cmets。如何防止这种行为或用我自己的替换获取查询?
-
什么是 Page/Pageable 类?是hibernate的吗?
标签: java sql spring hibernate spring-data