фильтрация критериев гибернации по набору значений перечислений - PullRequest
1 голос
/ 03 июня 2010

Привет! Я использую Hibernate 3.2 с 1.6 JDK и Mysql 5.0. Я пытаюсь использовать критерии API для создания динамического фильтра. Однако, когда я добавляю ограничение на набор перечислений, которое является свойством моего объекта Criteria, я получаю исключение org.hibernate.exception.GenericJDBCException.

мой код такой:

public class FollowUp {
    ...
    public Set<AdminCategory> getAdminCategories() {...}
    public void setAdminCategories(Set<AdminCategory> _arg) { ... }

}

Мой файл отображения hibernate имеет набор значений Enum, как указано в документации по hibernate: http://docs.jboss.org/hibernate/stable/core/reference/en/html/collections.html#collections-ofvalues. Файл (FollowUp.hbm.xml ) это так

<hibernate-mapping>
    <typedef class="dao.util.HibernateAdminCategoryType" name="main-category" />
    <class name="FollowUp" table="follow_up">
    <!-- other properties here -->
    <set name="mainCategories" table="follow_up_main_categories" fetch="join" lazy="false">
             <key column="fup_id"/>
             <element column="identifier" type="main-category"/>
     </set>
     <!-- other stuff -->
     </class>
</hibernate-mapping>

Код фильтра критериев выглядит следующим образом:

public void runFilter(FollowUpFilter _filter) {
    Criteria criteria = this.getSession().createCriteria(FollowUp.class);
    if (_filter.hasMainCategories()) {
        criteria.add(Restrictions.in("mainCategories", _filter.getMainCategories()));    
    }
    criteria.setResultTransformer( Criteria.DISTINCT_ROOT_ENTITY );

    criteria.setProjection(Projections.rowCount());
    Integer count = (Integer) criteria.uniqueResult();
    _filter.setTotalSize(count);
}

Когда я запускаю свои тесты (с выводом sql), я получаю следующую ошибку:

Statement parameter 1 not set.
org.hibernate.exception.GenericJDBCException: could not execute query

вывод sql выглядит следующим образом:

select
    count(*) as y0_ 
from
    follow_up this_ 
where
    this_.id in (
        ?
    ) 

Кто-нибудь знает правильный способ фильтрации набора значений перечисления в критериях (в Hibernate 3.2)?

Приветствие Simon

Ответы [ 3 ]

1 голос
/ 20 декабря 2010

Я просмотрел несколько разных страниц, включая следующие:

Включая это, которое выглядит как элегантное решение для людей, использующих hibernate 3.5 или JPA 2.0 (с аннотациями):

API Hibernate Criteria - добавление критерия: строка должна быть в коллекции

Этот в конечном итоге указал мне на решение: https://forum.hibernate.org/viewtopic.php?f=1&t=942839&start=0

В конце концов, я выполнил ручной выбор, я не доволен им, но он работает. Я не могу поверить, что это предпочтительное решение, но я не мог найти другое. Это настолько уродливо, насколько может быть решение, и все же оправдывает название: - (

public void runFilter(AdminNoteFilter _filter) {
   assert _filter != null;
   Criteria criteria = this.getSession().createCriteria(FollowUp.class);
   if (_filter.hasMainCategories()) {
      CriteriaQueryTranslator cqt = null;

      Criterion mainCategoriesCriterion = HibernateFilterUtil.getEnumIdentifierCriterion(_filter.getMainCategories(),
         "{alias}.id in " +
         "(select fup.id " +
         "from follow_up fup, follow_up_main_categories v " +
         "where fup.id = v.fup_id and v.identifier in (" + HibernateFilterUtil.SUBSTITUE_QUESTION_MARKS + "))");
      criteria.add(mainCategoriesCriterion);

   }


   List<FollowUp> adminNotes = (List<FollowUp>) criteria.list();
}

/**
 * constructs a criterion for filtering on a collection of enums using a subselect.
 * <br />/2009834/filtratsiya-kriteriev-gibernatsii-po-naboru-znachenii-perechislenii
 * <br />https://forum.hibernate.org/viewtopic.php?f=1&t=942839&start=0
 *
 * @param _enums     non null non empty
 * @param _subSelect non null must contain the {@link #SUBSTITUE_QUESTION_MARKS} string to be substituted
 * @return the Criterion that can be added to a Criteria
 */
private static Criterion getEnumIdentifierCriterion(Set<? extends MarshallableEnum> _enums, String _subSelect) {
   assert _enums != null;
   assert _enums.size() > 0;
   assert _subSelect != null;
   assert _subSelect.contains(SUBSTITUE_QUESTION_MARKS);

   Set<String> identifiersSet = MarshallableEnumUtil.getIdentifiersFromMarshallableEnums(_enums);
   String[] identifiers = identifiersSet.toArray(Constants.EMPTY_STRING_ARRAY);

   // taken from
   //https://forum.hibernate.org/viewtopic.php?f=1&t=942839&start=0
   final org.hibernate.type.Type[] types = new org.hibernate.type.Type[identifiers.length];
   Arrays.fill(types, org.hibernate.Hibernate.STRING);

   final StringBuilder questionMarks = new StringBuilder();
   for (int i = 0; i < identifiers.length; i++) {
      if (i > 0) {
         questionMarks.append(",");
      }
      questionMarks.append("?");
   }
   // substitute in the question marks to the sub select subselect
   String finalSubSelect = _subSelect.replace(SUBSTITUE_QUESTION_MARKS, questionMarks);

   return Restrictions.sqlRestriction(finalSubSelect, identifiers, types);
}

private static Set<String> getIdentifiersFromMarshallableEnums(Set<? extends MarshallableEnum> _enums) {
   Set<String> retSet = new HashSet<String>();
   for (MarshallableEnum tmpEnum : _enums) {
      retSet.add(tmpEnum.getIdentifier());
   }
   return retSet;
}

Надеюсь, это поможет, если кто-нибудь найдет лучшее решение для версии hibernate (3.2), пожалуйста, опубликуйте его, чтобы помочь сообществу

Приветствие Simon

1 голос
/ 19 декабря 2010

Похоже, вы передаете параметр несовместимого типа. Например, он ожидает долго, но вы передаете int. Установите уровень журнала для трассировки и посмотрите, что ожидает hibernate, чтобы вы могли принять решение о передаче массива, набора или чего-то еще.

0 голосов
/ 01 июля 2016

Я знаю, что это старый вопрос, но я только что столкнулся с проблемой силимара и нашел решение.

Вы должны присоединиться к mainCategories и запросить его, используя свойство elements. Просто так:

session.createCriteria(FollowUp.class)
    .createAlias("mainCategories", "mainCategories")
    .add(Restrictions.eq("mainCategories.elements", Category.ITEM))
    .list() 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...