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

下面是MEMBERIN的一个很好的解释:. Also have a look at here: http://www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_

但是,即使文档说当您根据作为参数传递的列表进行比较时使用了 IN 关键字,如果您通过实体列表而不是原始值列表。我最近遇到了这个问题,使用 MEMBER 解决了这个问题。我不确定这是休眠错误还是所有其他提供程序的行为方式相同。

在 ObjectDB 的文档中,您可能会读到它以相同的方式处理 INMEMBER。在我看来,如果 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---)")