Проблеми с последователни именувани параметри в 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
Разбрано, но не го поправя за съжаление. Всъщност версията, която поставих с 'find', беше грешка, защото се опитвах да отстраня грешки в нещо, използвах 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