对一组枚举值进行休眠条件过滤 [英] hibernate criteria filtering on a set of enum values
问题描述
我正在将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屋!