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的常见用法

  1. Hibernate Criteria API 提供了可以用于聚合函数(如sum()、min()、max()等)的投影功能。
  2. Hibernate Criteria API 可以与 ProjectionList 一起使用,只获取选择的列。
  3. Hibernate 的 Criteria 可以用于连接查询,通过连接多个表,Hibernate Criteria 的有用方法有 createAlias()、setFetchMode() 和 setProjection()。
  4. Hibernate API 的 Criteria 可以用于带有条件的结果获取,有用的方法是 add(),我们可以在其中添加限制条件。
  5. 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的简要总结。

bannerAds