2010-06-03 44 views
1

嗨我使用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映射文件都有一组枚举值作为休眠文件中规定: 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)中的一组枚举值?

干杯 西蒙

回答

1

好像你逝去的不兼容类型的参数。例如,它期望很长,但你传递int。设置你的日志级别来跟踪,看看hibernate期待什么,这样你就可以决定传递一个数组或者其他东西。

1

我看着几个不同的页,包括以下内容:

包括这一个看起来像使用休眠3.5或JPA 2.0(有标注)人优雅的溶液:

Hibernate Criteria API - adding a criterion: string should be in collection

这个最终指出我的解决方案: 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 />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; 
} 

希望这会有所帮助,如果任何人发现的休眠(3.2)的版本,更好的解决方案,请张贴它帮助社区

干杯 西蒙

0

我知道这是一个老问题,但我刚刚遇到silimar问题,并发现解决方案。

你必须加入mainCategories和使用查询它0属性。就像那样:

session.createCriteria(FollowUp.class) 
    .createAlias("mainCategories", "mainCategories") 
    .add(Restrictions.eq("mainCategories.elements", Category.ITEM)) 
    .list()