20. Hibernate 中的 Criteria 查询

1. 前言

今天给大家介绍一个绝对纯正的 OOP 查询方案:Criteria 查询。通过本节课程的内容,你将了解到:

  • 什么是 Criteria 查询
  • Criteria 实现复杂查询;

2. Criteria 查询

什么是 Criteria 查询?

Criteria 查询从字面翻译就是标准查询。所谓 标准查询,指的是 HIbernate 提供了纯正的 OOP API 查询方案。不像 HQL 还掺杂了一些 SQL 层面的内容。

来一个查询需求:查询所有的学生。

想必这学生会很生气,总是被搬来搬去的。

上实例之前,先认识 Hibernate 兄弟会中的一名新成员:Criteria

在使用 Criteria 查询之前,必须先创建 Criteria 对象:

Criteria cr = session.createCriteria(Student.class);
List<Student> stus = cr.list();

是不是很 OOP。使用 HQL 时,会有一种时空穿越的感觉 ,OOP 和 SQL 语法交替出现,很容易犯晕。使用 Criteria 进行查询时则不会。

而且,Criteria 不是一个人在战斗,它也有属于自己的兄弟会,为开发者提供了更强有力的支持。

先介绍一下它的几个兄弟,并且它们的作用已经从字面告诉了你。

  • Criterion: 这位兄弟长得好生面熟,其实它就 Criteria 的单数存在形式;
  • Oder: 提供排序功能;
  • Restrictions: 限制、约束的意思,和 SQL 中的 where 关键字的作用是一样。所以,它提供了很多类似于运算符的方法,可以对查询数据进行过滤。

Criteria 面子上很 OOP ,但是无论你怎么逃,都是在 SQL 的手掌心,也就是说 Criteria 查询最终还是会被 Hibernate 转译成 SQL 语句。

只要是使用关系型数据库,SQL 就是逃不掉的宿命。只是直接、间接使用的区别。

所以,Criteria 查询中总会找到 SQL 的影子。

2.1 基础查询

为了更好地理解它们,来一个实例:查询姓名叫 “Hibernate” 的学生。

Criteria criteria = session.createCriteria(Student.class);
Criterion criterion = Restrictions.eq("stuName", "Hibernate");
criteria.add(criterion);
Student student = (Student) criteria.uniqueResult();
System.out.println(student);

Criteria 查询封装了关系型数据库的概念,所以,一定要注意,使用方法进行数据过滤时,都是属性进行比较。

确认查询出来的数据只有一条记录时,可以使用 uniqueResult() 方法。条件查询的关键是了解 Restrictions,它所提供的很多类似于逻辑运算符的方法:

  • Restrictions.eq(): 相当于 =;
  • Restrictions.not(Exprission.eq()) : 相当于 <>;
  • Restrictions.le(): 相当于 <=;
  • Restrictions.gt(): 相当于 >;
  • Restrictions.ge(): 相当于 >=;
  • Restrictions.lt(): 相当于 <;
  • Restrictions.isnull(): 相当于 is null;
  • Restrictions.isNotNull(): 相当于 is not null ;
  • Restrictions.like(): 相当于 like;
  • Restrictions.and(): 相当于 and;
  • Restrictions.conjunction(): 相当于 and;
  • Restrictions.or(): 相当于 or;
  • Restrictions.disjunction() : 相当于 or;
  • Restrictions.not(): 相当于 not;
  • Restrictions.in(): 相当于 in;
  • Restrictions.not(Restrictions.in()): 相当于 not in;
  • Restrictions.between(): 相当于 between x and y;
  • Restrictions.not(Restrictions…between()) : 相当于 not between x and y。

如上方法,几乎涵盖了所有 SQL 条件运算符,任意组合上面方法,没有查询不出来的结果。

如查询学生编号是 1 或 2 或 4 的学生。
使用 SQL,则是:

select * from student where stuId in (1,2,4)

使用 Criteria 查询,则如下所示:

Criterion criterion = Restrictions.in("stuId",new Integer[] {1,2,4} );
criteria.add(criterion);

如查询学生编号大于 2 且班级编号为 1 的学生。

使用 SQL:

select * from student where stuId>2 and classRommId=1

如果使用 Criteria 查询,则先构建两个约束对象:

Criterion criterion = Restrictions.gt("stuId", 2);
Criterion criterion1 = Restrictions.eqOrIsNull("classRoom.classRoomId", 1);

再把这两个约束作为参数,构建一条联合约束:

LogicalExpression logicalExpression = Restrictions.and(criterion, criterion1);
criteria.add(logicalExpression);

LogicalExpression API 用来表示一个逻辑表达式。是 Criterion 的子类。

比较原生 SQL 和 Criteria 查询,会发现原生 SQL 语句要简单很多,使用 Criteria 查询需要掌握很多 API,而且代码量也比较大,这也可能是 Criteria 查询得不到普及的原因吧。

但是,Hibernate 既然推出了这种查询方案,想必也有它的考虑。比如说,创建动态查询语句,这点原生 SQL 或 HQL 都没有 Criteria 好。

还是那句话,存在就是合理的。

如果,你对原生 SQL 有情怀,Criteria 查询中也是可以用的。

criteria.add( Restrictions.sqlRestriction("stuId>2 and clasRoomId=1"));

注意,不要在 Sql 片段中使用 where 关键字。既然是原生 SQL,所以语句中是字段概念,而不是属性概念

前面讲解 HQL 时,提到了分页查询。Criteria 一样可以实现分页查询,和 HQL 中分页方法一样:

Criteria criteria = session.createCriteria(Student.class);
criteria.setFirstResult(1);
criteria.setMaxResults(5);
List results = criteria.list();

2.2 高级查询

排序查询使用 order API 实现:

criteria.addOrder(Order.desc("stuId"));
criteria.addOrder(Order.asc("stuName"));

一样,可以多字段排序。

使用聚合函数:聚合函数的功能封装在 projections API 中:

criteria.setProjection(Projections.rowCount());
criteria.setProjection(Projections.avg("stuId"));
criteria.setProjection(Projections.max("stuId"));
criteria.setProjection(Projections.min("stuId"));
criteria.setProjection(Projections.sum("stuId"));

Criteria 也能实现关联查询:

Criteria criteria = session.createCriteria(Student.class);
criteria.add(Restrictions.like("stuName", "Hibernate%"));
Criteria criteria01 = criteria.createCriteria("classRoom");
criteria01.add(Restrictions.like("classRoomName", "c19%"));
List<Student> students = criteria.list();

可以把一个 Criteria 实例看成对一张表的查询,如果需要关联多张表,则可以通过一个 Criteria 再创建一个 Criteria 对象。

Hibernate 为 Criteria 查询提供各种各样的 API,适应于任何查询需求,相比较使用的已经很普遍的 SQL 查询,Criteria 查询充满了鸡肋的味道。但对于动态查询需求,Criteria 查询的优势又很明显。

3. 原生 SQL 查询

Hibernate 支持原生 SQL 查询,对于熟悉并钟情于 SQL 语句的开发者来讲,是一个很大的福音。
实例:

String sql="select * from student";
SQLQuery sqlQuery= session.createSQLQuery(sql);

Hibernate 提供了一个与原生 SQL 有关的 SQLQuery 对象。SQLQuery 是 Query 的子类,可适应不同的原生 SQL 语句查询。

4. 小结

本节课和大家聊到了 Criteria 查询,HQL 查询,原生 SQL 查询。原生 SQL 查询无所不能,HQL 查询是面向对象的 SQL ,具有混血身份。据说,混血的总是很美,也是建议大家选择的一种查询方案。

Criteria 查询是 Hibernate 提供的一种纯面向对象的解决方案,但是,为了构建一条 SQL 语句需要写许多代码,其应用领域会相对较窄。

本节课给大家介绍 Criteria 的目的,一是扩展学生的学习范围,如果需要使用动态查询,Criteria 则有着无可比拟的优越感。

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红薯不甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值