【问题标题】:IN clause on collection with Hibernate使用 Hibernate 收集的 IN 子句
【发布时间】:2015-04-19 08:07:59
【问题描述】:

我有两个实体:AcknowledgementIndustry。前者与后者具有多对多关联,反之亦然。

@Entity
public class Acknowledgement {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int id;

    @ManyToMany
    @JoinTable(name = "acknowledgement_industry", joinColumns = @JoinColumn(name = "acknowledgement_id"), inverseJoinColumns = @JoinColumn(name = "industry_id"))
    private Set<Industry> industries = new HashSet<>();
}

@Entity
public class Industry {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private int id;

    @ManyToMany(mappedBy = "industries")
    private Set<Acknowledgement> acknowledgements = new HashSet<>();
}

我正在尝试创建一个 JPQL/HQL 查询,该查询根据一组 ID 查找确认,这些 ID 还与一组行业 ID 相关联 - 并使用聚合函数 count。所以我想知道有多少确认满足这些标准。以下是我尝试过的一些方法:

long result = (long) this.getEntityManager()
            .createQuery(jpql)
            .setParameter("acknowledgements", new HashSet<>(acknowledgementIds))
            .setParameter("industries", new HashSet<>(industryIds))
            .getSingleResult();

参数是整数集。我也尝试过使用实体对象。对于jpql 字符串,我尝试了以下查询(以及一些变体)。

查询 #1

select count(a) from Acknowledgement a where a.id in :acknowledgements and a.industries in :industries

结果

org.postgresql.util.PSQLException: No value specified for parameter 2.

查询 #2

select count(a) from Acknowledgement a where a.id in :acknowledgements and a.industries.id in :industries

结果

org.hibernate.QueryException: illegal attempt to dereference collection [acknowledg0_.id.industries] with element property reference [id]

这种方法适用于其他一些关联类型,但显然不适用于集合。

问题在于industries 关联的IN 子句。我可以编写本机查询,但我想避免这种情况。如何找到 A 类型的实体,这些实体具有关联的 B 类型的对象,其 ID 在给定集中?

我希望我说清楚了。谢谢。

【问题讨论】:

    标签: hibernate jpa orm hql


    【解决方案1】:

    尝试下一个查询:

    SELECT COUNT( DISTINCT a) FROM Acknowledgement a INNER JOIN a.industries AS ind where a.id in :acknowledgements and ind.id IN :industries
    

    您也可以使用MEMBER OF 代替IN 表达式:WHERE :industry1 MEMBER OF a.industries OR :industry2 MEMBER OF a.industries OR ...

    【讨论】:

    • 您是否知道一种更动态的方法,这样我就不必根据我的集合中有多少行业来操纵我的查询?我会调查MEMBER OF - 谢谢。
    • 我没有听说过更动态的方式。动态方式的问题在于不清楚是否应该使用 ORAND 运算符,即 1.WHERE :industry1 MEMBER OF a.industries OR :industry2 MEMBER OF a.industries 与 2.WHERE :industry1 MEMBER OF a.industries AND :industry2 MEMBER OF a.industries
    • 我在您的查询中更改了一些内容,并且似乎找到了可行的解决方案。请看我的回答。我接受这个答案是因为你指出了我正确的方向。感谢您的帮助。
    【解决方案2】:

    受安德烈回答的启发,我想出了以下似乎可行的查询。我之前尝试过,但我缺少的是 COUNT 函数中的 DISTINCT 关键字。与接受的答案相比,我还将连接更改为INNER JOIN,并在i.id 上使用了IN 子句,而不仅仅是别名i

    SELECT COUNT(DISTINCT a) FROM Acknowledgement a INNER JOIN a.industries i WHERE a.id IN :acknowledgements AND i.id IN :industries
    

    【讨论】:

    • 与问题有关,应该使用具有 id 属性的路径而不是实体的路径:这实际上取决于您的参数是什么。根据我的经验:如果你有一个Longs 的列表作为参数,那么你必须使用 id 的路径,否则你可以同时使用。
    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 2019-04-01
    • 1970-01-01
    • 2014-09-10
    • 2021-05-15
    相关资源
    最近更新 更多