Свойство коллекции Hibernate Criteria (подзапрос?)

Я не очень хорошо знаком с критериями гибернации и прошу прощения, если этот вопрос слишком прост... Тем не менее, любая помощь очень ценится!

У меня есть две сущности, CD и Track. Каждый компакт-диск имеет набор объектов Track. В каждой дорожке есть строковое поле с именем «название». Теперь я хочу получить, используя Hibernate Criteria, все компакт-диски с дорожкой с «названием», установленным на определенное значение. Что у меня есть до сих пор это:

//session handling
Criteria cdCriteria = session.createCriteria(CD.class);
DetachedCriteria trackCriteria = DetachedCriteria.forClass(Track.class);
trackCriteria.add(Restrictions.eq("title", "SomeTitle"));
trackCriteria.setProjection(Projections.property("title"));
criteria.add(Subqueries.exists(trackCriteria));
List<CD> cds = criteria.list();

Это возвращает все компакт-диски, независимо от названия трека. У кого-нибудь есть предложения?

Заранее спасибо.


person user1119371    schedule 28.12.2011    source источник


Ответы (2)


Вы очень близки к разгадке. Вы просто пропустили ограничение о том, что трек должен быть треком компакт-диска:

Criteria cdCriteria = session.createCriteria(CD.class, "cd");
DetachedCriteria trackCriteria = DetachedCriteria.forClass(Track.class, "track");
trackCriteria.add(Restrictions.eq("track.title", "SomeTitle"));
trackCriteria.add(Restrictions.propertyEq("track.cd.id", "cd.id"));
trackCriteria.setProjection(Projections.property("track.title"));
criteria.add(Subqueries.exists(trackCriteria));
List<CD> cds = criteria.list();

or

Criteria cdCriteria = session.createCriteria(CD.class, "cd");
DetachedCriteria trackCriteria = DetachedCriteria.forClass(Track.class, "track");
trackCriteria.add(Restrictions.eq("track.title", "SomeTitle"));
trackCriteria.createAlias("track.cd", "trackCd");
trackCriteria.add(Restrictions.propertyEq("trackCd.id", "cd.id"));
trackCriteria.setProjection(Projections.property("track.title"));
criteria.add(Subqueries.exists(trackCriteria));
List<CD> cds = criteria.list();

Вы также можете избежать подзапроса и просто использовать соединение

Criteria cdCriteria = session.createCriteria(CD.class, "cd");
criteria.createAlias("cd.tracks", "track");
criteria.add(Restrictions.eq("track.title", "someTitle"));
criteria.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE);
person JB Nizet    schedule 28.12.2011
comment
Благодарю вас! Мне удалось заставить ваше последнее решение работать с соединением. Два других терпят неудачу с исключением сопоставления, Unknown entity: null Я полагаю, что это из-за track.cd, так как cd не является полем в Track. Отношение направлено только от компакт-диска к дорожке. Или я тут неправильно рассуждаю? - person user1119371; 28.12.2011
comment
Нет, ты прав. Я предположил, что ассоциация была двунаправленной, а трек имел поле cd. - person JB Nizet; 28.12.2011
comment
Значит, нельзя решить с помощью подзапроса? Поскольку ассоциация не является двунаправленной, единственный способ — использовать соединения? - person user1119371; 28.12.2011
comment
Учитывая, что вам нужно получить доступ к дорожкам компакт-диска, я не вижу, как вы могли бы избежать соединения между компакт-диском и дорожкой. - person JB Nizet; 28.12.2011
comment
В этой строке приведенного выше ответа отсутствует двойная кавычка, но StackOverflow не позволяет мне это исправить (по-видимому, минимальная длина редактирования должна составлять 6 символов): критерии.createAlias(cd.tracks, track); - person Jeff Evans; 07.05.2013

Вы можете сделать это на самом деле без соединения - просто используйте cdCriteria.getAlias() вместо строкового значения псевдонима. Таким образом, ключевой строкой будет:

trackCriteria.add(Restrictions.propertyEq("trackCd.id", cdCriteria.getAlias() + ".id"));
person Y G    schedule 17.04.2012
comment
При этом используется внутренний псевдоним спящего режима, а не определенный пользователем. - person Y G; 17.04.2012