Hibernate Criteria查询完全指南:实例与最佳实践
Hibernate Criteria 示例教程
欢迎来到Hibernate Criteria示例教程。今天我们将深入研究Hibernate中的Criteria API。
Hibernate Criteria 简介
Hibernate Criteria允许开发者通过特定条件来查询和筛选数据。大多数情况下,我们使用HQL(Hibernate Query Language)来查询数据库并获取结果。然而,HQL并不是执行更新或删除操作的首选方式,因为这样我们需要注意表之间的任何关联。Hibernate Criteria API提供了一种面向对象的方法来查询数据库并获取结果。我们无法使用Hibernate的Criteria来运行更新或删除查询或任何DDL语句。Hibernate Criteria查询仅用于使用面向对象的方法从数据库中获取结果。在本教程中,我将使用与HQL示例相同的设置,向您展示如何在Hibernate中使用Criteria来查询数据库。
Hibernate Criteria API的常见用法
- Hibernate Criteria API 提供了可以用于聚合函数(如sum()、min()、max()等)的投影功能。
- Hibernate Criteria API 可以与 ProjectionList 一起使用,只获取选择的列。
- Hibernate 的 Criteria 可以用于连接查询,通过连接多个表,Hibernate Criteria 的有用方法有 createAlias()、setFetchMode() 和 setProjection()。
- Hibernate API 的 Criteria 可以用于带有条件的结果获取,有用的方法是 add(),我们可以在其中添加限制条件。
- Hibernate Criteria API 提供了 addOrder() 方法,用于对结果进行排序。
以下类展示了Hibernate Criteria API的不同用法,其中大部分是HQL教程中示例的替代品。
package com.Olivia.hibernate.main;
import java.util.Arrays;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import com.Olivia.hibernate.model.Employee;
import com.Olivia.hibernate.util.HibernateUtil;
public class HibernateCriteriaExamples {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
// 准备工作
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
// 获取所有员工
Criteria criteria = session.createCriteria(Employee.class);
List<Employee> empList = criteria.list();
for(Employee emp : empList){
System.out.println("ID="+emp.getId()+", 邮编="+emp.getAddress().getZipcode());
}
// 根据ID获取,创建新的Criteria以移除所有设置
criteria = session.createCriteria(Employee.class)
.add(Restrictions.eq("id", new Long(3)));
Employee emp = (Employee) criteria.uniqueResult();
System.out.println("姓名=" + emp.getName() + ", 城市="
+ emp.getAddress().getCity());
// 分页示例
empList = session.createCriteria(Employee.class)
.addOrder(Order.desc("id"))
.setFirstResult(0)
.setMaxResults(2)
.list();
for(Employee emp4 : empList){
System.out.println("分页员工::"+emp4.getId()+","+emp4.getAddress().getCity());
}
// 模糊查询示例
empList = session.createCriteria(Employee.class)
.add(Restrictions.like("name", "%i%"))
.list();
for(Employee emp4 : empList){
System.out.println("姓名中包含'i'的员工::"+emp4.getName()+","+emp4.getAddress().getCity());
}
// 投影示例
long count = (Long) session.createCriteria(Employee.class)
.setProjection(Projections.rowCount())
.add(Restrictions.like("name", "%i%"))
.uniqueResult();
System.out.println("姓名中包含'i'的员工数量="+count);
// 使用投影进行sum、min、max等聚合函数
double sumSalary = (Double) session.createCriteria(Employee.class)
.setProjection(Projections.sum("salary"))
.uniqueResult();
System.out.println("薪资总和="+sumSalary);
// 连接查询示例,用于选择少数列
criteria = session.createCriteria(Employee.class, "employee");
criteria.setFetchMode("employee.address", FetchMode.JOIN);
criteria.createAlias("employee.address", "address"); // 默认为内连接
ProjectionList columns = Projections.projectionList()
.add(Projections.property("name"))
.add(Projections.property("address.city"));
criteria.setProjection(columns);
List<Object[]> list = criteria.list();
for(Object[] arr : list){
System.out.println(Arrays.toString(arr));
}
// 回滚事务以避免弄乱测试数据
tx.commit();
// 关闭Hibernate资源
sessionFactory.close();
}
}
当我们执行以上Hibernate Criteria示例程序时,我们得到以下输出:
5月26日 2014 6:53:32 下午 org.hibernate.annotations.common.reflection.java.JavaReflectionManager <clinit>
信息: HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
5月26日 2014 6:53:32 下午 org.hibernate.Version logVersion
信息: HHH000412: Hibernate Core {4.3.5.Final}
5月26日 2014 6:53:32 下午 org.hibernate.cfg.Environment <clinit>
信息: HHH000206: 未找到hibernate.properties文件
5月26日 2014 6:53:32 下午 org.hibernate.cfg.Environment buildBytecodeProvider
信息: HHH000021: 字节码提供者名称: javassist
5月26日 2014 6:53:32 下午 org.hibernate.cfg.Configuration configure
信息: HHH000043: 从资源配置: hibernate.cfg.xml
5月26日 2014 6:53:32 下午 org.hibernate.cfg.Configuration getConfigurationInputStream
信息: HHH000040: 配置资源: hibernate.cfg.xml
5月26日 2014 6:53:32 下午 org.hibernate.internal.util.xml.DTDEntityResolver resolveEntity
警告: HHH000223: 检测到过时的hibernate命名空间 https://hibernate.sourceforge.net/。请使用命名空间 https://www.hibernate.org/dtd/。参考Hibernate 3.6迁移指南!
5月26日 2014 6:53:32 下午 org.hibernate.cfg.Configuration doConfigure
信息: HHH000041: 配置的SessionFactory: null
Hibernate配置已加载
Hibernate服务注册已创建
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
警告: HHH000402: 使用Hibernate内置连接池(不适用于生产环境!)
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
信息: HHH000401: 使用驱动程序 [com.mysql.jdbc.Driver] 在URL [jdbc:mysql://localhost/TestDB]
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
信息: HHH000046: 连接属性: {user=scdev, password=****}
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
信息: HHH000006: 自动提交模式: false
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl configure
信息: HHH000115: Hibernate连接池大小: 20 (min=1)
5月26日 2014 6:53:32 下午 org.hibernate.dialect.Dialect <init>
信息: HHH000400: 使用方言: org.hibernate.dialect.MySQLDialect
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.internal.LobCreatorBuilder useContextualLobCreation
信息: HHH000423: 禁用上下文LOB创建,因为JDBC驱动报告的JDBC版本[3]小于4
5月26日 2014 6:53:32 下午 org.hibernate.engine.transaction.internal.TransactionFactoryInitiator initiateService
信息: HHH000399: 使用默认事务策略(直接JDBC事务)
5月26日 2014 6:53:32 下午 org.hibernate.hql.internal.ast.ASTQueryTranslatorFactory <init>
信息: HHH000397: 使用ASTQueryTranslatorFactory
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id
ID=1, 邮编=95129
ID=2, 邮编=95051
ID=3, 邮编=560100
ID=4, 邮编=100100
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id where this_.emp_id=?
姓名=Lisa, 城市=Bangalore
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id order by this_.emp_id desc limit ?
分页员工::4,New Delhi
分页员工::3,Bangalore
Hibernate: select this_.emp_id as emp_id1_1_1_, this_.emp_name as emp_name2_1_1_, this_.emp_salary as emp_sala3_1_1_, address2_.emp_id as emp_id1_0_0_, address2_.address_line1 as address_2_0_0_, address2_.city as city3_0_0_, address2_.zipcode as zipcode4_0_0_ from EMPLOYEE this_ left outer join ADDRESS address2_ on this_.emp_id=address2_.emp_id where this_.emp_name like ?
姓名中包含'i'的员工::David,Santa Clara
姓名中包含'i'的员工::Lisa,Bangalore
Hibernate: select count(*) as y0_ from EMPLOYEE this_ where this_.emp_name like ?
姓名中包含'i'的员工数量=2
Hibernate: select sum(this_.emp_salary) as y0_ from EMPLOYEE this_
薪资总和=1000.0
Hibernate: select this_.emp_name as y0_, address1_.city as y1_ from EMPLOYEE this_ inner join ADDRESS address1_ on this_.emp_id=address1_.emp_id
[Pankaj, San Jose]
[David, Santa Clara]
[Lisa, Bangalore]
[Jack, New Delhi]
5月26日 2014 6:53:32 下午 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop
信息: HHH000030: 清理连接池 [jdbc:mysql://localhost/TestDB]
由于我正在使用HQL示例项目,你需要导入它并添加这个类使其能够工作。注意输出中执行的Hibernate查询,这样你就可以优化查询并获得你所需要的结果。以上就是关于Hibernate中Criteria的简要总结。