HQL查询使用有效的SQL查询

时间:2018-05-01 18:21:05

标签: java hibernate rest hql hsqldb

我正在使用HSQLDB和Hibernate,我想从我的REST API执行搜索请求。

例如,对于像localhost:8080/search?token=a%20e这样的REST请求,我的方法应该创建以下查询:FROM Course WHERE Course.description LIKE '%a%' OR Course.description LIKE '%e%'并且我得到此异常:

  

javax.servlet.ServletException:java.lang.IllegalArgumentException:org.hibernate.QueryException:无法解析路径[Course.description],意外令牌[课程] [FROM model.Course WHERE Course.description LIKE' %A%'或者课程说明喜欢'%e%']

这是SearchServiceCoursedescription搜索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%'

当我在IDEA的SQL控制台中尝试SELECT * FROM Course WHERE c.description LIKE '%a%' OR c.DESCRIPTION LIKE '%e%';时,它会成功运行。 (我在创建的查询中没有使用SELECT *,因为HQL没有使用它)

我是HQL和SQL的新手,所以我不知道问题出在哪里。

修改

在调试器模式下,我找到了调用异常的确切位置。 Hibernate似乎有问题:

The call of Session.createQuery(String queryString)

我不知道造成这个问题的原因。

1 个答案:

答案 0 :(得分:1)

HQL适用于绑定参数,因此直接添加 LIKE'%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] + "%")
}

正如您所看到的,简单查询的代码很多。

所以基本上你有两个选择:

  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();
    
  3. TIPS:

    请勿绑定您的参与。使用 query.setParameter(..)