Hibernate criteria 查询示例

Hibernate提供了三种从数据库检索数据的方法。我们已经讨论了HQL和本地SQL查询。现在我们将讨论我们的第三个选项,即 Hibernate criteria 查询。条件查询API使您可以使用Java构建嵌套的结构化查询表达式,从而提供了编译时语法检查,而这是使用HQL或SQL之类的查询语言无法实现的。

Criteria API还包括示例查询(QBE)功能。这样,您就可以提供示例对象,这些对象包含要检索的属性,而不必逐步说明查询的组件。它还包括投影和汇总方法,其中包括count()。让我们详细探讨它的不同功能。

目录

1. Hibernate criteria 示例
2. Hibernate criteria -使用限制
3. Hibernate criteria -在结果集中分页
4. Hibernate criteria -获得唯一的结果
5. Hibernate criteria -获得不同的结果
6. Hibernate criteria -对查询结果进行排序
7. Hibernate criteria -执行关联(联接)
8. Hibernate criteria -添加投影
9. Hibernate criteria -通过示例查询(QBE)
10.摘要

1. Hibernate criteria 示例

Criteria API允许您以编程方式构建条件查询对象;该org.hibernate.Criteria接口定义了这些对象中的一个的可用方法。Hibernate Session接口包含多个重载createCriteria()方法。

将持久性对象的类或其实体名称传递给createCriteria()方法,然后hibernate将创建一个Criteria对象,当您的应用程序执行条件查询时,该对象将返回持久性对象的类的实例。

条件查询的最简单示例是没有可选参数或限制的条件查询-条件查询将仅返回与该类相对应的每个对象。

Criteria crit = session.createCriteria(Product.class);
List<Product> results = crit.list();

从这个简单的标准示例继续,我们将向我们的标准查询添加约束,以便我们可以缩减结果集。

2. Hibernate criteria –使用限制

使用Criteria API,您可以轻松地在查询中使用限制来有选择地检索对象。例如,您的应用程序只能检索价格超过30元的产品。您可以使用方法将这些限制添加到Criteria对象add()。该add()方法采用org.hibernate.criterion.Criterion代表单个限制的对象。一个条件查询可以有多个限制。

2.1。Restrictions.eq()示例

要检索属性值“ 等于 ”您的限制的对象,请使用eq()on方法Restrictions,如下所示:

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.eq("description","Mouse"));
List<Product> results = crit.list()

上面的查询将搜索所有描述为“鼠标”的产品。

2.2。Restrictions.ne()示例

要检索具有属性值“ not equal to”的对象,请使用ne()on方法Restrictions,如下所示:

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.ne("description","Mouse"));
List<Product> results = crit.list()

上面的查询将搜索所有具有描述的产品,但不包含“ Mouse”。

您不能使用不相等的限制来检索该属性在数据库中具有NULL值的记录(在SQL中,因此在Hibernate中,NULL表示缺少数据,因此无法与数据进行比较)。如果需要检索具有NULL属性的对象,则必须使用isNull()限制。

2.3。Restrictions.like()和Restrictions.ilike()示例

除了搜索完全匹配之外,我们还可以检索具有与给定模式的一部分属性匹配的所有对象。为此,我们需要使用like()ilike()方法创建一个SQL LIKE子句。该ilike()方法不区分大小写。

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.like("name","Mou%",MatchMode.ANYWHERE));
List<Product> results = crit.list();

上面的示例使用一个org.hibernate.criterion.MatchMode对象来指定如何将指定的值与存储的数据进行匹配。该MatchMode对象(类型安全的枚举)有四个不同的比赛:

ANYWHERE:字符串中的
任意位置END:字符串的末尾
EXACT:完全匹配
的字符串START:字符串的开头

2.4。Restrictions.isNull()和Restrictions.isNotNull()示例

isNull()isNotNull()限制允许你做的有(或没有)空的属性值对象的搜索。

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.isNull("name"));
List<Product> results = crit.list();

2.5。Restrictions.gt(),Restrictions.ge(),Restrictions.lt()和Restrictions.le()示例

一些限制对于进行数学比较很有用。大于比较是gt(),大于或等于比较是ge(),小于比较是lt(),小于或等于比较是le()。我们可以使用Java的类型促销来快速检索价格超过25元的所有产品,例如Double

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.gt("price", 25.0));
List<Product> results = crit.list();

2.6。结合两个或更多个条件示例

继续,我们可以开始使用Criteria API进行更复杂的查询。例如,我们可以在逻辑表达式中组合AND和OR限制。当我们向条件查询添加多个约束时,它将被解释为AND,如下所示:

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.lt("price",10.0));
crit.add(Restrictions.ilike("description","mouse", MatchMode.ANYWHERE));
List<Product> results = crit.list();

如果我们要使用两个限制来返回满足两个或两个限制的对象,则需要使用or()Restrictions类上的方法,如下所示:

Criteria crit = session.createCriteria(Product.class);
Criterion priceLessThan = Restrictions.lt("price", 10.0);
Criterion mouse = Restrictions.ilike("description", "mouse", MatchMode.ANYWHERE);
LogicalExpression orExp = Restrictions.or(priceLessThan, mouse);
crit.add(orExp);
List results=crit.list();

我们在此处创建的orExp逻辑表达式将被视为任何其他条件。因此,我们可以对条件添加另一个限制:

Criteria crit = session.createCriteria(Product.class);
Criterion price = Restrictions.gt("price",new Double(25.0));
Criterion name = Restrictions.like("name","Mou%");
LogicalExpression orExp = Restrictions.or(price,name);
crit.add(orExp);
crit.add(Restrictions.ilike("description","blocks%"));
List results = crit.list();

2.7。将析取对象与条件一起使用

如果我们要创建一个具有两个以上不同条件的OR表达式(例如,“ price> 25.0 OR名称,例如Mou%OR描述,而不是blocks%”),则可以使用一个org.hibernate.criterion.Disjunction对象来表示析取。

您可以从类的disjunction()工厂方法获取此对象Restrictions。分离比在代码中构建OR表达式树更方便。要表示具有两个以上条件的AND表达式,您可以使用conjunction()方法,尽管您可以轻松地将其添加到Criteria对象中。与在代码中构建AND表达式树相比,该连接更方便。这是一个使用析取的示例:

Criteria crit = session.createCriteria(Product.class);
Criterion priceLessThan = Restrictions.lt("price", 10.0);
Criterion mouse = Restrictions.ilike("description", "mouse", MatchMode.ANYWHERE);
Criterion browser = Restrictions.ilike("description", "browser", MatchMode.ANYWHERE);
Disjunction disjunction = Restrictions.disjunction();
disjunction.add(priceLessThan);
disjunction.add(mouse);
disjunction.add(browser);
crit.add(disjunction);
List results = crit.list();

2.8。Restrictions.sqlRestriction()示例

sqlRestriction()限制允许您直接在Criteria API中指定SQL。如果您需要使用Hibernate通过Criteria API不支持的SQL子句,这将非常有用。

您的应用程序的代码不需要知道您的类使用的表的名称。使用{alias}表示类的表,如下所示:

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.sqlRestriction("{alias}.description like 'Mou%'"));
List<Product> results = crit.list();

3. Hibernate criteria –分页浏览结果集

标准可以解决的一种常见应用程序模式是通过数据库查询的结果集进行分页。Criteria与Query相同,界面上有两种分页方法:setFirstResult()和和setMaxResults()。该setFirstResult()方法采用一个代表结果集中第一行的整数(从第0行开始)。您可以告诉Hibernate使用该setMaxResults()方法检索固定数目的对象。结合使用这两者,我们可以在Web或Swing应用程序中构造一个分页组件。

Criteria crit = session.createCriteria(Product.class);
crit.setFirstResult(1);
crit.setMaxResults(20);
List<Product> results = crit.list();

如您所见,这使得分页结果集变得容易。您可以增加返回的第一个结果(例如,从1到21,再到41等)以翻页结果集。

4. Hibernate 标准–获得独特的结果

有时您知道您将从给定查询中仅返回零或一个对象。这可能是因为您正在计算汇总,或者是因为您的限制自然会导致唯一的结果。如果要获取单个Object引用而不是List,则uniqueResult()Criteria对象上的方法将返回一个对象或null。如果结果不止一个,则该uniqueResult()方法将引发HibernateException

以下简短示例演示了一个结果集,该结果集将包含多个结果,但该结果集受setMaxResults()方法限制:

Criteria crit = session.createCriteria(Product.class);
Criterion price = Restrictions.gt("price",new Double(25.0));
crit.setMaxResults(1);
Product product = (Product) crit.uniqueResult();

同样,请注意,如果使用此uniqueResult()方法,则需要确保查询仅返回一或零个结果。否则,Hibernate将引发NonUniqueResultException异常。

5. Hibernate 标准–获得不同的结果

如果您想使用条件查询的不同结果,则Hibernate提供了一个针对不同实体的结果转换器org.hibernate.transform.DistinctRootEntityResultTransformer,以确保查询的结果集中没有重复项。不同于使用SQL的SELECT DISTINCT,不同的结果转换器使用它们的默认hashCode()方法比较每个结果,并且仅将具有唯一哈希码的结果添加到结果集中。这可能是也可能不是您从其他等效的SQL DISTINCT查询中得到的结果,因此请小心使用

Criteria crit = session.createCriteria(Product.class);
Criterion price = Restrictions.gt("price",new Double(25.0));
crit.setResultTransformer( DistinctRootEntityResultTransformer.INSTANCE )
List<Product> results = crit.list();

另一个性能说明:比较是在Hibernate的Java代码中完成的,而不是在数据库中完成的,因此非唯一的结果仍将在网络上传输。

6. Hibernate criteria –对查询结果进行排序

使用条件对查询结果进行排序的方式与使用HQL或SQL进行排序的方式几乎相同。Criteria API提供了一个org.hibernate.criterion.Order类,可以根据对象的属性之一,以升序或降序对结果集进行排序。

此示例演示如何使用Order类:

Criteria crit = session.createCriteria(Product.class);
crit.add(Restrictions.gt("price",10.0));
crit.addOrder(Order.desc("price"));
List<Product> results = crit.list();

您可以Order向该Criteria对象添加多个对象。Hibernate会将它们传递给基础SQL查询。您的结果将按第一顺序排序,然后第一排序中的所有相同匹配项将按第二顺序排序,依此类推。在幕后,Hibernate在将属性替换为适当的数据库列名称之后将其传递给SQL ORDER BY子句

7. Hibernate 标准–执行关联(联接)

关联从一对多或多对一进行时有效。首先,我们将演示如何使用一对多关联来获取价格超过25元的供应商。请注意,我们为产品属性创建了一个新的Criteria对象,向我们刚刚创建的产品标准添加了限制,然后从供应商Criteria对象获得结果:

Criteria crit = session.createCriteria(Supplier.class);
Criteria prdCrit = crit.createCriteria("products");
prdCrit.add(Restrictions.gt("price",25.0));
List results = crit.list();

换句话说,我们使用多对一关联从供应商MegaInc获取所有产品:

Criteria crit = session.createCriteria(Product.class);
Criteria suppCrit = crit.createCriteria("supplier");
suppCrit.add(Restrictions.eq("name","Hardware Are We"));
List results = crit.list();

8. Hibernate 标准–添加预测和汇总

您可以将结果集中的结果视为一组行和列,也称为数据投影,而不是使用结果集中的对象。这类似于您将通过JDBC使用SELECT查询中的数据的方式类似。

要使用投影,org.hibernate.criterion.Projection请从org.hibernate.criterion.Projections工厂类中获取所需的对象。该Projections班是类似的Restrictions,因为它提供了一种获取了一些静态工厂方法的类Projection的实例。获取Projection对象后,使用方法将其添加到Criteria对象中setProjection()。当Criteria对象执行,列表中包含的对象引用,可以转换为相应的类型。

8.1。单个聚合(获取行数)

Criteria crit = session.createCriteria(Product.class);
crit.setProjection(Projections.rowCount());
List<Long> results = crit.list();

Projections工厂类提供的其他汇总函数包括:

  1. avg(String propertyName):给出属性值的平均值
  2. count(String propertyName):计算属性发生的次数
  3. countDistinct(String propertyName):计算属性包含的唯一值的数量
  4. max(String propertyName):计算属性值的最大值
  5. min(String propertyName):计算属性值的最小值
  6. sum(String propertyName):计算属性值的总和

8.2。多个集合

我们可以将多个投影应用于给定的Criteria对象。若要添加多个投影,请从projectionList()Projections类的方法中获取一个投影列表。该org.hibernate.criterion.ProjectionList对象具有add()接受Projection对象的方法。您可以将投影列表传递给对象setProjection()上的方法,Criteria因为它ProjectionList实现了Projection接口。

Criteria crit = session.createCriteria(Product.class);
ProjectionList projList = Projections.projectionList();
projList.add(Projections.max("price"));
projList.add(Projections.min("price"));
projList.add(Projections.avg("price"));
projList.add(Projections.countDistinct("description"));
crit.setProjection(projList);
List<object[]> results = crit.list();

8.3。获取选定列

投影的另一个用途是检索单个属性,而不是实体。例如,我们可以仅从产品表中检索名称和描述,而不是将整个对象表示加载到内存中。

Criteria crit = session.createCriteria(Product.class);
ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("name"));
projList.add(Projections.property("description"));
crit.setProjection(projList);
crit.addOrder(Order.asc("price"));
List<object[]> results = crit.list();

9. Hibernate criteria –示例查询(QBE)

在QBE中,您可以部分填充该对象的实例,而不必以编程方式Criteria使用Criterion对象和逻辑表达式构建对象。您可以将此实例用作模板,并让Hibernate根据其值为您构建标准。这可以使您的代码保持整洁,并使您的项目更易于测试。

例如,如果我们有一个用户数据库,则可以构造一个用户对象的实例,设置类型和创建日期的属性值,然后使用CriteriaAPI运行QBE查询。Hibernate将返回一个结果集,其中包含与设置的属性值匹配的所有用户对象。在后台,Hibernate检查Example对象,并构造一个与Example对象的属性相对应的SQL片段。

下面的基本示例搜索与示例Supplier对象上的名称匹配的供应商:

Criteria crit = session.createCriteria(Supplier.class);
Supplier supplier = new Supplier();
supplier.setName("MegaInc");
crit.add(Example.create(supplier));
List results = crit.list();

10.总结

使用Criteria API是开始使用HQL开发的绝佳方法。Hibernate的开发人员提供了一个干净的API,用于为使用Java对象的查询添加限制。尽管HQL不太难学,但是一些开发人员更喜欢Criteria Query API,因为它提供了编译时语法检查-尽管在运行时才能检查列名和其他与模式相关的信息。

saigon has written 1440 articles

Leave a Reply