如何在休眠查询中使用嵌套属性作为命名参数?

问题描述 投票:3回答:2

我真的想在嵌套查询中使用嵌套属性作为命名参数。这样我就可以更优雅地维护我的param bean。

例如,我要像这样写我的HQL:

"......
where
    employee.age >= :age.min
  and
    employee.age <= :age.max
  and
    employee.name = :name"

并将所有参数放入一个paramBean中,在这个paramBean中,有一个嵌套的bean(名为“ age”),并且嵌套的bean具有2个属性:最小值和最大值

但是问题是:

  1. HQL语法不支持将嵌套属性命名为param:Hibernate将引发异常,因为它不允许使用“。”在参数名称中。
  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"

这个问题困扰了我很多年。

而且我终于找到了解决它的方法。

这里是解决方法:

  1. 对于问题(1):在HQL中:将“ _”用作“。”的转义字符。

HQL喜欢:

"......
where
    employee.age >= :age_min
  and
    employee.age <= :age_max
  and
    employee.name = :name"
  1. 对于问题(2):编写一些辅助方法,以设置所有参数值用于HQL。

辅助方法的代码为:

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

java sql hibernate parameters param
2个回答
0
投票

如何使用example query Criteria代替:


0
投票

我为什么需要这个?

© www.soinside.com 2019 - 2024. All rights reserved.