Как построить запрос гибернации, который использует один элемент из всех элементов в коллекции? - PullRequest
2 голосов
/ 12 июня 2009

Вот ситуация:

У меня есть тип данных C, который имеет ссылку «один ко многим» на тип данных P. Тип данных P имеет необязательную ссылку R (один к одному).

Мой запрос был следующим (это был счетчик, но он также будет использоваться для извлечения данных)

FROM C WHERE ... AND P.R.rProperty LIKE 'BLAH%';

Я получаю

org.hibernate.QueryException: illegal attempt to dereference collection 
[C.C_SEQUENCE_NUMBER.P] with element property reference [R] [select count(*) FROM C a WHERE a.DATE_FIELD >= ? AND a.DATE_FIELD <= ? AND a.P.R.rProperty LIKE ?]

Любые советы / предложения?

Ответы [ 4 ]

1 голос
/ 12 августа 2011

Я знаю, что для вас уже поздно, но это может помочь другим. Насколько я знаю, вы не можете сослаться на «субпредложения». В некотором смысле это проявление LOD (Закон Деметры) , что фактически означает, что вы можете использовать только одну точку. Несмотря на то, что это не относится к этой иерархии классов, именно так nhibernate хочет, чтобы вы ссылались на объекты / свойства в hql. Таким образом, вы могли бы написать это так:

from C c 
inner join fetch P p 
inner join fetch R r
where r.rProperty like 'BLAH%';

Выборка предназначена для того, чтобы сообщить hibernate / nhibernate о стремлении загрузить объекты, чтобы избежать проблемы SELECT N + 1. Я думаю, вы хотите предварительно загрузить все объекты в этом случае.

1 голос
/ 12 июня 2009

Попробуйте следующее

"FROM EntityC c inner join EntityP p WHERE p.R.rProperty LIKE 'BLAH%'"
0 голосов
/ 12 июня 2009

Вы можете начать с объекта P, при условии, что у него есть «обратная связь» с содержащим объектом C, так называемое двунаправленное отображение.

Этого можно добиться с помощью HQL, указав выбор или критерии с помощью ResultTransformer.

, например

select p.C from P p where p.r.property like 'BLAH%';

или

s.createCriteria(P.class)
 .createAlias("c","toSelect")
 .createCriteria("r")
 .add(Restrictions.like("property","BLAH%")
 .setResultTransformer(new ResultTransformer() {
      public Object transformTuple(Object[] tuple, String[] aliases) {
        for (int i = 0; i < aliases.length; i++) {
          if ("toSelect").equals(aliases[i])) {
            return tuple[i];
          }
        }
        throw new RuntimeException("What?");
      }
     ...
   })
 .list();
0 голосов
/ 12 июня 2009

Я что-то здесь упускаю или это должно быть

FROM C c WHERE ... AND c.p.r LIKE 'BLAH%';

Хм, давайте перепишем это правильно

Class Foo {
   public List<Bars>getBars();
}

class Bar {
   public Baz getBaz();
}

Где Foo - ваш C, Bar - ваш P, а Baz - ваш R Тогда ваш hql будет выглядеть как

from Foo f where f.bars.baz like 'BLAHH' 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...