一、前言

      我们都知道Hibernate是S2SH框架中的持久层的模块。主要是和数据库进行打交道,对数据进行增删改查。在整个框架中也占有很重要的一部分。但是当我们要进行查询的时候,单表还是比较简单的。多表就需要我们用连接来操作。 下面小编就系统的整理一下Hibernate如何查询各种类型表的数据。

二、查询的分类




【Hibernate】Hibernate单表查询和多表查询_数据库


三、实战练习

3.1 准备实体类



【Hibernate】Hibernate单表查询和多表查询_数据库_02


      假定关系如上如所示:一个部门有多个用户,一个岗位可以有多个用户,一个用户可以在多个岗位。

      User类:

public class User implements Serializable {
    private long uid;
    private String username;
    private String password;
    private String sex;
    private String phone;
    private String email;

    private Department department;  // 一对一

    private Set<Post> posts;   //多对多

    public long getUid() {
        return uid;
    }

    public void setUid(long uid) {
        this.uid = uid;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    public Set<Post> getPosts() {
        return posts;
    }

    public void setPosts(Set<Post> posts) {
        this.posts = posts;
    }

}

      Department类:

public class Department implements Serializable {
    private long did;
    private String dname;
    private String description;

    private Set<User> users;  //多对多
    public long getDid() {
        return did;
    }
    public void setDid(long did) {
        this.did = did;
    }
    public String getDname() {
        return dname;
    }
    public void setDname(String dname) {
        this.dname = dname;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public Set<User> getUsers() {
        return users;
    }
    public void setUsers(Set<User> users) {
        this.users = users;
    }


}

      Port类:

public class Post implements Serializable {
    private long pid;
    private String pname;
    private String description;

    private Set<User> users;  //多对多

    public long getPid() {
        return pid;
    }

    public void setPid(long pid) {
        this.pid = pid;
    }

    public String getPname() {
        return pname;
    }

    public void setPname(String pname) {
        this.pname = pname;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public Set<User> getUsers() {
        return users;
    }

    public void setUsers(Set<User> users) {
        this.users = users;
    }

}

3.2 单表查询

  • 页面上要显示的字段和数据库字段相比,少。

      例如,我们要获取所有用户的用户id和姓名,我们可以采用获取T_User的所有字段,但是这样效率比较低,下面这种方法是推荐的:

      使用构造函数,把要查询的字段写在构造函数中,当然构造函数可以重载,我们可以写很多个:

public Collection<User> getAllUserInfo(){
    String hql = "select new User(uid,username) from User";
    return this.getHibernateTemplate().find(hql);
}

      对User实体类的改变:添加构造函数

public User(){

    }

    public User(long uid,String username){
        this.uid=uid;
        this.username=username;
    }
  • 当页面显示和数据库字段差不多的时候

      这个查询是最简单的,直接查询表的所有信息就可以:

public Collection<User> getAllUserInfo(){
    String hql = "from User";
    return this.getHibernateTemplate().find(hql);
}

3.3 多表查询

  • 两张表查询,一个页面显示一个表的信息,点击链接显示另一个表的信息,一对多查询

      比如,实体类中一个部门对应多个员工。

      在一个页面显示所有的部门,点击链接,可以在另一个页面显示对应部门下所有的员工信息。

      当加载第一个页面显示所有部门的时候,后台:直接使用“from Department”。

public Collection<Department> getAllDepartment(){
    String hql = "from Department";
    return this.getHibernateTemplate().find(hql);
}

懒加载,所以在执行上面的 from Department ,sql语句的时候,并没有加载用户信息,这样第一个页面只能加载部门的信息了。

      点击链接的时候,后台:”from Department d where d.user.did=?”。

public Collection<Department> getAllUserInfo(Department department){
    String hql = "from Department d where d.user.did=?";
    return this.getHibernateTemplate().find(hql,department.getDid());
}
  • 在一个页面显示两张表的所有信息

      解决方案:使用迫切左外连接

select new UserView(u.username,d.dname) from User u inner join u.department d ;

      另外小编也试过这种方案:拼接表查询

select user.username,user.truename,user.sex,user.idnum,user.level,s.sumScore from Score as s,Examuser as user where s.id.userId = user.id;
  • 三张及以上的(一对多,多对多)

      解决方案:采用三张迫切左外连接的方式

public Collection<User> getAllUserInfo(Department department){
    String hql = "from User u left join fetch u.department d left join fetch u.posts p";
    List<User> userList = this.getHibernateTemplate().find(hql);
    return new HashSet<User>(userList);
}

this.getHibernateTemplate().find(hql)查询出来的结果会有重复的值,可以把他放到set中,set自动排重。然后返回set就可以了。

四、小结

      到这里为止,基本就算是介绍完了,这些操作都是非常经典的,就像是Hibernate原生的操作。没毛病!!所以大家还是要多多的练习,多多操作。查询再一个系统中是占有70%的,所以查询的操作我们一定要熟练于键盘。