JPQL查询-实体包含一个Longs列表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPQL查询-实体包含一个Longs列表相关的知识,希望对你有一定的参考价值。

在我的Spring MVC应用程序(Hibernate版本:4.1.7.final)中,我有一个包含多头列表的实体,例如以下代码:

@Entity
@Table(name = "foo")
public class Foo 
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable(
            name = "foo_numbers",
            joinColumns = @JoinColumn(
                    name = "foo_id",
                    referencedColumnName = "id"))
    private Collection<Long> numbers;

    ...

目标是为列表为空或包含给定数字的Foos编写查询,例如:

@Query("SELECT f FROM Foo AS f WHERE f.numbers IS EMPTY OR (:num) MEMBER OF f.numbers")
Collection<Foo> findTheRightFoos(@Param("num") Long num);

但是我遇到了以下问题:

@Query("SELECT f FROM Foo AS f WHERE (:num) MEMBER OF f.numbers")
Collection<Foo> findFoos_1(@Param("num") Long num);
//org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your mysql server version for the right syntax to use near '))' at line 1; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '))' at line 1
//Hibernate log: select fooba0_.id as id9_ from foo fooba0_ cross join foo_numbers numbers1_ where fooba0_.id=numbers1_.foo and (? in (.))

@Query("SELECT f FROM Foo AS f WHERE (:num) IN f.numbers")
Collection<Foo> findFoos_2(@Param("num") Long num);
//Can't start the app, got the following exception:
//antlr.NoViableAltException: unexpected end of subtree ...
//... Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of subtree [SELECT c FROM com.acme.Foo AS f WHERE (:num) IN f.numbers]

@Query("SELECT f FROM Foo AS f WHERE f.numbers = (:num)")
Collection<Foo> findFoos_3(@Param("num") Long num);
//org.springframework.dao.InvalidDataAccessApiUsageException: Parameter value [3870] did not match expected type [java.util.Collection]; nested exception is java.lang.IllegalArgumentException: Parameter value [3870] did not match expected type [java.util.Collection]

@Query("SELECT f FROM Foo AS f WHERE f.numbers IS EMPTY")
Collection<Foo> findFoos_4();
//Can't start the app, got the following exception:
//antlr.NoViableAltException: unexpected end of subtree ...
//... Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected end of subtree [SELECT c FROM com.acme.Foo AS f WHERE f.numbers IS EMPTY]

@Query("SELECT f FROM Foo AS f WHERE f.numbers IS NULL")
Collection<Foo> findFoos_5();
//org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'is null)' at line 1; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'is null)' at line 1
//Hibernate log: select fooba0_.id as id9_ from foo fooba0_ cross join foo_numbers numbers1_ where fooba0_.id=numbers1_.foo and (. is null)

@Query("SELECT f FROM Foo AS f WHERE f.numbers = NULL")
Collection<Foo> findFoos_6();
//org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'is null)' at line 1; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'is null)' at line 1
//Hibernate log same as 'findFoos_5': select fooba0_.id as id9_ from foo fooba0_ cross join foo_numbers numbers1_ where fooba0_.id=numbers1_.foo and (. is null)

这怎么了?我该怎么办?

答案

要实现所需的查询(针对@ElementCollection的内容),您需要更改为@OneToMany关联。这是我的支持(来自JPA: When to choose Multivalued Association vs. Element Collection Mapping

使用@ElementCollection而不是@OneToMany的局限性在于,不能独立于其父对象来查询,持久化和合并目标对象。它们是严格私有的(从属)对象,与@Embedded映射相同。 @ElementCollection上没有级联选项,目标对象始终与其父对象保持,合并或删除。 @ElementCollection仍然可以使用访存类型,并且默认为LAZY,与其他集合映射相同。

另一答案

正如guido所说,这是由于以下错误:https://hibernate.atlassian.net/browse/HHH-6686

我已经尝试过了,现在肯定可以在5.4.11版中使用了

以上是关于JPQL查询-实体包含一个Longs列表的主要内容,如果未能解决你的问题,请参考以下文章

JPQL 查询列表中的参数

如何在jpql中选择列表元素的属性

JPQL 根据孙属性选择实体

使用 JPQL 或条件 API 在省略某些字段的同时恢复具有相关实体的实体列表

使用 JPQL 通过连接表进行查询时出错

减少对包含实体的 JPQL POJO 的查询次数