gpt4 book ai didi

java - 如何在 hibernate 查询中使用嵌套属性作为命名参数?

转载 作者:行者123 更新时间:2023-12-03 20:21:14 25 4
gpt4 key购买 nike

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

例如,我想像这样编写 HQL:

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

并将所有参数放入一个 paramBean,
在这个 paramBean 中,有一个嵌套的 bean(名为“age”),
嵌套 bean 有 2 个属性: min 和 max。

但问题是:
  • HQL 语法不支持作为命名参数的嵌套属性:
    Hibernate 会抛出异常,因为它不允许使用
    “。”在参数名称中。
  • 在里面
    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 中创建很多委托(delegate)方法来访问嵌套属性:
    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):在 HQL 中:使用“_”作为“。”的转义字符。

  • HQL 喜欢:
    "......
    where
    employee.age >= :age_min
    and
    employee.age <= :age_max
    and
    employee.name = :name"
  • 对于问题(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 复制

    最佳答案

    使用 example query Criteria 怎么样?反而:

    Age age = ...;
    Employee employee = new Employee();
    employee.setAge(age);
    Example example = Example.create(employee);
    List results = session.createCriteria(Employee.class)
    .add(example)
    .list();

    这尽可能接近嵌套过滤参数。

    关于java - 如何在 hibernate 查询中使用嵌套属性作为命名参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28336513/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com