2015-05-12 44 views
0

我正在一個Spring-MVC應用程序中,我想同時在多個變量上運行搜索。但是代碼在爲第一個值本身設置參數時保持失敗。我不知道爲什麼。你能幫忙的話,我會很高興。Hibernate:org.hibernate.QueryParameterException:無法找到命名參數

ListStudents:

@Override 
public List<Student> addHostSearchHistory(HostSearchHistory hostSearchHistory, Long hostId) { 
    session = this.sessionFactory.getCurrentSession(); 
    Host host = (Host) session.get(Host.class,hostId); 
    host.getHostSearchHistorySet().add(hostSearchHistory); 
    hostSearchHistory.setHsHistory(host); 
    session.save(hostSearchHistory); 
    session.flush(); 

    StringBuilder sb = new StringBuilder(); 
    sb.append("from Student as s where "); 

    if(!(hostSearchHistory.getCountry()==null)){ 
     sb.append("s.studentCountry=:").append(hostSearchHistory.getCountry()); 
    } 
    if(!(hostSearchHistory.getCity()==null)){ 
     sb.append(" OR s.city=:").append(hostSearchHistory.getCity()); 
    } 
    if(!(hostSearchHistory.getDrivingLicense()==null)){ 
     sb.append(" OR s.studentInfoDetails.drivingLicense=").append(hostSearchHistory.getDrivingLicense()); 
    } 
    if(!(hostSearchHistory.getGender()==null)){ 
     sb.append(" OR s.gender=").append(hostSearchHistory.getGender()); 
    } 
    if(!(hostSearchHistory.getMotherTongue()==null)){ 
     sb.append(" OR s.studentInfoDetails.motherTongue=:").append(hostSearchHistory.getMotherTongue()); 
    } 
    if(!(hostSearchHistory.getSmoker()==null)){ 
     sb.append(" OR s.studentInfoDetails.smoker=").append(hostSearchHistory.getSmoker()); 
    } 
    if(!(hostSearchHistory.getPreviousAuPair()==null)){ 
     sb.append(" OR s.studentInfoDetails.previouslyAuPair=").append(hostSearchHistory.getPreviousAuPair()); 
    } 
    if(!(hostSearchHistory.getWillingToWork()==null)){ 
     sb.append(" OR s.studentInfoDetails.willingToWork=").append(hostSearchHistory.getWillingToWork()); 
    } 
    if(!(hostSearchHistory.getWorkForSingleParent()==null)){ 
     sb.append(" OR s.studentInfoDetails.workForSingleParent=").append(hostSearchHistory.getWorkForSingleParent()); 
    } 
    if(!(hostSearchHistory.getWorkingForDisabledChild()==null)){ 
     sb.append(" OR s.studentInfoDetails.workingForDisabledChild=").append(hostSearchHistory.getWorkingForDisabledChild()); 
    } 
    if(!(hostSearchHistory.getOtherLanguages()==null)){ 
     sb.append(" OR s.studentInfoDetails.otherLanguages=:").append(hostSearchHistory.getOtherLanguages()); 
    } 

    sb.append(" order by s.registrationDate desc"); 

    System.out.println("Sb.toString is "+sb.toString()); 

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

// The code fails here 
    if(!(hostSearchHistory.getCountry()==null)){ 
     query.setParameter("studentCountry",hostSearchHistory.getCountry()); 
    } 
    if(!(hostSearchHistory.getCity()==null)){ 
     query.setParameter("city",hostSearchHistory.getCity()); 
    } 
    if(!(hostSearchHistory.getDrivingLicense()==null)){ 
     query.setParameter("drivingLicense",hostSearchHistory.getDrivingLicense()); 
    } 
    if(!(hostSearchHistory.getGender()==null)){ 
     query.setParameter("gender",hostSearchHistory.getGender()); 
    } 
    if(!(hostSearchHistory.getMotherTongue()==null)){ 
     query.setParameter("motherTongue",hostSearchHistory.getMotherTongue()); 
    } 
    if(!(hostSearchHistory.getSmoker()==null)){ 
     query.setParameter("smoker",hostSearchHistory.getSmoker()); 
    } 
    if(!(hostSearchHistory.getPreviousAuPair()==null)){ 
     query.setParameter("previouslyAuPair",hostSearchHistory.getPreviousAuPair()); 
    } 
    if(!(hostSearchHistory.getWillingToWork()==null)){ 
     query.setParameter("willingToWork",hostSearchHistory.getWillingToWork()); 
    } 
    if(!(hostSearchHistory.getWorkForSingleParent()==null)){ 
     query.setParameter("workForSingleParent",hostSearchHistory.getWorkForSingleParent()); 
    } 
    if(!(hostSearchHistory.getWorkingForDisabledChild()==null)){ 
     query.setParameter("workingForDisabledChild",hostSearchHistory.getWorkingForDisabledChild()); 
    } 
    if(!(hostSearchHistory.getOtherLanguages()==null)){ 
     query.setParameter("otherLanguages",hostSearchHistory.getOtherLanguages()); 
    } 

    List<Student> studentList = query.list(); 
    for(Student student : studentList){ 
     System.out.println("Student name is "+student.getUsername()); 
    } 
    return studentList; 

} 

sb.toString()的輸出:

Sb.toString is from Student as s where s.studentCountry=:Germany OR s.city=:Hamburg OR s.studentInfoDetails.drivingLicense=true OR s.gender=male OR s.studentInfoDetails.smoker=true OR s.studentInfoDetails.willingToWork=true OR s.studentInfoDetails.workingForDisabledChild=true order by s.registrationDate desc 

錯誤日誌:

org.hibernate.QueryParameterException: could not locate named parameter [studentCountry] 
    org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterDescriptor(ParameterMetadata.java:148) 
    org.hibernate.engine.query.spi.ParameterMetadata.getNamedParameterExpectedType(ParameterMetadata.java:165) 
    org.hibernate.internal.AbstractQueryImpl.determineType(AbstractQueryImpl.java:523) 
    org.hibernate.internal.AbstractQueryImpl.setParameter(AbstractQueryImpl.java:493) 
    com.journaldev.spring.dao.HostSearchHistoryDAOImpl.addHostSearchHistory(HostSearchHistoryDAOImpl.java:82) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 

我在做什麼錯了人。你能幫忙的話,我會很高興。非常感謝。 :-)

回答

0

簡短的回答 - 你寫了這個

query.setParameter("studentCountry",hostSearchHistory.getCountry()); 

但在你的sb.toString()輸出你沒有:studentCountry

您的方法的整個第一部分應該有硬編碼的參數名稱,如sb.append("s.studentCountry=:studentCountry"),那麼第二部分應該工作。

或者,使用sb.append("s.studentCountry='").append(hostSearchHistory.getCountry()).append("'");並且完全不使用參數。

+0

我喜歡第二個選項,我根本不使用參數。我會嘗試你的解決方案,請等待。你的意思是我不需要使用query.setParameter,如果我使用你的最後一個方法。 –

+0

該死的東西工作我的朋友,只是一件事之前,我標記你的答案,你能告訴我如何可以進行搜索,因此它是不區分大小寫的,並尋找類似的東西。就像當用戶輸入國家名稱爲GerMAN時,德國在數據庫中是一個有效的國家,結果應該被返回。 –

+0

嘗試像這樣'sb.append(「upper(s.studentCountry)='」)。append(hostSearchHistory.getCountry()。toUpperCase())。append(「'」)'。 –

1

您應該使用Predrag建議的第一個選項。使用第二個選項有兩個主要缺陷:

1)性能低下。數據庫不會將一個準備好的語句與綁定變量進行緩存,但其中的許多對於所有輸入參數的組合都是如此。這意味着再次解析語句並從緩存中清除其他準備好的語句。

2)安全性。沒有綁定變量的語句非常容易受到SQL注入攻擊。它可能會或可能不會在你的具體情況爲例,但一般,假設一個惡意用戶(黑客:))輸入爲城市以下或類似的過濾條件或其他一些領域:

' union select null, USERNAME || ',' || PASSWORD, null, null... from USER_PASSWORDS -- 

他將獲得作爲學生城市返回的所有用戶名/密碼。 :) 當然這只是一個普遍的例子,它可能是您的數據庫中實際存在的表中的一些其他查詢部分或其他敏感數據。

+0

好的。我會做出必要的改變。這似乎也更靈活。感謝您的意見。 –