Hibernate③单表和多表的查询方式

更多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());
}

右连接并没有迫切

猜你喜欢

转载自blog.csdn.net/g425680992/article/details/80369902