简体   繁体   English

JPQL 多对多 - in 子句

[英]JPQL many to many - in clause

Can you please help me find out what is wrong with the following JPQL query.您能帮我找出以下 JPQL 查询有什么问题吗? It should filter books by their genres.它应该按类型过滤书籍。

Query has additional OR conditions which I have removed due to better readability (with or without the other conditions the error is the same).查询有额外的 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);

Following is the stacktrace:以下是堆栈跟踪:

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_)]

Relation between Book and Genre classes is ManyToMany undirectional. Book 和 Genre 类之间的关系是多对多无方向的。

    @ManyToMany
    @JoinTable(name = "books_genres",
                 joinColumns = @JoinColumn(name = "BOOK_ID"),
                 inverseJoinColumns = @JoinColumn(name = "GENRE_ID"))
    private List<Genre> genres;

I have checked the subquery separately and it works:我已经单独检查了子查询并且它有效:

@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres")
    List<Book> searchBooksByGenre(@Param("genres") List<Genre> genres);

Is it possible at all to use the subquery in this way?是否有可能以这种方式使用子查询?

Your query with nested select is OK, but you must use MEMBER keyword instead of IN when you want to search in collection of entities.您使用嵌套选择的查询是可以的,但是当您要在实体集合中进行搜索时,您必须使用MEMBER关键字而不是IN

Here is a good explanation of MEMBER and IN : https://stackoverflow.com/a/9820394/784594 .这是MEMBERIN一个很好的解释: https : //stackoverflow.com/a/9820394/784594 Also have a look at here: http://www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_也看看这里: http : //www.objectdb.com/java/jpa/query/jpql/collection#NOT_MEMBER_OF_

However , even if the documentation says that IN keyword is used when you compare according a list passed as a parameter, hibernate seems to behave oddly if you pass list of entities instead of list of primitive values.但是,即使文档说IN根据作为参数传递的列表进行比较时使用了IN关键字,如果传递实体列表而不是原始值列表,hibernate 的行为似乎也很奇怪。 I came accross this recently and using MEMBER fixed the problem .我最近遇到了这个问题,使用MEMBER解决了这个问题 I am not sure if this is a hibernate bug or whether all other providers behave the same way.我不确定这是一个休眠错误还是所有其他提供程序的行为方式相同。

In the documentation to ObjectDB, you may read that it treats IN and MEMBER in the same way.在 ObjectDB 的文档中,您可能会读到它以相同的方式对待INMEMBER In my opinion, there is no reason why there should be 2 keywords if JPA provider should have enough information to interpret the query even if IN was used in both cases.在我看来,如果 JPA 提供者应该有足够的信息来解释查询,即使在这两种情况下都使用了IN ,也没有理由应该有 2 个关键字。

Unfortunately I had further issues with memberOf, pertaining to data format, when passing a list of genres and check if they exist in book genre list, query would fail with a data format exception.不幸的是,我对 memberOf 有进一步的问题,与数据格式有关,当传递流派列表并检查它们是否存在于书籍流派列表中时,查询将因数据格式异常而失败。

@Query("SELECT b FROM Book b WHERE " +
        ":genres MEMBER OF b.genres")

with @Param("genres") List<Genre> genres with @Param("genres") List<Genre> genres

would cause the following (1 and 4 are ids of the Genre objects in genres parameter passed to the query):将导致以下情况(1 和 4 是传递给查询的流派参数中流派对象的 ID):

Caused by: org.h2.jdbc.JdbcSQLException: Data conversion error converting "(1, 4)"; SQL statement:

I have abandoned the mentioned solution and managed to solve the issue using the "subquery" as a normal query and then continued adding conditions to the query.我已经放弃了上述解决方案,并设法使用“子查询”作为普通查询来解决该问题,然后继续向查询添加条件。

So final solution is the following:所以最终的解决方案如下:

@Query("select distinct b1 FROM Book b1 inner join b1.genres genre where genre in :genres AND (---additional querys---)")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM