Java Hibernate:设置多变量搜索的参数和来自其他表的数据

Java Hibernate:设置多变量搜索的参数和来自其他表的数据,java,spring,hibernate,spring-mvc,search,Java,Spring,Hibernate,Spring Mvc,Search,我正在开发一个SpringMVC应用程序,在这个应用程序中,我想用上面提到的一些条件在数据库中搜索。不幸的是,他们大约有10-12人。所以我之前问过一个问题,如何将它们分解成小块,检查其中哪些不是null,并将它们用作参数。通过使用下面提到的StringBuilder,我取得了部分成功 我遇到的问题是如何为非空值设置query.setParameter(“variablename”,variablename)。首先是一个例子: @Override public List<Student&

我正在开发一个SpringMVC应用程序,在这个应用程序中,我想用上面提到的一些条件在数据库中搜索。不幸的是,他们大约有10-12人。所以我之前问过一个问题,如何将它们分解成小块,检查其中哪些不是null,并将它们用作参数。通过使用下面提到的StringBuilder,我取得了部分成功

我遇到的问题是如何为非空值设置query.setParameter(“variablename”,variablename)。首先是一个例子:

 @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().equals(""))){
        sb.append("s.country=:").append(hostSearchHistory.getCountry());
    }
    if(!(hostSearchHistory.getCity().equals(""))){
        sb.append("OR s.city=:").append(hostSearchHistory.getCity());
    }
    if(!(hostSearchHistory.getDrivingLicense().equals(""))){
        sb.append("OR s.studentDetails.drivingLicense=").append(hostSearchHistory.getDrivingLicense());
    }
    if(!(hostSearchHistory.getGender().equals(""))){
        sb.append("OR s.gender=").append(hostSearchHistory.getGender());
    }
    if(!(hostSearchHistory.getMotherTongue().equals(""))){
        sb.append("OR s.studentDetails.motherTongue=:").append(hostSearchHistory.getMotherTongue());
    }
    if(!(hostSearchHistory.getSmoker().equals(""))){
        sb.append("OR s.studentDetails.smoker=").append(hostSearchHistory.getSmoker());
    }
    if(!(hostSearchHistory.getPreviousAuPair().equals(""))){
        sb.append("OR s.studentDetails.previouslyAuPair=").append(hostSearchHistory.getPreviousAuPair());
    }
    if(!(hostSearchHistory.getWillingToWork().equals(""))){
        sb.append("OR s.studentDetails.willingToWork=").append(hostSearchHistory.getWillingToWork());
    }
    if(!(hostSearchHistory.getWorkForSingleParent().equals(""))){
        sb.append("OR s.studentDetails.workForSingleParent=").append(hostSearchHistory.getWorkForSingleParent());
    }
    if(!(hostSearchHistory.getWorkingForDisabledChild().equals(""))){
        sb.append("OR s.studentDetails.workingForDisabledChild").append(hostSearchHistory.getWorkingForDisabledChild());
    }
    sb.append(" order by s.registrationDate desc");

    Query query = session.createQuery(sb.toString());
    if(!(hostSearchHistory.getCountry().equals(""))){
        query.setParameter("country",hostSearchHistory.getCountry());
    }
    if(!(hostSearchHistory.getCity().equals(""))){
        query.setParameter("city",hostSearchHistory.getCity());
    }
    if(!(hostSearchHistory.getDrivingLicense().equals(""))){
        query.setParameter("drivingLicense",hostSearchHistory.getDrivingLicense());
    }
    if(!(hostSearchHistory.getGender().equals(""))){
        query.setParameter("gender",hostSearchHistory.getGender());
    }
    if(!(hostSearchHistory.getMotherTongue().equals(""))){
        query.setParameter("motherTongue",hostSearchHistory.getMotherTongue());
    }
    if(!(hostSearchHistory.getSmoker().equals(""))){
        query.setParameter("smoker",hostSearchHistory.getSmoker());
    }
    if(!(hostSearchHistory.getPreviousAuPair().equals(""))){
        query.setParameter("previouslyAuPair",hostSearchHistory.getPreviousAuPair());
    }
    if(!(hostSearchHistory.getWillingToWork().equals(""))){
        query.setParameter("willingToWork",hostSearchHistory.getWillingToWork());
    }
    if(!(hostSearchHistory.getWorkForSingleParent().equals(""))){
        query.setParameter("workForSingleParent",hostSearchHistory.getWorkForSingleParent());
    }
    if(!(hostSearchHistory.getWorkingForDisabledChild().equals(""))){
        query.setParameter("workingForDisabledChild",hostSearchHistory.getWorkingForDisabledChild());
    }

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

}
学生信息模型:

@Entity
@Table(name = "studentinfo")
public class StudentInfo {
    @Id
    @Column(name="infoid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "student_info_gen")
    @SequenceGenerator(name = "student_info_gen",sequenceName = "student_info_seq")
    private Long studentInfoId;

 @OneToOne
    @JoinColumn(name = "studentid",nullable = false)
    private Student studentDetails;

    public Student getStudentDetails() {
        return studentDetails;
    }

    public void setStudentDetails(Student studentDetails) {
        this.studentDetails = studentDetails;
    }
}

谢谢你的帮助

这是我项目中的一个示例,我不会建议更好的方法,但会在您的查询中显示一些缺失的点。我也有较长的查询,但编写此查询以保持简单。我使用
CreateQuery
方法:

@Override
    public List<CampaignCode> queryCampaignCode(Merchant merchant, PaymentSystemType paymentSystemType, Date now) {
        if (merchant == null) {
            new IllegalArgumentException("Merchant parameter can not be null!");
        }
        StringBuilder sb = new StringBuilder();
        sb.append("FROM ").append(CampaignCode.class.getName()).append(" WHERE merchant=:merchant");
        if (paymentSystemType != null) {
            sb.append("AND paymentSystemType=:paymentSystemType ");
        }
        if (now != null) {
            sb.append(" AND :now BETWEEN startDate AND endDate ");
        }
        //Return current session
        Query query = getSession().createQuery(sb.toString());
        if (paymentSystemType != null) {
            query.setParameter("paymentSystemType", paymentSystemType);
        }
        if (now != null) {
            query.setParameter("now", now);
        }
        query.setParameter("merchant", merchant);
        return query.list();
    }
@覆盖
公共列表查询CampaignCode(商户,付款系统类型PaymentSystemType,当前日期){
如果(商户==null){
新的IllegalArgumentException(“商户参数不能为空!”);
}
StringBuilder sb=新的StringBuilder();
sb.append(“FROM”).append(activitycode.class.getName()).append(“其中merchant=:merchant”);
如果(paymentSystemType!=null){
sb.追加(“和paymentSystemType=:paymentSystemType”);
}
如果(现在!=null){
sb.附加(“和:现在介于开始日期和结束日期之间”);
}
//返回当前会话
Query Query=getSession().createQuery(sb.toString());
如果(paymentSystemType!=null){
query.setParameter(“paymentSystemType”,paymentSystemType);
}
如果(现在!=null){
setParameter(“现在”,现在);
}
query.setParameter(“商户”,商户);
返回query.list();
}
  • 所以在这里,我有一个
    merchant
    对象,它是一直设置的,所以我在创建sql时没有任何语法错误。在您的示例中,如果用户只设置了国家/地区,则在运行时会出现sql语法异常,请谨慎使用
    用法。
  • 在您的示例中,您只需使用
    String#equals
    方法进行检查,如果我的所有参数都是字符串,我始终信任Apache
    StringUtils#isBlank
    (我的示例不是这样,但在您的示例中,我更喜欢
    StringUtils#isBlank
  • 从类名(如
    Student.class.getName()
    )中获取表名会很好,这样,如果更改了类名,查询就会知道
  • 最后

    我对这种用法很满意,而且我可以在上层(服务层或业务层)将这种方法用于lor业务逻辑,所以我用这种方法一次又一次地重用相同的方法

    编辑


    编辑后,如果未设置国家/地区、城市或其他参数,则仍会出现我的第一个场景。

    我认为您可以通过使用。您只需将所有参数值设置为示例对象(
    null
    值将被忽略,因此任何
    null
    值都不会包含在生成的SQL中)。它看起来像这样

    Student s = new Student();
    s.setCountry(hostSearchHistory.getCountry());
    s.setCity(hostSearchHistory.getCity());
    ...
    StudentDetails sd = new StudentDetails();
    sd.setDrivingLicense(hostSearchHistory.getDrivingLicense());
    sd.setSmoker(hostSearchHistory.getSmoker());
    ...
    
    Criteria crit = session.createCriteria(Student.class);
    crit.add(Example.create(s));
    crit.createCriteria("studentDetails").add(Example.create(sd));
    List<Student> studentList = crit.list();
    
    Student s=新学生();
    s、 setCountry(hostSearchHistory.getCountry());
    s、 setCity(hostSearchHistory.getCity());
    ...
    StudentDetails sd=新的StudentDetails();
    sd.setDrivingLicense(hostSearchHistory.getDrivingLicense());
    sd.setSmoker(hostSearchHistory.getSmoker());
    ...
    Criteria crit=session.createCriteria(Student.class);
    标准添加(示例创建);
    crit.createCriteria(“studentDetails”).add(Example.create(sd));
    List studentList=crit.List();
    

    有一些限制,如忽略
    id
    字段以及关联(否则仅将
    sd
    设置为
    s
    就足够了)。

    您可以使用Criteria API。你可以在这里找到一个例子:@Faton:我已经编辑了我的主要帖子以包含完整的方法,对吗。对我来说,更重要的是,我是否能以我现有的方式引用一对一实体。非常感谢。声明@OneToOne似乎是正确的。如果以这种方式构建查询,请不要忘记在所有字段都为null/空时处理该情况。@Faton:我是通过检查字符串来实现的。。。是吗?如果所有字符串都是空的,您将得到以下“来自学生as s where order by s.registrationDate desc”。
    Student s = new Student();
    s.setCountry(hostSearchHistory.getCountry());
    s.setCity(hostSearchHistory.getCity());
    ...
    StudentDetails sd = new StudentDetails();
    sd.setDrivingLicense(hostSearchHistory.getDrivingLicense());
    sd.setSmoker(hostSearchHistory.getSmoker());
    ...
    
    Criteria crit = session.createCriteria(Student.class);
    crit.add(Example.create(s));
    crit.createCriteria("studentDetails").add(Example.create(sd));
    List<Student> studentList = crit.list();