更多Hibernate在框架开发
1 单表查询
1.1 QID检索与查询中的效率优化
OID检索方式是Session对象的get()方法和load()方法 。都是根据id查询返回实体类对象。 其中get()是立即查询,load()是延迟查询 。
1.1.1 get()与立即查询
Depart dept = session.get(Depart.class, 1); //发送sql语句
System.out.println(dept.getDepName());
立即查询: 调用方法后立即发送sql语句进行查询操作,返回实体类对象
代码中,调用get()方法后,立即发送sql语句,查询id=1的记录,返回Depart实体类的对象。
1.1.2 load()与延迟查询
Depart dept = session.load(Depart.class, 2); //没有发送sql语句
System.out.println(dept.getDepId()); //没有发送sql语句
System.out.println(dept.getDepName()) //发送sql语句
延迟查询: 调用方法后不会发送sql语句,只是返回一个实体类的代理对象,此代理对象是一个空壳,只有实体类的id属性,当用到其他属性时才发送sql语句。也叫懒加载或懒查询
代码中,调用load()方法后,不发送sql语句,返回Depart实体类的代理对象,该代理对象只有id属性,当使用name属性时,才发送sql语句。
load()方法默认是延迟查询,可以通过配置修改成立即查询,配置为: 在查询实体类的映射配置文件的<class>
标签中添加属性lazy=false
。
提醒 : 延迟查询因为其代理对象空壳的性质,极大的节约了内存空间,提高了查询效率,所以能用延迟查询就不要用立即查询
1.2 HQL检索
HQL检索是hibernate提供的一种常用的检索方法。需要使用org.hibernate.Query
。需要使用hql语言,其与sql语言的不同在于 实体类名和属性名代替了表名和字段名,且可以省略select关键字,但*不再可用。
/**
* 查询所有记录
* from User //查询所有,可以省略select,但不能用*代替所有
* select u from User u //别名
* from User order by userid // 排序查询
*/
Query query = session.createQuery("select u from User u");
List<User> list = query.list();
for(User user : list){
System.out.println(user.getUsername());
}
/**
* 条件查询
* 两种方式,索引方式中是从0开始的
*/
/*Query query = session.createQuery("from User where username=?");
query.setParameter(0, "赵玉强");*/
Query query = session.createQuery("from User where username=:name");
query.setParameter("name", "赵玉强");
List<User> list = query.list();
for(User user : list){
System.out.println(user.getUsername());
}
/**
* 分页检索
*/
Query query = session.createQuery("from User");
query.setFirstResult(0); //开始位置
query.setMaxResults(2); //每页记录数
List<User> list = query.list();
for(User user : list){
System.out.println(user.getUsername());
}
/**
* 统计查询
* count、sum、avg、max、min
*/
Query query = session.createQuery("select count(*) from User");
Long count = (Long)query.uniqueResult();
System.out.println(count.intValue());
提醒 : 不同版本的hibernate,Query接口或许不同,hibernante5.2版本和是org.hibernate.query.Query,当然方法也会有所不同。
1.3 QBC检索
QBC检索是hibernate提供的常用检索方式,因为其不需要写任何的数据库查询语句。需要用到org.hibernate.Criteria。
/**
* 查询所有
*/
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
/**
* 条件查询
* import org.hibernate.criterion.Restrictions;
*/
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("userage",18));
criteria.add(Restrictions.like("username","%婷"));
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
/**
* 分页检索
*/
Criteria criteria = session.createCriteria(User.class);
criteria.setFirstResult(0); //开始位置
criteria.setMaxResults(2); //每页记录数
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
/**
* 排序检索
* import org.hibernate.criterion.Order;
*/
Criteria criteria = session.createCriteria(User.class);
criteria.addOrder(Order.desc("userid"));
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
/**
* 统计检索
* org.hibernate.criterion.Projections;
*/
Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.rowCount());
Long count = (Long) criteria.uniqueResult();
System.out.println(count.intValue());
/**
* 离线查询(SSH常用)(特例)
* 离线:离线查询对象不是session创建的。
* org.hibernate.criterion.DetachedCriteria
*/
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(User.class);
detachedCriteria.add(Restrictions.eq("userage",18));
List<User> list = detachedCriteria.getExecutableCriteria(session).list();//离线查询对象与session绑定
for (User user : list) {
System.out.println(user);
}
提醒 : 不同版本的hibernate,Criteria接口或许不同,hibernante5.2版本把Criteria融合到了JPA中 (javax.persistence.criteria.CriteriaQuery)
2 多表查询
2.1 对象图导航检索
对象图导航是非常重要的一种多表检索方式。实现步骤非常简单,例如,员工对象自动导航找到员工所属部门的部门对象。 该检索方法都是延迟加载。看下面两种需求实例:
/**
*1. 查询某一部门下的所有员工中
* 延迟加载,默认配置即可
*/
Depart dept = session.get(Depart.class, 2); //立即查询返回部门实体类对象
Set<Staff> stafList = dept.getStaffs(); //延迟加载,返回的集合中的员工实体类都是代理对象(目的是为了节约内存)
for(Staff staf : stafList) {
System.out.println(staf.getStaName()); //真正使用员工实体类,这时才开始真正查询
}
/**
* 查找某一员工对应的部门信息
* 需要使用立即加载,在多的一方(员工)映射配置文件中的<many-to-one>标签中添加属性lazy,值为false
*/
Staff staff = session.get(Staff.class,"ff80818163588ee90163588eecfd0000");//立即查询返回员工实体类对象
Depart dept = staff.getDepart(); //依然是延迟加载,返回的部门实体类对象依然是代理对象。
System.out.println(dept.getDepName()); //开始使用部门实体类对象,这时才开始真正查询
2.2 内链接与迫切内连接
内连接查询,方法返回的每个集合元素都是一个Object数组,Object数组中的每个元素都是一个对象。
/**
* 1. 内连接
*/
Query query = session.createQuery("from Depart d inner join d.staffs");
List<Object[]> list = query.list();
for(Object[] obj : list) {
Depart dep = (Depart)obj[0];
Staff sta = (Staff)obj[1];
for(Staff staf : stafList) {
System.out.println(dept.getDepName()+"->"+staf.getStaName());
}
}
迫切内连接不同于内连接的是: 迫切内连接查询,方法返回的每个集合元素都是一个对象 ,通过该对象查找另一个对象。使用迫切查询,需要在hql中加fetch
/**
* 2. 迫切内连接
*/
Query query = session.createQuery("from Depart d inner join fetch d.staffs");
List<Depart> deptList = query.list();
for(Depart dept : deptList) {
Set<Staff> stafList = dept.getStaffs();
for(Staff staf : stafList) {
System.out.println(dept.getDepName()+"->"+staf.getStaName());
}
}
2.3 左外连接与迫切左外连接
/**
* 3. 左外连接
* 返回的每个集合元素都是一个Object数组,Object数组中的每个元素都是一个对象
*/
Query query = session.createQuery("from Depart d left outer join d.staffs");
List<Object[]> deptList = query.list();
for (Object[] obj : deptList) {
Depart dept = (Depart) obj[0];
Staff staf = (Staff) obj[1];
System.out.println(dept.getDepName()+"->"+staf.getStaName());
}
/**
* 4. 迫切左外连接
* 返回的每个集合元素都是一个对象 ,通过该对象查找另一个对象
*/
Query query = session.createQuery("from Depart d left outer join fetch d.staffs");
List<Depart> deptList = query.list();
for(Depart dept : deptList) {
Set<Staff> stafList = dept.getStaffs();
for(Staff staf : stafList) {
System.out.println(dept.getDepName()+"->"+staf.getStaName());
}
}
2.4 右外连接
/**
* 5. 右外连接
*/
Query query = session.createQuery("from Depart d right outer join d.staffs");
List<Object[]> objList = query.list();
for(Object[] obj : objList) {
Depart dept = (Depart)obj[0];
Staff staf = (Staff) obj[1];
System.out.println(dept.getDepName()+"->"+staf.getStaName());
}
右连接并没有迫切