Сравнение двух коллекций перечислений с Hibernate или SQL - PullRequest
5 голосов
/ 06 июля 2011

У меня есть сущность 'Parent', у которой есть набор перечислений

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 или что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 17 июля 2011

Дайте следующую попытку для вас, существует подпункт

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)
0 голосов
/ 13 июля 2011

Я думаю, вы можете сделать это в Java. Выполните ваш изначально предложенный запрос, итерируйте результат и исключите (iterator.remove()) ложные срабатывания. Это должно быть O(n), и я считаю, что MySQL потребует того же времени для фильтрации вашего результата.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...