2010-06-03 7 views
1

Salut J'utilise Hibernate 3.2 avec un 1.6 JDK et Mysql 5.0 J'essaie d'utiliser les critères api pour assembler un filtre dynamique. Cependant, lorsque j'ajoute une Restriction sur un Ensemble d'Enums qui est une propriété de mon objet Critères, j'obtiens une org.hibernate.exception.GenericJDBCException.Filtrer les critères d'hibernation sur un ensemble de valeurs enum

mon code est comme ceci:

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

} 

Mon mise en veille prolongée fichier de mappage a un ensemble de valeurs Enum comme spécifié dans la documentation de mise en veille prolongée: http://docs.jboss.org/hibernate/stable/core/reference/en/html/collections.html#collections-ofvalues. Le fichier (FollowUp.hbm.xml ) est comme ce

<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> 

le code de filtre de critères est comme ceci:

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); 
} 

Quand je lance mes tests (avec sortie sql) Je reçois l'erreur suivante :

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

la sortie SQL est la suivante:

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

Est-ce que quelqu'un connaît la manière correcte de filtrer sur un ensemble de valeurs enum dans un critère (dans Hibernate 3.2)?

Vive Simon

Répondre

1

Il semble que vous passez un type incompatible de paramètre. Par exemple, il attend longtemps mais vous passez int. Définissez votre niveau de consignation sur Trace et observez ce que Hibernate attend pour pouvoir décider de transmettre un tableau ou un ensemble ou quelque chose d'autre.

1

J'ai regardé quelques pages différentes, dont les suivantes:

dont celui-ci qui ressemble à une solution élégante pour les gens à l'aide de mise en veille prolongée 3.5 ou JPA 2.0 (avec annotations):

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

Celui-ci m'a finalement orienté vers une solution: https://forum.hibernate.org/viewtopic.php?f=1&t=942839&start=0

En fin de compte j'ai fait un sous-menu manuel, je ne suis pas content mais ça marche. Je ne peux pas croire que c'est la solution préférée, mais je ne pouvais pas en trouver d'autres. Il est à peu près aussi laid comme une solution peut être et encore justifier le nom :-(

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; 
} 

Hope this helps, si vous quelqu'un trouve une meilleure solution pour la version de mise en veille prolongée (3.2) s'il vous plaît poster pour aider la communauté

Vive Simon

0

Je sais que c'est une vieille question, mais je viens de problème rencontré silimar et solution.

trouvé

Vous devez joindre mainCategories et d'interroger à l'aide elements propriété. Juste comme ça:

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