对一组枚举值进行休眠条件过滤 [英] hibernate criteria filtering on a set of enum values

查看:50
本文介绍了对一组枚举值进行休眠条件过滤的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将Hibernate 3.2与1.6 JDK和Mysql 5.0一起使用,我正在尝试使用条件api来组合动态过滤器.但是,当我对作为我的Criteria对象的属性的枚举集添加限制时,我得到了org.hibernate.exception.GenericJDBCException.

Hi I'm using Hibernate 3.2 with a 1.6 JDK and Mysql 5.0 I'm trying to use the criteria api to put together a dynamic filter. However when I add a Restriction on a Set of Enums that is a property of my Criteria object I get a org.hibernate.exception.GenericJDBCException.

我的代码是这样的:

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

}

我的休眠映射文件具有一组在休眠文档中指定的Enum值: http://docs.jboss.org/hibernate/stable/core/reference/zh-CN/html/collections.html#collections-ofvalues .文件(FollowUp.hbm.xml)就是这样

My hibernate mapping file has a set of Enum values as specified in the hibernate documentation: http://docs.jboss.org/hibernate/stable/core/reference/en/html/collections.html#collections-ofvalues. The file (FollowUp.hbm.xml ) is like this

<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输出)时,出现以下错误:

When I run my tests (with sql output) I get the following error:

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 (
        ?
    ) 

有人知道在Criteria中(在Hibernate 3.2中)对一组枚举值进行过滤的正确方法吗?

Does anyone know the correct way to filter on a set of enum values in a Criteria (in Hibernate 3.2)?

欢呼西蒙

推荐答案

我查看了一些不同的页面,包括以下内容:

I looked at a few different pages including the following:

包括这一对于使用hibernate 3.5或JPA 2.0(带有批注)的人们来说似乎是一种优雅的解决方案:

Including this one which looks like an elegant solution for folks using hibernate 3.5 or JPA 2.0 (with annotations):

Hibernate Criteria API-添加条件:字符串应在集合中

这个人最终为我指出了一个解决方案: https://forum.hibernate.org/viewtopic.php?f = 1& t = 942839& start = 0

This one eventually pointed me to a solution: https://forum.hibernate.org/viewtopic.php?f=1&t=942839&start=0

最后,我做了一个手动的子选择,我对此并不满意,但是它可以工作.我无法相信这是首选的解决方案,但我找不到其他解决方案.解决方案可能很丑陋,但仍要保证名称:-(

In the end I did a manual subselect, I'm not happy with it but it works. I can't believe that this is the preferred solution but I couldn't find any other. It's about as ugly as a solution can be and still warrant the name :-(

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 />https://stackoverflow.com/questions/2967199/hibernate-criteria-filtering-on-a-set-of-enum-values
 * <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)版本的更好的解决方案,请发布该版本以帮助社区

Hope this helps, if you anyone finds a better solution for the version of hibernate (3.2) please post it to help the community

欢呼西蒙

这篇关于对一组枚举值进行休眠条件过滤的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆