API критериев гибернации: фильтрация по подмножеству - PullRequest
4 голосов
/ 05 июня 2011

У меня есть класс, который содержит набор Bs.

Я бы хотел создать Критерии гибернации, чтобы получить все А, для которых набор B является надмножеством некоторого заданного набора.

Для примера:

скажем, у нас есть три объекта типа A

a1, который имеет набор Bs = [b1, b2, b3]
a2, с множеством = [b3, b4, b5]
а3, с множеством = [b3, b5]

Предположим, я хочу получить все А, так что его набор содержит [b3, b5]. Тогда результат будет a2 и a3

Надеюсь, я ясно дал понять. Заранее спасибо!
Manuel

Ответы [ 3 ]

1 голос
/ 06 июня 2011

Я решил это так. Трудно было понять, что это сработало, но это довольно просто, когда ты это увидишь.

        B[] subset = new B[] {b3, b5};
        DetachedCriteria.forClass(A.class).createAlias("bs", "b");

        for (B b : subset) {
            criteria.add(Restrictions.eq("b.id", b.getId()));
        }
0 голосов
/ 06 июня 2011

Прежде чем думать о Критериях, вам нужно сначала нарисовать сырой SQL.

Вы можете сделать это в SQL следующим образом (при условии, что есть таблица AB, объединяющая записи между A и B, где fk_A указывает на id в A и fk_B указывает на id in B):

SELECT fk_A, count(fk_B) FROM AB
   WHERE fk_B IN (b3, b5)
   GROUP BY fk_A 
   HAVING count(fk_B) = 2

Таким образом, вы не получите «неполные» записи из A, поскольку оператор HAVING count(fk_B) фильтрует их. Само собой разумеется, вам придется заменить 2 на соответствующий номер, если сумма B отличается.

Далее идет трудная задача по преобразованию этого в Критерии :) Некоторый псевдо (читай: непроверенный) код:

Criteria criteria = getSession().createCriteria(A.class);
criteria.add(Restrictions.in("fk_B", new String[] {b3, b5}));

ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.count("fk_B"));
projectionList.add(Projections.groupProperty("fk_A"));
criteria.setProjection(projectionList);

Как видите, этот критерий по-прежнему пропускает HAVING бит. К сожалению, HAVING еще не поддерживается в Criteria API. Однако вы должны получить список результатов и count и игнорировать те из них, где count меньше требуемого.

0 голосов
/ 05 июня 2011

Я полагаю, что этот критерий поможет (если предположить, что свойство A, содержащее набор B сущностей, называется bs):

DetachedCriteria.forClass(A.class).add(Restrictions.and(
    Restrictions.in("bs", new B[] { b3, b5 }),
    Restrictions.notIn("bs", DetachedCriteria.forClass(B.class).add(
        Restrictions.notIn("this", new B[] { b3, b5 }))
    )
));

Вероятно, не очень эффективно, однако.

...