JPQL 多对多 - in 子句
JPQL many to many - in clause
你能帮我找出以下 JPQL 查询有什么问题吗?它应该按类型过滤书籍。
查询有额外的 OR 条件,为了更好的可读性,我已经删除了这些条件(有或没有其他条件,错误都是一样的)。
@Query("SELECT b FROM Book b WHERE " +
"b in (select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres)")
List<Book> searchBooks(@Param("genres") List<Genre> genres);
以下是堆栈跟踪:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: , near line 1, column 197 [select count(b) FROM *.domain.Book AS b WHERE b.id = (select distinct b1.id FROM *.domain.Book b1 inner join b1.genres genre where genre in :genres_0_, :genres_1_)]
书籍与类型之间的关系 类 是多对多无向关系。
@ManyToMany
@JoinTable(name = "books_genres",
joinColumns = @JoinColumn(name = "BOOK_ID"),
inverseJoinColumns = @JoinColumn(name = "GENRE_ID"))
private List<Genre> genres;
我单独检查了子查询,它有效:
@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres")
List<Book> searchBooksByGenre(@Param("genres") List<Genre> genres);
有没有可能以这种方式使用子查询?
您使用嵌套 select 的查询是可以的,但是当您要在实体集合中搜索时,您必须使用 MEMBER 关键字而不是 IN
。
下面是MEMBER
和IN
的一个很好的解释:. Also have a look at here: http://www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_
但是,即使文档说当您根据作为参数传递的列表进行比较时使用了 IN
关键字,如果您通过实体列表而不是原始值列表。我最近遇到了这个问题,使用 MEMBER
解决了这个问题。我不确定这是休眠错误还是所有其他提供程序的行为方式相同。
在 ObjectDB 的文档中,您可能会读到它以相同的方式处理 IN
和 MEMBER
。在我看来,如果 JPA 提供程序应该有足够的信息来解释查询,即使在两种情况下都使用了 IN
,也没有理由应该有 2 个关键字。
不幸的是,我对 memberOf 有进一步的问题,与数据格式有关,当传递类型列表并检查它们是否存在于书籍类型列表中时,查询将失败并出现数据格式异常。
@Query("SELECT b FROM Book b WHERE " +
":genres MEMBER OF b.genres")
和@Param("genres") List<Genre> genres
会导致以下结果(1 和 4 是传递给查询的流派参数中流派对象的 ID):
Caused by: org.h2.jdbc.JdbcSQLException: Data conversion error converting "(1, 4)"; SQL statement:
我已经放弃了提到的解决方案,并设法使用 "subquery" 作为普通查询来解决问题,然后继续向查询添加条件。
所以最终的解决方案如下:
@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres AND (---additional querys---)")
你能帮我找出以下 JPQL 查询有什么问题吗?它应该按类型过滤书籍。
查询有额外的 OR 条件,为了更好的可读性,我已经删除了这些条件(有或没有其他条件,错误都是一样的)。
@Query("SELECT b FROM Book b WHERE " +
"b in (select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres)")
List<Book> searchBooks(@Param("genres") List<Genre> genres);
以下是堆栈跟踪:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: , near line 1, column 197 [select count(b) FROM *.domain.Book AS b WHERE b.id = (select distinct b1.id FROM *.domain.Book b1 inner join b1.genres genre where genre in :genres_0_, :genres_1_)]
书籍与类型之间的关系 类 是多对多无向关系。
@ManyToMany
@JoinTable(name = "books_genres",
joinColumns = @JoinColumn(name = "BOOK_ID"),
inverseJoinColumns = @JoinColumn(name = "GENRE_ID"))
private List<Genre> genres;
我单独检查了子查询,它有效:
@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres")
List<Book> searchBooksByGenre(@Param("genres") List<Genre> genres);
有没有可能以这种方式使用子查询?
您使用嵌套 select 的查询是可以的,但是当您要在实体集合中搜索时,您必须使用 MEMBER 关键字而不是 IN
。
下面是MEMBER
和IN
的一个很好的解释:. Also have a look at here: http://www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_
但是,即使文档说当您根据作为参数传递的列表进行比较时使用了 IN
关键字,如果您通过实体列表而不是原始值列表。我最近遇到了这个问题,使用 MEMBER
解决了这个问题。我不确定这是休眠错误还是所有其他提供程序的行为方式相同。
在 ObjectDB 的文档中,您可能会读到它以相同的方式处理 IN
和 MEMBER
。在我看来,如果 JPA 提供程序应该有足够的信息来解释查询,即使在两种情况下都使用了 IN
,也没有理由应该有 2 个关键字。
不幸的是,我对 memberOf 有进一步的问题,与数据格式有关,当传递类型列表并检查它们是否存在于书籍类型列表中时,查询将失败并出现数据格式异常。
@Query("SELECT b FROM Book b WHERE " +
":genres MEMBER OF b.genres")
和@Param("genres") List<Genre> genres
会导致以下结果(1 和 4 是传递给查询的流派参数中流派对象的 ID):
Caused by: org.h2.jdbc.JdbcSQLException: Data conversion error converting "(1, 4)"; SQL statement:
我已经放弃了提到的解决方案,并设法使用 "subquery" 作为普通查询来解决问题,然后继续向查询添加条件。
所以最终的解决方案如下:
@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres AND (---additional querys---)")