休眠:为其他表

时间:2015-05-12 12:57:25

标签: java spring hibernate spring-mvc search

我正在开发一个Spring-MVC应用程序,我想在数据库中搜索一些提到的标准。不幸的是,它们大约有10-12个。所以我之前问过一个关于如何将它们分解成小块的问题,检查它们中的哪些不是空的,并将它们用作参数。通过使用如下所述的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;

}

现在,即使我可以像这样构建查询,我还必须继续挖掘HostSearchHistory,然后设置query.setParameters()。还有其他选择吗?

另外,正如大家们可能已经注意到的那样,最后一个sb.append从映射请求信息,特别是与StudentInfo的一对一映射。这种语法是否正确?我发布了以下学生和学生信息模型,以进一步明确。请告诉我。非常感谢。

学生模特:

@Entity
@Table(name="student")
public class Student implements UserDetails{
@Id
    @Column(name="studentid")
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "student_seq_gen")
    @SequenceGenerator(name = "student_seq_gen",sequenceName = "student_seq")
    private Long studentid;


    @OneToOne(mappedBy = "studentDetails",fetch = FetchType.LAZY,cascade = CascadeType.REMOVE)
    private StudentInfo studentInfoDetails = new StudentInfo();

    public void setStudentInfoDetails(StudentInfo studentInfoDetails){
        this.studentInfoDetails = studentInfoDetails;
    }

    public StudentInfo getStudentInfoDetails(){
        return this.studentInfoDetails;
    }
}

StudentInfo模型:

@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;
    }
}

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

这是我项目中的一个示例,我不会建议更好的方法,但会在您的查询中显示一些遗漏点。我也有更长的查询,但写这个以保持简单。我使用 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();
    }
  1. 所以在这里我有一个merchant对象,它始终设置,所以我在创建sql的每个可能性中都没有语法错误。在您的示例中,如果用户仅设置国家/地区,则在运行时获得sql语法异常,非常谨慎地使用AND
  2. 在您的示例中,您只使用String#equals方法检查我总是信任Apache StringUtils#isBlank如果我的所有参数都是字符串(我的样本不是这种情况,但在您的情况下我更喜欢StringUtils#isBlank })
  3. 最好从类名Student.class.getName()获取表名,这样您的查询就会知道您的类名是否已更改。
  4. <强> 最后

    我很满意这种用法,我也可以将这种方法用于上层的业务逻辑(服务或业务层)所以我用这种方式一次又一次地重复使用相同的方法。

    <强> 修改

    编辑完成后,如果国家未设置且城市或其他参数为SET,则仍会发生我的第一个场景。

答案 1 :(得分:1)

我认为您可以使用Hibernate Query By Example简化这一过程。您只需将所有参数值设置为示例对象(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();

有一些限制,例如id字段被忽略,关联也是如此(否则只需将sd设置为s即可。)