您好我正在使用Hibernate 3.2和1.6 JDK以及Mysql 5.0我正在尝试使用标准api来组合动态过滤器。但是当我在一组枚举上添加一个限制时,我得到了一个org.hibernate.exception.GenericJDBCException。
我的代码是这样的:
public class FollowUp {
...
public Set<AdminCategory> getAdminCategories() {...}
public void setAdminCategories(Set<AdminCategory> _arg) { ... }
}
我的hibernate映射文件有一组在hibernate文档中指定的Enum值: 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中)?
干杯 西蒙
答案 0 :(得分:1)
您似乎正在传递不兼容的参数类型。例如,它期望很长但你传递int。将您的日志级别设置为跟踪并查看hibernate期望的内容,以便您可以决定传递数组或集合或其他内容。
答案 1 :(得分:1)
我查看了几个不同的页面,包括以下内容:
包含这个看起来像是使用hibernate 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
最后我做了一个手动的subselect,我对它不满意但是它有效。我无法相信这是首选的解决方案,但我找不到任何其他解决方案。它就像解决方案一样丑陋而且仍然保证名称: - (
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)版本的解决方案,请发布它以帮助社区
干杯 西蒙
答案 2 :(得分:0)
我知道这是一个老问题,但我刚刚遇到了silimar问题并找到了解决方案。
您必须加入mainCategories
并使用elements
属性进行查询。就像那样:
session.createCriteria(FollowUp.class)
.createAlias("mainCategories", "mainCategories")
.add(Restrictions.eq("mainCategories.elements", Category.ITEM))
.list()