我有许多类作为继承层次结构映射到单个表中。
我想使用以下Criteria
查询,但这会产生ClassCastException
,因为Class
无法投放到String
。
Set<Class> childClasses = new HashSet<>();
childClasses.add(Child1.class);
childClasses.add(Child2.class);
session.createCriteria(Parent.class)
.add(Restrictions.in("class", childClasses)
.list();
我注意到Hibernate支持使用Restrictions.eq("class", childClass)
指定单个类,因此我可以使用Disjunction
&#39;来解决此问题。我也知道,如果我的resriction基于每个子类的鉴别器字符串,但是我不想使用这些,那么这将有效。
可以这种方式使用Criteria
吗? this question接受的答案表明,当课程属于您Criteria
所基于的课程的属性时它会起作用,但在我没有这种情况下它似乎无效如上所示。
答案 0 :(得分:1)
查看源代码,我会说这是一个Hibernate错误。
例如,SimpleExpression
(由Restrictions.eq
返回)调用criteriaQuery.getTypedValue
来处理Class
值转换为相应的鉴别值。
InExpression
(由Restrictions.in
返回)按原样添加值,而不进行转换。这就是为什么你得到ClassCastException
的原因,因为后来尝试将Class
转换为String
(显然你的鉴别器值的类型是String
)。< / p>
您可以避免使用此表单直到它已修复(您已经建议了正确的解决方法),或者,如果您真的想坚持直接使用Class
对象,那么您可以实现自定义{ {1}}在您的项目中。例如,像:
InExpression
然后您将使用它代替public class ClassInExpression extends InExpression {
private static final String CLASS = "class";
private final Collection<Class> values;
public ClassInExpression(Collection<Class> values) {
super(CLASS, values.toArray(new Object[values.size()]));
this.values = values;
}
@Override
public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) {
if (criteriaQuery.getTypeUsingProjection(criteria, CLASS).isComponentType()) {
return super.getTypedValues(criteria, criteriaQuery);
}
return convertToDiscriminatorValues(criteria, criteriaQuery);
}
private TypedValue[] convertToDiscriminatorValues(Criteria criteria, CriteriaQuery criteriaQuery) {
List<TypedValue> resultList = new ArrayList<TypedValue>();
for (Object value : values) {
resultList.add(criteriaQuery.getTypedValue(criteria, CLASS, value));
}
return resultList.toArray(new TypedValue[resultList.size()]);
}
}
:
Restrictions.in