2013-03-04 3 views
3

HQL noob здесь, действительно борется с этим.Выбор коллекций в HQL

Допустим, у меня есть следующие три класса:

public class A { 
int id; 
B b; 
} 

public class B { 
int id; 
Set<C> c; 
} 

public class C { 
int id; 
String type; 
} 

Таблица B имеет отношения многие ко многим с C, определяемой таблицей b_c. Мне нужен запрос, который выбирает из таблицы A, группы по C.id, фильтрует по C.type = 'wishType' и возвращает объект C и счетчик A.id. Я играл вокруг с чем-то вроде:

SELECT c, COUNT(a.id) as count from A a JOIN a.b.c as c WHERE c.type = 'desiredType' GROUP BY c.id ORDER BY COUNT(a.id) desc 

Я играл с различными итерациями этого запроса, но я получаю различные исключения или мой запрос не вернет ничего. Основная проблема, по-видимому, не в том, чтобы понять, как вернуть отдельные объекты коллекции, соответствующие правильному типу.

Надеюсь, этот вопрос не звучит глупо. Я прочитал руководства по HQL и сотни других вопросов SO, но я должен что-то упустить. Заранее благодарю за любое руководство.

+0

Не прямой ответ на ваш вопрос, но проблема в том, что вам лучше выполнять более строгие правила и вместо того, чтобы использовать «тип» в вашем объекте «C», вы должны добавить подтипы класса, используя тип столбца ваша база данных как дискриминант. Тогда было бы проще запросить только C правильного типа. С другой стороны, я терплю вас от боли, требуя отфильтрованной коллекции спящего режима. – benzonico

ответ

2

Что вы хотите сделать, так не работает. Наконец, вы хотите выбрать из A и B, но только подмножество B.c, которое соответствует вашему состоянию. Это невозможно. Hibernate может загружать полный набор c (не на 100% правильный, вы можете ограничить выбор в своем сопоставлении, но это не решение здесь). Таким образом, существует вероятность, которая, вероятно, не соответствует вашим требованиям. Вы загружаете всех А ограничены, существует положение и сосчитать вручную:

FROM A a where EXISTS (SELECT 1 FROM C, B_C 
          WHERE C.type = 'desiredType' 
          AND B_C.c_id = C.id 
          AND B_C.b_id = a.b.id) 

Тогда вы должны пройти в цикле по всем элементам списков, которые являются экземплярами, проверить во внутреннем цикле по всем а если этот C имеет желаемый тип (все еще нужно сделать, верхний выбор ограничивает выбор только тем, что A имеет хотя бы один C желаемого типа, но в вашем списке у вас есть все C для этих A) и установите счет для права c.id.

Недостатком этого решения является то, что все C загружаются, даже если они имеют неправильный тип, и все подсчеты должны выполняться в Java-коде. Таким образом, вам может не понравиться это решение.

Лучшее решения:

Начните свое мышление с таблицей C. В классе C вы добавляете Set <B> b; (это многие ко многим отношений, возможно, это более удобно, чтобы определить таблицу присоединиться b_c в класс Java). В классе B вы добавляете доступ к таблице A либо добавьте A a (если B: A относится к соотношению 1: 1), либо Set<A> a (если B: A - отношение 1: n). Тогда вы просто выбрать нужный C:

FROM C WHERE C.type = 'desiredType' 

графа А группы по c.id вы просто получить в Java для каждого выбранного с помощью countA = c.b.size() (1: 1 соотношение между А и В) или countA = 0; for (B b : c.b) {countA += b.a.size()} (п: 1 между A и B).

Смежные вопросы