Hibernate查询方式
- (1)对象导航查询:根据id查询某个班级,再查询这个班级里面的所有学生
- (2)OID查询:根据id查询某一条记录,返回对象
- (3)HQL查询:利用Query对象,写HQL语句实现查询
- (4)QBC查询:利用Criteria对象实现查询
- (5)本地sql查询:利用SQLQuery对象,使用普通sql实现查询
对象导航查询
对象导航查询是根据已经加载的对象,查询到它的关联对象。
需求:查询某个班级中的所有学生,使用对象导航查询
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Classes classes=session.get(Classes.class, 4);
Set<Student> s=classes.getcStudents();
for(Student student:s){
System.out.println(student);
}
transaction.commit();
session.close();
sessionFactory.close();
}
OID查询
OID查询主要指用session的get方法加载某条记录对应的对象
需求:根据id属性查询某个班级
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Classes classes=session.get(Classes.class, 4);
transaction.commit();
session.close();
sessionFactory.close();
}
HQL查询
- HQL(Hibernate Query Language)是面向对象的查询语言,它和sql查询语言很相似
- HQL与SQL的区别:SQL操作数据表和字段,HQL操作实体类和属性
- 使用HQL查询操作步骤:第一步:创建Query对象,写HQL语句;第二步:调用Query对象里面的方法得到结果
常用的HQL语句:
- 查询所有:from 实体类名称
- 条件查询:from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?
from 实体类名称 where 实体类属性名称 like ?
- 排序查询:from 实体类名称 order by 实体类属性名称 asc/desc
(1)查询所有
需求:查询所有学生记录
步骤:第一步:创建Query对象,写HQL语句;第二步:调用Query对象中的list方法,得到结果
语句:from 实体类名称
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Query对象
Query query=session.createQuery("from Student");
//调用list方法得到结果
List<Student> list=query.list();
//通过for循环遍历结果集
for(Student stu : list){
System.out.println(stu);
}
transaction.commit();
session.close();
sessionFactory.close();
}
(2)条件查询
语法:from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?(条件查询)
from 实体类名称 where 实体类属性名称 like ?(模糊查询)
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Query对象
//select * from Student where sid=? and sname=?;
Query query = session.createQuery("from Student s where s.sid=? and s.sname=? ");
//设置条件值,第一个参数表示位置(从0开始),第二个参数表示具体参数值
//按位置绑定参数
query.setParameter(0, 3);
query.setParameter(1, "张三");
//调用query对象中的list方法
List<Student> list=query.list();
for(Student s:list){
System.out.println(s);
}
transaction.commit();
session.close();
sessionFactory.close();
}
模糊查询:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Query对象
Query query=session.createQuery("from Student s where s.sname like ?");
//设置占位符的值
query.setParameter(0, "%李%");
//调用query对象的list方法
List<Student> list=query.list();
for(Student s:list){
System.out.println(s.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(3)排序查询
语法:from 实体类名称 order by 实体类属性名称 asc/desc
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Query query=session.createQuery("from Student s order by s.sid desc ");
List<Student> list=query.list();
for(Student student : list){
System.out.println(student.getSid()+" : "+student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(4)分页查询
- 分页功能是很常见的功能,如果结果集数据量很大,比如几万行数据,放在一个页面显示的话数据量太大,不如分页显示,每次显示100条。
- Mysql实现分页:使用关键字limit
- 在HQL中实现分页:hibernate中的Query对象封装了setFirstResult和setMaxResults两个方法实现分页操作
效果图:
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Query query=session.createQuery("from Student");
//设置分页数据开始位置
query.setFirstResult(0);
//设置分页数据每页记录数
query.setMaxResults(2);
List<Student> list=query.list();
for(Student student:list){
System.out.println(student.getSid()+" + "+student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
(5)投影查询
投影查询:查询部分字段的值
select sname from student;
语法:select 实体类属性名称1,实体类属性名称2 from 实体类名称
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Query query=session.createQuery("select sname from Student");
List<Object> list=query.list();
for(Object obj:list){
System.out.println(obj);
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(6)聚集函数使用
常用的聚集函数:count,sum,avg,max,min
需求:查询数据表中的记录数
语法:select count(*) from 实体类名称
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Query query=session.createQuery("select count(*) from Student");
Object obj=query.uniqueResult();
System.out.println(obj);
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
QBC查询
- QBC(Query By Criteria)是Hibernate提供的另一种查询对象的方式
- 使用QBC查询,不需要使用语句,直接使用方法实现
- QBC查询,使用Criteria对象,操作的是实体类和属性
- 使用步骤:第一步:创建Criteria对象;第二步:调用相关方法得到结果
(1)查询所有
需求:查询所有学生记录
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
Criteria criteria=session.createCriteria(Student.class);
List<Student> list=criteria.list();
for(Student s:list){
System.out.println(s.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
(2)条件查询
HQL的条件查询可以在HQL语句中设置条件值,但是QBC使用封装的方法设置条件值
QBC查询使用Restrictions对象编写查询条件,在Restictions类中提供了大量的静态方法来创建查询条件,如下所示:
需求:根据学id和姓名进行查询
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Criteria对象
Criteria criteria=session.createCriteria(Student.class);
//使用Criteria对象中的add方法设置条件值
criteria.add(Restrictions.eq("sid", 3));
criteria.add(Restrictions.eq("sname","王富贵"));
//调用list方法,得到结果
List<Student> list=criteria.list();
for(Student student:list){
System.out.println(student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
模糊查询:
需求:查询姓名中有“李”的所有学生
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Criteria对象
Criteria criteria=session.createCriteria(Student.class);
//使用Criteria对象中的add方法设置条件值
criteria.add(Restrictions.like("sname", "%李%"));
//调用list方法,得到结果
List<Student> list=criteria.list();
for(Student student:list){
System.out.println(student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(3)排序查询
需求:按照学生id,倒序查询所有学生
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Criteria对象
Criteria criteria=session.createCriteria(Student.class);
//设置对哪个属性进行排序,并设置排序方式
criteria.addOrder(Order.desc("sid"));
//调用list方法,得到结果
List<Student> list=criteria.list();
for(Student student:list){
System.out.println(student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(4)分页查询
在QBC中实现分页:hibernate中的Criteria对象封装了setFirstResult和setMaxResults两个方法实现分页操作
需求:分页查询,从0开始,每页显示两个。开始位置计算公式: (当前页-1)*每页记录数
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Criteria对象
Criteria criteria=session.createCriteria(Student.class);
//设置开始位置
criteria.setFirstResult(0);
//设置每页显示记录数
criteria.setMaxResults(2);
//调用list方法,得到结果
List<Student> list=criteria.list();
for(Student student:list){
System.out.println(student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(5)统计查询
需求:统计学生表中的记录数
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
//创建Criteria对象
Criteria criteria=session.createCriteria(Student.class);
//设置操作(设置统计功能)
criteria.setProjection(Projections.rowCount());
//调用uniqueResult方法得到结果
Object object=criteria.uniqueResult();
System.out.println(object);
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
(6)离线查询
- 离线查询使用DetachedCriteria对象,它可以脱离session来使用。而Criteria对象必须由session对象来创建,即必须现有session才可以生成Criteria对象,而DetachedCriteria对象可以在其他层对条件进行封装。
- 在以后的SSH整合中,会经常使用DetachedCriteria对象,其主要优点是做一些比较复杂的条件查询时,往往会在web层向service层传递很多参数,业务层也会将这些参数传递给dao层,最后在dao层中拼接SQL完成查询。有了离线查询以后,可以直接在web层将数据封装好,传递到service层,再传递到dao层完成查询。
实现:
public void testDemo(){
Configuration cfg=new Configuration();
cfg.configure();
SessionFactory sessionFactory=cfg.buildSessionFactory();
Session session=sessionFactory.openSession();
Transaction transaction=session.beginTransaction();
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Student.class);
Criteria criteria=detachedCriteria.getExecutableCriteria(session);
List<Student> list=criteria.list();
for(Student student : list){
System.out.println(student.getSname());
}
transaction.commit();
session.close();
sessionFactory.close();
}
结果:
HQL多表查询
(1)Mysql中多表查询
内连接
左外连接
右外连接
参考:https://blog.csdn.net/plg17/article/details/78758593
(2)HQL实现多表查询
HQL多表查询:
- 内连接
- 左外连接
- 右外连接
- 迫切内连接
- 迫切左外连接
HQL内连接
1 内连接查询hql语句写法:以客户和联系人为例
(1)from Customer c inner join c.setLinkMan
返回list,list里面每部分是数组形式
2 演示迫切内连接
(1)迫切内连接和内连接底层实现一样的
(2)区别:使用内连接返回list中每部分是数组,迫切内连接返回list每部分是对象
(3)hql语句写法
- from Customer c inner join fetch c.setLinkMan
HQL左外连接
1 左外连接hql语句:
(1)from Customer c left outer join c.setLinkMan
(2)迫切左外连接from Customer c left outer join fetch c.setLinkMan
2 左外连接返回list中每部分是数组,迫切左外连接返回list每部分是对象
1 右外连接hql语句:
(1)from Customer c right outer join c.setLinkMan
Hibernate检索策略
(1)hibernate检索策略分为两类:
立即查询:根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
结果:
延迟查询:根据id查询,调用load方法,调用load方法不会马上发送语句查询数据,只有得到对象里面的其他值的时候才会发送语句查询数据库
结果:
(2)延迟查询分为两类:
类级别延迟:根据id查询返回实体类对象,调用load方法,不会马上发送语句。
结果:
关联级别延迟:查询某个班级,再查询这个班级中的所有学生。查询这个班级中的所有学生是否需要延迟,这个过程称为关联级别延迟。
结果:
关联级别延迟操作
(1)在映射文件中进行配置实现
根据班级得到所有学生,在班级映射文件中进行配置
(2)在set标签上使用属性
fetch:值select(默认使用)
lazy:值
- --true:延迟(默认)
- --false:不延迟
- --extra:极其延迟
实现:lazy属性值为true,即开启延迟
实现:lazy属性值为false,即关闭延迟
调用get方法之后,直接发送两条sql语句。
实现:lazy属性值为extra,极其延迟/极其懒惰
要什么值给什么值(查询set集合数量,只查询count)
Hibernate批量抓取
需求:查询所有的班级,返回list集合,遍历list集合,得到每个班级,得到每个班级的所有学生
实现:
问题:上面操作代码,发送多条sql语句,性能不高
解决:批量抓取
在班级的映射文件中,set标签里配置batch-size属性,值越大,发送语句越少。