hibernate 检索方式

概述

  • Hibernate 提供了下面几种检索对象的方式

    • 导航对象图检索方式: 依据已经载入的对象导航到其它对象
    • OID 检索方式: 依照对象的 OID 来检索对象
    • HQL 检索方式: 使用面向对象的 HQL 查询语言
    • QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这样的 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口.
    • 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句

HQL 检索方式

HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有例如以下功能:

  • 在查询语句中设定各种查询条件
  • 支持投影查询, 即仅检索出对象的部分属性
  • 支持分页查询
  • 支持连接查询
  • 支持分组查询, 同意使用 HAVING 和 GROUP BY keyword
  • 提供内置聚集函数, 如 sum(), min() 和 max()
  • 支持子查询
  • 支持动态绑定參数

HQL 检索方式包含下面步骤:

  • 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中能够包括命名參数
  • 动态绑定參数
  • 调用 Query 相关方法运行查询语句

Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型

HQL vs SQL:

  • HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后依据对象-关系映射文件里的映射信息, 把 HQL 查询语句翻译成对应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性
  • SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段.

绑定參数:

  • Hibernate 的參数绑定机制依赖于 JDBC API 中的 PreparedStatement 的提前定义 SQL 语句功能.
  • HQL 的參数绑定由两种形式:
    • 按參数名字绑定: 在 HQL 查询语句中定义命名參数, 命名參数以 “:” 开头.
    • 按參数位置绑定: 在 HQL 查询语句中用 “?

      ” 来定义參数位置

  • 相关方法:
    • setEntity(): 把參数与一个持久化类绑定
    • setParameter(): 绑定随意类型的參数. 该方法的第三个參数显式指定 Hibernate 映射类型

HQL 採用 ORDER BY keyword对查询结果排序

分页查询:

  • setFirstResult(int firstResult):
    设定从哪一个对象開始检索, 參数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象開始检索
  • setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 在默认情况下, Query 和 Criteria 接口检索出查询结果中全部的对象

在映射文件里定义命名查询语句

  • Hibernate 同意在映射文件里定义字符串形式的查询语句.
  • <query> 元素用于定义一个 HQL 查询语句, 它和 <class> 元素并列.
  • 在程序中通过 Session 的 getNamedQuery() 方法获取查询语句相应的 Query 对象.

投影查询

  • 投影查询: 查询结果仅包括实体的部分属性.通过 SELECT keyword实现.
  • Query 的list()方法返回的集合中包括的是数组类型的元素,每一个对象数组代表查询结果的一条记录
  • 能够在持久化类中定义一个对象的构造器来包装投影查询返回的记录,使程序代码能全然运用面向对象的语义来訪问查询结果集. 
  • 能够通过 DISTINCT keyword来保证查询结果不会返回反复元素

报表查询

  • 报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BYkeyword对数据分组, 用 HAVING
    keyword对分组数据设定约束条件.
  • 在 HQL 查询语句中能够调用下面聚集函数

    count()

    min()

    max()

    sum()

    avg()

HQL (迫切)左外连接

  • 迫切左外连接:

    • LEFT JOIN FETCH keyword表示迫切左外连接检索策略
    • list() 方法返回的集合中存放实体对象的引用, 每一个 Department 对象关联的 Employee 集合都被初始化, 存放全部关联的 Employee 的实体对象.
    • 查询结果中可能会包括反复元素, 能够通过一个 HashSet 来过滤反复元素
  • 左外连接:
    • LEFT JOIN keyword表示左外连接查询.
    • list() 方法返回的集合中存放的是对象数组类型
    • –依据配置文件来决定 Employee集合的检索策略. 
    • 假设希望 list() 方法返回的集合中仅包括 Department 对象, 能够在HQL 查询语句中使用 SELECT keyword

HQL (迫切)内连接

  • 迫切内连接:

    • INNER JOIN FETCH keyword表示迫切内连接, 也能够省略 INNER keyword
    • list() 方法返回的集合中存放 Department 对象的引用, 每一个 Department 对象的 Employee 集合都被初始化, 存放全部关联的 Employee 对象
  • 内连接:
    • INNER JOIN keyword表示内连接, 也能够省略 INNER keyword
    • list() 方法的集合中存放的每一个元素相应查询结果的一条记录, 每一个元素都是对象数组类型
    • 假设希望 list() 方法的返回的集合仅包括 Department 对象, 能够在 HQL 查询语句中使用 SELECT keyword

关联级别执行时的检索策略

  • 假设在 HQL 中没有显式指定检索策略, 将使用映射文件配置的检索策略.
  • HQL 会忽略映射文件里设置的迫切左外连接检索策略,
    假设希望 HQL 採用迫切左外连接策略, 就必须在 HQL 查询语句中显式的指定它
  • 若在 HQL 代码中显式指定了检索策略, 就会覆盖映射文件里配置的检索策略

QBC 检索和本地 SQL 检索

  • QBC 查询就是通过使用 Hibernate 提供的 Query By Criteria API 来查询对象,这样的 API 封装了 SQL 语句的动态拼装。对查询提供了更加面向对象的功能接口
  • 本地SQL查询来完好HQL不能涵盖全部的查询特性

实例具体解释:

Department.java

package com.atguigu.hibernate.entities;

import java.util.HashSet;
import java.util.Set;

public class Department {

	private Integer id;
	private String name;

	private Set<Employee> emps = new HashSet<>();

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set<Employee> getEmps() {
		return emps;
	}

	public void setEmps(Set<Employee> emps) {
		this.emps = emps;
	}

	@Override
	public String toString() {
		return "Department [id=" + id + "]";
	}

}

Department.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="com.atguigu.hibernate.entities.Department" table="GG_DEPARTMENT">

        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>

        <set name="emps" table="GG_EMPLOYEE" inverse="true" lazy="true">
            <key>
                <column name="DEPT_ID" />
            </key>
            <one-to-many class="com.atguigu.hibernate.entities.Employee" />
        </set>

    </class>
</hibernate-mapping>

Employee.java

package com.atguigu.hibernate.entities;

public class Employee {

	private Integer id;
	private String name;
	private float salary;
	private String email;

	private Department dept;

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public float getSalary() {
		return salary;
	}

	public void setSalary(float salary) {
		this.salary = salary;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Department getDept() {
		return dept;
	}

	public void setDept(Department dept) {
		this.dept = dept;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + "]";
	}

	public Employee(String email, float salary, Department dept) {
		super();
		this.salary = salary;
		this.email = email;
		this.dept = dept;
	}

	public Employee() {
		// TODO Auto-generated constructor stub
	}

}

Employee.hbm.xml

<?

xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

    <class name="com.atguigu.hibernate.entities.Employee" table="GG_EMPLOYEE">

    	<!--
    	<cache usage="read-write"/>
    	-->

        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>

        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>

        <property name="salary" type="float">
            <column name="SALARY" />
        </property>

        <property name="email" type="java.lang.String">
            <column name="EMAIL" />
        </property>

        <many-to-one name="dept" class="com.atguigu.hibernate.entities.Department">
            <column name="DEPT_ID" />
        </many-to-one>

    </class>

    <query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal]]></query>

</hibernate-mapping>
package com.atguigu.hibernate.test;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.jdbc.Work;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.atguigu.hibernate.dao.DepartmentDao;
import com.atguigu.hibernate.entities.Department;
import com.atguigu.hibernate.entities.Employee;
import com.atguigu.hibernate.hibernate.HibernateUtils;

public class HibernateTest {

	private SessionFactory sessionFactory;
	private Session session;
	private Transaction transaction;

	@Before
	public void init(){
		Configuration configuration = new Configuration().configure();
		ServiceRegistry serviceRegistry =
				new ServiceRegistryBuilder().applySettings(configuration.getProperties())
				                            .buildServiceRegistry();
		sessionFactory = configuration.buildSessionFactory(serviceRegistry);

		session = sessionFactory.openSession();
		transaction = session.beginTransaction();
	}

	@After
	public void destroy(){
		transaction.commit();
		session.close();
		sessionFactory.close();
	}

	@Test
	public void testBatch(){
		session.doWork(new Work() {
			@Override
			public void execute(Connection connection) throws SQLException {
				//通过 JDBC 原生的 API 进行操作, 效率最高, 速度最快!
			}
		});
	}

	@Test
	public void testHQLUpdate(){
		String hql = "DELETE FROM Department d WHERE d.id = :id";

		session.createQuery(hql).setInteger("id", 280)
		                        .executeUpdate();
	}

	@Test
	public void testNativeSQL(){
		String sql = "INSERT INTO gg_department VALUES(?

, ?)";
		Query query = session.createSQLQuery(sql);

		query.setInteger(0, 280)
		     .setString(1, "ATGUIGU")
		     .executeUpdate();
	}

	@Test
	public void testQBC4(){
		Criteria criteria = session.createCriteria(Employee.class);

		//1. 加入排序
		criteria.addOrder(Order.asc("salary"));
		criteria.addOrder(Order.desc("email"));

		//2. 加入翻页方法
		int pageSize = 5;
		int pageNo = 3;
		criteria.setFirstResult((pageNo - 1) * pageSize)
		        .setMaxResults(pageSize)
		        .list();
	}

	@Test
	public void testQBC3(){
		Criteria criteria = session.createCriteria(Employee.class);

		//统计查询: 使用 Projection 来表示: 能够由 Projections 的静态方法得到
		criteria.setProjection(Projections.max("salary"));

		System.out.println(criteria.uniqueResult());
	}

	@Test
	public void testQBC2(){
		Criteria criteria = session.createCriteria(Employee.class);

		//1. AND: 使用 Conjunction 表示
		//Conjunction 本身就是一个 Criterion 对象
		//且当中还能够加入 Criterion 对象
		Conjunction conjunction = Restrictions.conjunction();
		conjunction.add(Restrictions.like("name", "a", MatchMode.ANYWHERE));
		Department dept = new Department();
		dept.setId(80);
		conjunction.add(Restrictions.eq("dept", dept));
		System.out.println(conjunction); 

		//2. OR
		Disjunction disjunction = Restrictions.disjunction();
		disjunction.add(Restrictions.ge("salary", 6000F));
		disjunction.add(Restrictions.isNull("email"));

		criteria.add(disjunction);
		criteria.add(conjunction);

		criteria.list();
	}

	@Test
	public void testQBC(){
		//1. 创建一个 Criteria 对象
		Criteria criteria = session.createCriteria(Employee.class);

		//2. 加入查询条件: 在 QBC 中查询条件使用 Criterion 来表示
		//Criterion 能够通过 Restrictions 的静态方法得到
		criteria.add(Restrictions.eq("email", "SKUMAR"));
		criteria.add(Restrictions.gt("salary", 5000F));

		//3. 运行查询
		Employee employee = (Employee) criteria.uniqueResult();
		System.out.println(employee);
	}

	@Test
	public void testLeftJoinFetch2(){
		String hql = "SELECT e FROM Employee e INNER JOIN e.dept";
		Query query = session.createQuery(hql);

		List<Employee> emps = query.list();
		System.out.println(emps.size()); 

		for(Employee emp: emps){
			System.out.println(emp.getName() + ", " + emp.getDept().getName());
		}
	}

	@Test
	public void testLeftJoin(){
		String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps";
		Query query = session.createQuery(hql);

		List<Department> depts = query.list();
		System.out.println(depts.size());

		for(Department dept: depts){
			System.out.println(dept.getName() + ", " + dept.getEmps().size());
		}

//		List<Object []> result = query.list();
//		result = new ArrayList<>(new LinkedHashSet<>(result));
//		System.out.println(result);
//
//		for(Object [] objs: result){
//			System.out.println(Arrays.asList(objs));
//		}
	}

	@Test
	public void testLeftJoinFetch(){
//		String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN FETCH d.emps";
		String hql = "FROM Department d INNER JOIN FETCH d.emps";
		Query query = session.createQuery(hql);

		List<Department> depts = query.list();
		depts = new ArrayList<>(new LinkedHashSet(depts));
		System.out.println(depts.size()); 

		for(Department dept: depts){
			System.out.println(dept.getName() + "-" + dept.getEmps().size());
		}
	}

	@Test
	public void testGroupBy(){
		String hql = "SELECT min(e.salary), max(e.salary) "
				+ "FROM Employee e "
				+ "GROUP BY e.dept "
				+ "HAVING min(salary) > :minSal";

		Query query = session.createQuery(hql)
				             .setFloat("minSal", 8000);

		List<Object []> result = query.list();
		for(Object [] objs: result){
			System.out.println(Arrays.asList(objs));
		}
	}

	@Test
	public void testFieldQuery2(){
		String hql = "SELECT new Employee(e.email, e.salary, e.dept) "
				+ "FROM Employee e "
				+ "WHERE e.dept = :dept";
		Query query = session.createQuery(hql);

		Department dept = new Department();
		dept.setId(80);
		List<Employee> result = query.setEntity("dept", dept)
				                     .list();

		for(Employee emp: result){
			System.out.println(emp.getId() + ", " + emp.getEmail()
					+ ", " + emp.getSalary() + ", " + emp.getDept());
		}
	}

	@Test
	public void testFieldQuery(){
		String hql = "SELECT e.email, e.salary, e.dept FROM Employee e WHERE e.dept = :dept";
		Query query = session.createQuery(hql);

		Department dept = new Department();
		dept.setId(80);
		List<Object[]> result = query.setEntity("dept", dept)
				                     .list();

		for(Object [] objs: result){
			System.out.println(Arrays.asList(objs));
		}
	}

	@Test
	public void testNamedQuery(){
		Query query = session.getNamedQuery("salaryEmps");

		List<Employee> emps = query.setFloat("minSal", 5000)
				                   .setFloat("maxSal", 10000)
				                   .list();

		System.out.println(emps.size());
	}

	@Test
	public void testPageQuery(){
		String hql = "FROM Employee";
		Query query = session.createQuery(hql);

		int pageNo = 22;
		int pageSize = 5;

		List<Employee> emps =
								query.setFirstResult((pageNo - 1) * pageSize)
								     .setMaxResults(pageSize)
								     .list();
		System.out.println(emps);
	}

	@Test
	public void testHQLNamedParameter(){

		//1. 创建 Query 对象
		//基于命名參数.
		String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
		Query query = session.createQuery(hql);

		//2. 绑定參数
		query.setFloat("sal", 7000)
		     .setString("email", "%A%");

		//3. 运行查询
		List<Employee> emps = query.list();
		System.out.println(emps.size());
	}

	@Test
	public void testHQL(){

		//1. 创建 Query 对象
		//基于位置的參数.
		String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ?

AND e.dept = ?

"
				+ "ORDER BY e.salary";
		Query query = session.createQuery(hql);

		//2. 绑定參数
		//Query 对象调用 setXxx 方法支持方法链的编程风格.
		Department dept = new Department();
		dept.setId(80);
		query.setFloat(0, 6000)
		     .setString(1, "%A%")
		     .setEntity(2, dept);

		//3. 运行查询
		List<Employee> emps = query.list();
		System.out.println(emps.size());
	}
}
时间: 2024-10-13 10:29:53

hibernate 检索方式的相关文章

Hibernate检索方式概述

Hibernate检索方式概述 我们在对数据库的操作中,最常用的是select,那么使用Hibernate如何进行select操作呢?本文就来徐徐道来. Hibernate检索方式可分为5种: 导航对象图检索方式,根据已加载的对象导航到其它对象. OID检索方式,按照对象的OID来检索对象. HQL检索方式,使用面向对象的HQL查询语言. QBC检索方式,使用QBC(Query by Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口. 本

4. Hibernate检索方式

Hibernate检索方式的分类 Hibernate的检索方式主要有5种,分别为导航对象图检索方式.OID检索方式.HQL检索方式.QBC检索方式和SQL检索方式.下面对这5中检索方式的使用进行详解. 1. 对象图导航检索 对象图导航检索方式是根据已经加载的对象,导航到他的关联对象.它利用类与类之间的关系来检索对象.譬如要查找一个联系人对应的客户,就可以由联系人对象自动导航找到联系人所属的客户对象.当然,前提是必须在对象关系映射文件上配置了多对一的关系.其检索方式如下所示: LinkMan li

[原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)

hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 HQL 检索方式: 使用面向对象的 HQL 查询语言 QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口. 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句 建立封装

Hibernate检索方式和Criteria查询的讲解

Hibernate框架5种检索方式 1.导航对象图检索方式:根据已经加载的对象导航到其他对象 2.OID检索方式:按照对象的OID来检索对象 3.HQL检索方式:使用面向对象的HQL查询语言 4.QBC检索方式:使用QBC(Query By Criteria)API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口 5.本地SQL检索方式:使用本地数据库的SQL查询语句 这次重点讲解Criteria查询,首先我们先了解一下它.  Criteria 查询采用面向对象

Hibernate检索方式-HQL(7)

Hibernate 提供了以下几种检索对象的方式 (1)导航对象图检索方式:  根据已经加载的对象导航到其他对象 (2)OID 检索方式:  按照对象的 OID 来检索对象 (3)HQL 检索方式: 使用面向对象的 HQL 查询语言 (4)QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口. (5)本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句 HQL(Hiber

Hibernate检索(上)

什么是HQL检索 HQL(Hibernate Query Language)是面向对象的查询语言,具有丰富灵活的特性 在Hibernate提供的各种检索方式中,HQL是使用最为广泛的一种检索方式,也是官方推荐的查询模式 Hibernate检索方式的功能 可以在查询语句中设定查询条件,动态绑定参数 支持投影查询 支持分页查询 支持链接查询 支持分组查询,可以使用having和group by关键字 内置聚集函数,如sum().min().max()等 可调用用户自定义函数 支持子查询 HQL检索步

7.Hibernate 检索

1.Hibernate检索方式 检索方式简介: 导航对象图检索方式:根据已经加载的对象,导航到其他对象.OID检索方式:按照对象的OID来检索对象.Session 的 get() 和 load() 方法提供了这种功能. HQL检索方式:使用面向对象的HQL查询语言.QBC检索方式:使用QBC(Query By Criteria)API来检索对象.这种API封装了基于字符串形式的查询语句,提供了更加面向对象的接口.本地SQL检索方式:使用本地数据库的SQL查询语句. HQL简介: HQL是一种面向

Hibernate的检索方式

Hibernate提供以下几种检索对象的方式 1.导航对象图检索方式    根据已经加载的对象,导航到其他对象 2.OID检索方式    按照对象的OID来检索对象 3.HQL检索方式    使用面向对象的HQL查询语言 4.QBC检索方式    使用QBC(Qurey By Criteria) API来检索对象 5.本地SQL检索方式    使用本地数据库的SQL查询语句