在 JPA NamedQuery 中使用 HashSet 作为参数会引发 IllegalArgumentException

Posted

技术标签:

【中文标题】在 JPA NamedQuery 中使用 HashSet 作为参数会引发 IllegalArgumentException【英文标题】:Using HashSet as argument in JPA NamedQuery throws IllegalArgumentException 【发布时间】:2020-04-22 18:48:42 【问题描述】:

我已经这样设置了 NamedQuery:

@Entity
@Table(name = "channel")
@NamedQuery(name = "Channel.getPrivateChannel", query = "SELECT pvt from Channel pvt WHERE pvt.state = 3 AND pvt.channelOwnerWorkspace = :channelOwnerWorkspace AND pvt.channelSubscribers = :channelSubscribers")
public class Channel implements Serializable 

...

@Column(nullable = false)
    private int type;

@ManyToOne
    @JoinColumn(name = "workspaceId")
    private Workspace channelOwnerWorkspace;

@ManyToMany(mappedBy = "subscribedChannels", fetch = FetchType.EAGER)
    private Set<User> channelSubscribers;

所有变量都非空且存在;并且,当调用上述查询时,我得到一个像这样的 IllegalArgumentException:

Parameter value [pt.project.entity.User@4125ce40] did not match expected type [java.util.Set (n/a)]

这里抛出异常:

public Channel findPrivateChannel1(String workspace, Set<User> channelSubscribers) 


///

        Workspace selectedWorkspace = workspaceDAO.findByTitle(workspace);

        try 
            Channel pvtChannel = em.createNamedQuery("Channel.getPrivateChannel", Channel.class)
                    .setParameter("channelOwnerWorkspace", selectedWorkspace)
                    .setParameter("channelSubscribers", channelSubscribers).getSingleResult();

我做错了什么?甚至可以将 HashSet 设置为参数吗?

提前致谢。

【问题讨论】:

调用这个 namedQuery 时你传递了什么?如果您可以共享调用此命名查询并获得上述异常的代码。 当然。这里抛出异常:public Channel findPrivateChannel1(String workspace, Set&lt;User&gt; channelSubscribers) /// try Channel pvtChannel = em.createNamedQuery("Channel.getPrivateChannel", Channel.class) .setParameter("channelOwnerWorkspace", selectedWorkspace) .setParameter("channelSubscribers", channelSubscribers).getSingleResult(); return pvtChannel; catch (NoResultException e) return null; catch (Exception e) return null; 导致第二个异常。 【参考方案1】:

根据JSR-338,第 4.6.7 项,等于比较运算符不能用于整个集合:

顺便说一句,目前尚不清楚您使用两个完整列表进行比较的目标是什么。更具体地说,您可以使用一些非常有用的集合表达式来选择您的实体,例如 IN、MEMBER OF 或 IS EMPTY,甚至是一些子选择(ANY、SOME 或 ALL)。

【讨论】:

查询应该是:"@NamedQuery(name = "Channel.getPrivateChannel", query = "SELECT pvt from Channel pvt WHERE pvt.state = 3 AND pvt.channelOwnerWorkspace = :channelOwnerWorkspace AND pvt.channelSubscribers IN :channelSubscribers")";,但关键是要找到一个频道,其中只有并且只有所述 Set 上的用户。我的问题是 NamedQuery 不使用整个 Set,只使用一个 User。

以上是关于在 JPA NamedQuery 中使用 HashSet 作为参数会引发 IllegalArgumentException的主要内容,如果未能解决你的问题,请参考以下文章

在 JPA NamedQuery 中使用 HashSet 作为参数会引发 IllegalArgumentException

JPA 计数 NamedQuery

EclipseLink JPA NamedQuery 在 Set 类型的字段中找不到 .size 属性

从 JPA 实体的接口中检索 @NamedQuery

JPA:如何将@NamedStoredProcedureQuery 与@NamedQuery 结合起来执行周边搜索?

在@NamedQuery (JPA QL 1.0) 中设置为空的参数