我正在开发一个Spring-MVC应用程序,我希望同时在多个变量上运行搜索。但是代码仍然无法为第一个值本身设置参数。我不知道为什么。你能帮忙的话,我会很高兴。
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 :(得分:1)
您应该使用Predrag建议的第一个选项。使用第二个选项有两个主要缺点:
1)性能低下。数据库不会使用绑定变量缓存一个预准备语句,但其中许多语句适用于所有输入参数组合。这意味着重新解析语句并从缓存中清除其他准备好的语句。
2)安全。没有绑定变量的语句非常容易受到SQL注入攻击。在您的具体示例中可能会或可能不是这种情况,但通常,假设恶意用户(黑客:))为城市或其他字段输入以下或类似的过滤条件:
' union select null, USERNAME || ',' || PASSWORD, null, null... from USER_PASSWORDS --
他会将所有用户名/密码作为学生城市返回。 :) 当然,这只是一个通用示例,它可能是数据库中实际存在的表中的其他查询部分或其他敏感数据。
答案 1 :(得分:0)
简短的回答 - 你写了这个
query.setParameter("studentCountry",hostSearchHistory.getCountry());
但在您的sb.toString()
输出中,您没有:studentCountry
。
方法的整个第一部分应该有硬编码的参数名称,如sb.append("s.studentCountry=:studentCountry")
,然后第二部分应该有用。
或者,使用sb.append("s.studentCountry='").append(hostSearchHistory.getCountry()).append("'");
并且根本不使用参数。