2010-06-03 43 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()