Последовательные проблемы с именованными параметрами в Hibernate (Spring HibernateTemplate)

Я пытаюсь использовать именованные параметры для ввода некоторых строк в запрос. Я использую spring и hibernateTemplate, и я новичок в Hibernate. Раньше у меня работали безымянные и именованные параметры, но кажется, что когда они находятся рядом друг с другом, они выдают ошибку. Я сделал пример кода, аналогичный моей проблеме ниже (упрощенный, чтобы выделить проблему под рукой). orderBy содержит строку поля, а orderDirection содержит ASC или DESC.

public List<HashMap<String, Object>> exampleList(String orderBy, String orderDirection) {
    logger.debug(orderBy);
    logger.debug(orderDirection);

    final String queryString =  "SELECT new map("+
                                "a.id AS id, "+
                                "a.name AS name, "+
                                "a.number AS number ) "+
                                "FROM Asset a "+
                                "ORDER BY :orderBy :orderDirection";

    String[] parameterNames = {"orderBy", "orderDirection"};
    Object[] parameterValues = {orderBy, orderDirection};

    List<HashMap<String, Object>> results = (List<HashMap<String, Object>>) hibernateTemplate.find(queryString, parameterNames, parameterValues);

    return results;
}

Консоль отлаживает мои параметры:

DEBUG: com.myOrg.myProject.asset.AssetDAO - a.id
DEBUG: com.myOrg.myProject.asset.AssetDAO - desc

И я знаю, что этот запрос будет работать нормально сам по себе, так как я тестировал его, помещая значения непосредственно в строку запроса. Я знаю, что это плохая практика и может подвергнуть меня инъекциям, поэтому я этого не делаю.

Ошибка, которую я получаю, выглядит следующим образом (трассировка стека сокращена для удобства чтения, но это единственная ошибка, и я могу предоставить полную трассировку стека по запросу):

SEVERE: Servlet.service() for servlet dmat3 threw exception
org.hibernate.hql.ast.QuerySyntaxException: unexpected token: : near line 1, column 118 [SELECT new map(a.id AS id, a.name AS name, a.number AS number ) FROM com.gsipt.dmat3.asset.Asset a ORDER BY :orderBy :orderDirection]
    at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:31)
    at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:24)
    at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:59)
    at org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:258)
    at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:157)
    at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:111)
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
    at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:56)
    at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:72)
    at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:133)
    at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:112)
    at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1623)
    at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:914)
    at org.springframework.orm.hibernate3.HibernateTemplate$30.doInHibernate(HibernateTemplate.java:1)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
    at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:912)
    at com.myOrg.myProject.asset.AssetDAO.exampleList(AssetDAO.java:142)
    at com.myOrg.myProject.navigator.NavigatorController.assetGrid(NavigatorController.java:163)

Опять же, это прекрасно работает, когда есть отдельные параметры, но когда они помещаются вместе, это происходит. Эту же ошибку можно воссоздать с использованием неназванных параметров, только "неожиданный токен" является вторым "?" в строке запроса. Как поместить два параметра, именованные или безымянные, рядом друг с другом, как это имело бы смысл в операторе ORDER BY.

Спасибо, - Клифф


person Cliff Casey    schedule 01.07.2011    source источник


Ответы (4)


Вы используете find, а не

findByNamedParams

См. здесь. Подробнее об API Spring 3 см. здесь.

Также обратите внимание, что в документации HibernateTemplate говорится

ПРИМЕЧАНИЕ. Начиная с Hibernate 3.0.1, транзакционный код доступа к Hibernate также может быть закодирован в простом стиле Hibernate. Следовательно, для новых проектов рассмотрите возможность использования стандартного стиля Hibernate3 для кодирования объектов доступа к данным, основанного на SessionFactory.getCurrentSession().

person hvgotcodes    schedule 01.07.2011
comment
Понял, но не исправляет, к сожалению. На самом деле версия, которую я вставил с помощью «найти», была ошибкой, потому что я пытался что-то отладить, я использовал findByNamedParam и получил ту же ошибку. Я даже попробовал это только сейчас по вашей рекомендации и получил идентичную ошибку. - person Cliff Casey; 01.07.2011
comment
hvgotcodes: У вас есть примеры DAO на основе SessionFactory.getCurrentSession? - person Justin Wrobel; 01.07.2011

Вы не можете использовать параметры (именованные или позиционные) в предложении ORDER BY. Вы можете использовать их только в предложении WHERE.

person Stevi Deter    schedule 01.07.2011

Почему вам нужно параметризовать их в любом случае? Пока значения для orderBy и orderDirection не поступают из пользовательского ввода, вы можете безопасно просто объединить значения в запрос.

if orderDirection == Sort.ASC) {
    queryString += " ASC";
}
else {
    queryString += " DESC";
}

и т.д

person matt b    schedule 01.07.2011
comment
Я мог бы сделать это, но меня беспокоит не только инъекция. Я хотел бы знать, почему он не выполняет то, что выглядит довольно простой операцией, и что я делаю неправильно. - person Cliff Casey; 01.07.2011

Параметры предназначены для указания значений, а не для построения синтаксиса sql. Просто объедините строки.

person James Scriven    schedule 01.07.2011