Запрос HQL выдает исключение QueryException с рабочим запросом SQL

Я работаю с HSQLDB и Hibernate и хочу выполнять поисковые запросы из моего REST API.

Например, для запроса REST, такого как localhost:8080/search?token=a%20e, мой метод должен создать следующий запрос: FROM Course WHERE Course.description LIKE '%a%' OR Course.description LIKE '%e%', и я получаю это исключение:

javax.servlet.ServletException: java.lang.IllegalArgumentException: org.hibernate.QueryException: Unable to resolve path [Course.description], unexpected token [Course] [FROM model.Course WHERE Course.description LIKE '%a%' OR Course.description LIKE '%e%']

Это код в методе SearchService для поиска Course по description или name.

public List<Course> searchCourses(String token, MatchIn column) {

    // Prepare and clean token, leaving only key words

    String[] keyWords = token.split(" ");

    // Build query and ask database to retrieve relevant courses

    StringBuilder sb = new StringBuilder("FROM Course WHERE ");
    String colName = "Course.";
    if (column.equals(MatchIn.DESCRIPTION))  colName += "description";
    else if (column.equals(MatchIn.NAME))  colName += "name";
    sb.append(colName);

    int i = 0;

    sb.append(" LIKE \'");
    sb.append("%");
    sb.append(keyWords[i]);
    sb.append("%\'");

    if (keyWords.length != 1){
        i++;

        for (; i < keyWords.length; i++) {
            sb.append(" OR " + colName +
                    " LIKE \'");
            sb.append("%");
            sb.append(keyWords[i]);
            sb.append("%\'");
        }
    }

    Query query = session.createQuery(sb.toString());

    return query.list();
}

Обратите внимание, что в полученном мной исключении говорится, что мой метод фактически создает следующий запрос: FROM *model.*Course WHERE Course.description LIKE '%a%' OR Course.description LIKE '%e%'

Когда я пробую SELECT * FROM Course WHERE c.description LIKE '%a%' OR c.DESCRIPTION LIKE '%e%'; в консоли IDEA SQL, он работает успешно. (Я не использую SELECT * в создаваемом мной запросе, потому что HQL его не использует)

Я новичок в HQL и SQL, поэтому не знаю, в чем проблема.

Обновлено:

В режиме отладчика я нашел точное место, где вызывается исключение. Похоже, проблема с Hibernate:

Запрос HQL выдает исключение QueryException с рабочим запросом SQL

Я не знаю, что вызывает эту проблему.

Добавьте псевдоним для объекта Course и укажите для него полный путь к классу

Joe Taras 02.05.2018 16:58
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
170
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

HQL работает с параметрами привязки, поэтому прямое добавление НРАВИТСЯ '% key%' не сработает. Hibernate преобразует HQL в SQL, поэтому для этого вы можете сделать следующее:

for (; i < keyWords.length; i++) {
    sb.append(" OR " + colName + " LIKE " + "key" + String.valueOf(i));// notice that I'm not adding the '%%'
}

тогда вам нужно привязать параметры:

 Query query = session.createQuery(sb.toString());

 for (int j = 0; j < keyWords.length; j++) {
    query.setParameter("key" + String.valueOf(j), "%" + keyWords[j] + "%")
}

Как видите, для простого запроса много кода.

Итак, в основном у вас есть 2 варианта:

  1. Создайте собственный SQL. session.createSQLQuery (...)

  2. Критерии использования.

    String colName = "";
    
    if (column.equals(MatchIn.DESCRIPTION)) {
        colName = "description";
    } else if (column.equals(MatchIn.NAME)) {
        colName = "name";
    }
    
    Criteria criteria = session.createCriteria(Course.class)
    
    for(String key : keyWords) {
        criteria.add(Restrictions.or(Restrictions.like( colName, "%" + key + "%"));
    }
    
    return criteria.list();
    

ЧАЕВЫЕ:

НЕ СВЯЗЫВАЙТЕ СВОИ ПАРАМЕТРЫ. ИСПОЛЬЗОВАТЬ query.setParameter (..)

Другие вопросы по теме