我真的想在嵌套查询中使用嵌套属性作为命名参数。这样我就可以更优雅地维护我的param bean。
例如,我要像这样写我的HQL:
"......
where
employee.age >= :age.min
and
employee.age <= :age.max
and
employee.name = :name"
并将所有参数放入一个paramBean中,在这个paramBean中,有一个嵌套的bean(名为“ age”),并且嵌套的bean具有2个属性:最小值和最大值
但是问题是:
在org.hibernate.internal.AbstractQueryImpl.setProperties(Object)方法,实现代码为:
Getter getter = ReflectHelper.getGetter( clazz, namedParam );
Class retType = getter.getReturnType();
final Object object = getter.get( bean );
它在param bean上使用getter方法,因此它无法检索嵌套的属性。
我必须在param bean中创建很多委托方法,以访问嵌套的属性:
public int getAgeMin() {
return this.age.getMin();
}
public int getAgeMax() {
return this.age.getMax();
}
并像这样写HQL:
"......
where
employee.age >= :ageMin
and
employee.age <= :ageMax
and
employee.name = :name"
这个问题困扰了我很多年。
而且我终于找到了解决它的方法。
这里是解决方法:
HQL喜欢:
"......
where
employee.age >= :age_min
and
employee.age <= :age_max
and
employee.name = :name"
辅助方法的代码为:
private void setParameters(final Query query, final Object paramBean) {
for (String namedParam : query.getNamedParameters()) {
try {
// !!! Fix problem (1) !!!
// unescape the param name into nested property name
String nestedPropName = StringUtils.replace(namedParam, "_",
".");
// !!! Fix problem (2) !!!
// retrieve the nested property, using Apache Commons BeanUtils
// see: http://commons.apache.org/proper/commons-beanutils/
Object paramValue = PropertyUtils.getNestedProperty(paramBean,
nestedPropName);
Class<?> paramType = null;
if (paramValue != null) {
paramType = paramValue.getClass();
}
if ((paramType != null)
&& Collection.class.isAssignableFrom(paramType)) {
query.setParameterList(namedParam,
(Collection<?>) paramValue);
} else if ((paramType != null) && paramType.isArray()) {
query.setParameterList(namedParam, (Object[]) paramValue);
} else {
Type type = this.guessType(paramType);
query.setParameter(namedParam, paramValue, type);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
private Type guessType(final Class<?> clazz) throws HibernateException {
SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) this.sessionFactory;
String typeName = clazz.getName();
Type type = sessionFactoryImplementor.getTypeResolver().heuristicType(
typeName);
boolean serializable = type != null && type instanceof SerializableType;
if (type == null || serializable) {
try {
sessionFactoryImplementor.getEntityPersister(clazz.getName());
} catch (MappingException me) {
if (serializable) {
return type;
} else {
throw new HibernateException(
"Could not determine a type for class: " + typeName);
}
}
return this.getSession().getTypeHelper().entity(clazz);
} else {
return type;
}
}
要点是[!!!解决问题(1)!!!]]和[!!!解决问题(2)!!!],
其他所有代码都只是从org.hibernate.internal.AbstractQueryImpl复制而来>>
我真的想在嵌套查询中使用嵌套属性作为命名参数。这样我就可以更优雅地维护我的param bean。例如,我要像这样写我的HQL:“ ...... where employee.age&...