hibernate 检索方式[通俗易懂]

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> 元素并列. 
  • hibernate 检索方式[通俗易懂]
  • 在程序中通过 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()); }}







版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/115846.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • chmod的用法_举例说明chmod的两种用法

    chmod的用法_举例说明chmod的两种用法虽然Ubuntu图形化已经做得很好,但是还是有些操作需要在命令行下执。chmod命令详细用法指令名称:chmod使用权限:所有使用者使用方式:chmod[-cfvR][–help][–version]modefile…说明:Linux/Unix的档案调用权限分为三级:档案拥有者、群组、其他。利用chmod可以藉以控制档案如何被他人所调用。…

    2022年10月20日
  • 如何编写优秀的单元测试用例「建议收藏」

    如何编写优秀的单元测试用例「建议收藏」优秀单元测试的定义​单元测试:一段自动化的代码,这段代码调用被测试的工作单元,之后对这个工作单元的单个最终结果的某些假设进行检验。单元测试几乎都是用单元测试框架进行编写。单元测试容易编写,快速运行,可自动化,可靠,可读,可维护,结果稳定。  集成测试:对一个工作单元进行的测试,这个测试对被测试的工作单元没有完全的控制,并使用该单元的一个或多个真实依赖物,例如数据库、系统时间、系统文件等  工作单元:从调用系统一个公共方法到产生一个测试可见的最终结果,其间这个系统发生的行为。一个

  • MongoDB和Mysql区别

    MongoDB和Mysql区别mysql和MongoDB的区别?对应优点?mysql是关系型数据库,MongoDB是非关系型数据库。Mysql的优点:处理复杂事务,批sql(交易系统、订单系统、银行系统)。 MongoDB优点:更高的写入负载:侧重数据写入性能,而非事务安全; 储存对象数据方便,类可以直接序列化成JSON储存到MongoDB中。…

  • iOS7 UIKit动力学-碰撞特性UICollisionBehavior 下

    iOS7 UIKit动力学-碰撞特性UICollisionBehavior 下

  • RESTful API 设计指南

    RESTful API 设计指南

  • 2021pycharm永久激活码[免费获取]

    (2021pycharm永久激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~MLZPB5EL5Q-eyJsaWNlb…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号