Запрос Hibernate на примере и проекциях - PullRequest
21 голосов
/ 17 сентября 2008

Короче говоря: hibernate не поддерживает проекции и запросы на примере? Я нашел этот пост:

Код такой:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr))

Как сказал другой автор, сгенерированный sql продолжает иметь класс where, ссылающийся на y0_ =? вместо этого_город .

Я уже попробовал несколько подходов и искал трекер, но ничего не нашел по этому поводу.

Я даже пытался использовать псевдоним Projection и Transformers, но он не работает:

User usr = new User();
usr.setCity = 'TEST';
getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Example.create(usr)).setResultTransformer(Transformers.aliasToBean(User.class));

Кто-нибудь использовал проекции и запросы на примере?

Ответы [ 6 ]

44 голосов
/ 06 июня 2009

Проблема возникает, когда у вас есть псевдоним с тем же именем, что и у объекта objects. Hibernate, кажется, подобрать псевдоним и использовать его в SQL. Я нашел это задокументированное здесь и здесь , и я считаю, что это ошибка в Hibernate, хотя я не уверен, что команда Hibernate соглашается.

В любом случае, я нашел простую работу, которая работает в моем случае. Ваш пробег может варьироваться. Подробности приведены ниже, я попытался упростить код для этого примера, поэтому я прошу прощения за любые ошибки или опечатки:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("sectionHeader", sectionHeaderVar)) // <- Problem!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

Будет производить этот sql:

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(y1_) like ? ) 

Что вызвало ошибку: java.sql.SQLException: ORA-00904: "Y1_": неверный идентификатор

Но, когда я изменил свое ограничение на использование «this», вот так:

Criteria criteria = session.createCriteria(MyClass.class)
    .setProjection(Projections.projectionList()
        .add(Projections.property("sectionHeader"), "sectionHeader")
        .add(Projections.property("subSectionHeader"), "subSectionHeader")
        .add(Projections.property("sectionNumber"), "sectionNumber"))
    .add(Restrictions.ilike("this.sectionHeader", sectionHeaderVar)) // <- Problem Solved!
    .setResultTransformer(Transformers.aliasToBean(MyDTO.class));

Это произвело следующий sql, и моя проблема была решена.

select
    this_.SECTION_HEADER as y1_,
    this_.SUB_SECTION_HEADER as y2_,
    this_.SECTION_NUMBER as y3_,
from
    MY_TABLE this_ 
where
    ( lower(this_.SECTION_HEADER) like ? ) 

Вот так! Довольно простое решение проблемы. Я не знаю, как это исправление перешло бы к запросу на примере проблемы, но оно может приблизить вас.

16 голосов
/ 17 сентября 2008

Могу ли я увидеть ваш класс пользователя? Это просто использование ограничений ниже. Я не понимаю, почему ограничения действительно отличаются от примеров (хотя я думаю, что в примерах пустые поля по умолчанию игнорируются)

getCurrentSession().createCriteria(User.class)
.setProjection( Projections.distinct( Projections.projectionList()
.add( Projections.property("name"), "name")
.add( Projections.property("city"), "city")))
.add( Restrictions.eq("city", "TEST")))
.setResultTransformer(Transformers.aliasToBean(User.class))
.list();

Я никогда не использовал alaistToBean, но я просто читал об этом. Вы также можете просто просмотреть результаты ..

List<Object> rows = criteria.list();
for(Object r: rows){
  Object[] row = (Object[]) r;
  Type t = ((<Type>) row[0]);
}

Если вам нужно, вы можете вручную заполнить пользователя таким образом.

Трудно разобраться в проблеме без дополнительной информации для диагностики проблемы.

6 голосов
/ 15 сентября 2010

Настоящая проблема здесь заключается в том, что в hibernate есть ошибка, когда в предложении where используются псевдонимы списка выбора:

http://opensource.atlassian.com/projects/hibernate/browse/HHH-817

На всякий случай, если кто-то приземлится в поисках ответов, посмотрите на билет. Исправление заняло 5 лет, но теоретически это будет в одном из следующих выпусков, и тогда я подозреваю, что ваша проблема исчезнет.

0 голосов
/ 13 февраля 2016
ProjectionList pl = Projections.projectionList();
pl.add(Projections.property("id"));
pl.add(Projections.sqlProjection("abs(`pageNo`-" + pageNo + ") as diff", new String[] {"diff"}, types ), diff); ---- solution
crit.addOrder(Order.asc("diff"));
crit.setProjection(pl);
0 голосов
/ 11 июля 2011

Я на самом деле не думаю, что я могу найти слово "это". заставляет hibernate не включать какие-либо ограничения в свой запрос, что означает, что он получил все списки записей. Что касается сообщения об ошибке гибернации, о котором сообщалось, я вижу, что оно исправлено, но мне не удалось загрузить исправление.

0 голосов
/ 10 июня 2009

У меня похожая проблема. Я использую Query by Example и хочу отсортировать результаты по настраиваемому полю. В SQL я бы сделал что-то вроде:

select pageNo, abs(pageNo - 434) as diff
from relA
where year = 2009
order by diff

Работает нормально без упорядочения. Что я получил, это

Criteria crit = getSession().createCriteria(Entity.class);
crit.add(exampleObject);
ProjectionList pl = Projections.projectionList();
pl.add( Projections.property("id") );
pl.add(Projections.sqlProjection("abs(`pageNo`-"+pageNo+") as diff", new String[] {"diff"}, types ));
crit.setProjection(pl);

Но когда я добавлю

crit.addOrder(Order.asc("diff"));

Я получаю org.hibernate.QueryException: не удалось разрешить свойство: diff исключение. Обходной путь с этот тоже не работает.

PS: поскольку я не смог найти какой-либо сложной документации по использованию QBE для Hibernate, все вышеперечисленное - в основном метод проб и ошибок

...