hibernate 检索方式
小编:管理员 331阅读 2022.09.14
概述
-
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 同意在映射文件里定义字符串形式的查询语句.
-
元素用于定义一个 HQL 查询语句, 它和 元素并列.
- 在程序中通过 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复制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 getEmps() { return emps; } public void setEmps(Set emps) { this.emps = emps; } @Override public String toString() { return "Department [id=" + id + "]"; } }
Department.hbm.xml
复制
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
复制:minSal AND e.salary < :maxSal]]>
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复制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 depts = query.list(); System.out.println(depts.size()); for(Department dept: depts){ System.out.println(dept.getName() + ", " + dept.getEmps().size()); } // List
相关推荐
- 经典笔试题-JDBC及Hibernate篇 五、JDBC 及Hibernate:(共12 题:基础10 道,中等难度2 道)110、数据库,比如100 用户同时来访,要采取什么技术解决?【基础】 答:可采用连接池。111、什么是ORM?【基础】 答:对象关系映射(Object—Relational Mapping,简称ORM)是一种为了解决面向对象…
- 3DMAX提示和技巧 本主题标识使用 Civil View 的一些重要提示和技巧。常规使用屏幕分辨率至少为 1280x1024 的 Civil View。低于此分辨率时,一些面板将占用过多屏幕空间。 将视口设置为线框显示以达到最佳性能。 要尽可能简化用户界面,请在单个视口中工作并关闭 3ds Max 命令面…