【问题标题】:Comparing two collections of enums with Hibernate or SQL使用 Hibernate 或 SQL 比较两个枚举集合
【发布时间】:2011-07-06 15:53:07
【问题描述】:

我有一个实体“父母”,它有一组枚举

private Set<MyEnum> myEnums = EnumSet.noneOf(MyEnum.class);

    @CollectionOfElements(targetElement=MyEnum.class)
    @JoinTable
        (name="PARENT_MY_ENUM",
        joinColumns=@JoinColumn(name="PARENT_ID"))
    @Enumerated(EnumType.STRING)
    @Column (name="MY_ENUM", nullable=false)
    public Set<MyEnum> getMyEnums(){
        return myEnums;
    }


public MyEnum {
ENUM_A,
ENUM_B, 
ENUM_C,
ENUM_D;
}

现在我想用 MyEnums 的集合搜索这个实体。仅应返回所有枚举都设置为搜索集合中的实体。 因此,如果实体 A 具有 ENUM_A、ENUM_B 和 ENUM_C,而实体 B 具有 ENUM_B、ENUM_C、ENUM_D,则使用搜索集合 ENUM_A、ENUM_B、ENUM_C 进行搜索应该只返回实体 A。搜索 ENUM_B 和 ENUM_C 应该什么都不返回。

我将如何在 Hibernate 中做到这一点? 如果我这样做了

select p from Parent p where p.myEnums IN (:searchCollection) and size(p.myEnums) = size(:searchCollection)

那么这将返回两个实体进行第一次搜索。

有什么想法吗?

更新:我进一步了解了如何在 MySQL 中执行此操作,但将其应用于 Hibernate 会生成无效的 SQL。 您可以使用带有 EXISTS 的子查询,例如:

WHERE EXISTS(
    SELECT pa.PARENT_ID, count(pme.MY_ENUM) FROM PARENT pa, PARENT_MY_ENUM pme
    where pa.PARENT_ID = pme.PARENT_ID 
    AND pme.MY_ENUM IN ('ENUM_A','ENUM_B')
    GROUP BY pa.PARENT_ID HAVING count(pme.MY_ENUM) = 2
)

但是当我尝试在 Hibernate 中做同样的事情时:

select pa.ParentId, count(pa.myEnums) from Parent pa 
WHERE pa.myEnums IN ('ENUM_A','ENUM_B')
GROUP BY pa.ParentId HAVING count(pa.myEnums) = 2

Hiberante 创建这个 SQL 语句:

select pa.CONTAINER_RELEASE_REFERENCE_ID as col_0_0_, count(.) as col_1_0_ from PARENT pa, PARENT_MY_ENUM enum1, PARENT_MY_ENUM enum2, PARENT_MY_ENUM enum3 
where pa.PARENT_ID=enum1.PARENT_ID and pa.PARENT_ID=enum2.PARENT_ID and pa.PARENT_ID=enum3.PARENT_ID 
and (. in ('ENUM_A' , 'ENUM_B')) 
group by pa.PARENT_ID having count(.)=2

MySQL 抱怨 '.',这是从哪里来的,为什么 Hibernate 使用 3 个连接到 PARENT_MY_ENUM?

这是一个 Hibernate 错误还是我做错了什么?

【问题讨论】:

    标签: mysql hibernate jpa


    【解决方案1】:

    为你的存在子选择尝试以下方法

    select pa.ParentId, count(en) from Parent pa join pa.myEnums as en
    WHERE en IN ('ENUM_A','ENUM_B')
    GROUP BY pa.ParentId HAVING count(en) = 2
    

    否则,我想知道这样的事情是否无法完成

    select p from Parent p join p.myEnums em
    where (:results) = elements(em)
    

    select p from Parent p join p.myEnums em
    where (:results) in elements(em)
    

    【讨论】:

    • 感谢 Enum 上的额外连接起到了作用。非常感谢
    【解决方案2】:

    我认为你可以在 java 中做到这一点。执行您最初提出的查询,迭代结果并排除 (iterator.remove()) 误报。应该是O(n),我相信MySQL会需要同样的时间来过滤你的结果。

    【讨论】:

    • 问题的顺序可能相同,但是您还需要考虑数据库和应用程序服务器之间传输的数据量(它们可能在也可能不在同一服务器上) .假设只有百分之一的结果集实际上符合标准。因此,可以说为了节省应用服务器和数据库之间的带宽(和时间),您将最大结果设置为 100,您最终只会得到一行。因此,虽然这可能是一种解决方法,但它并不能真正解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 2023-02-03
    • 1970-01-01
    • 2014-12-10
    • 1970-01-01
    相关资源
    最近更新 更多