一、前言
我们都知道Hibernate是S2SH框架中的持久层的模块。主要是和数据库进行打交道,对数据进行增删改查。在整个框架中也占有很重要的一部分。但是当我们要进行查询的时候,单表还是比较简单的。多表就需要我们用连接来操作。 下面小编就系统的整理一下Hibernate如何查询各种类型表的数据。
二、查询的分类
三、实战练习
3.1 准备实体类
假定关系如上如所示:一个部门有多个用户,一个岗位可以有多个用户,一个用户可以在多个岗位。
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%的,所以查询的操作我们一定要熟练于键盘。