Hibernate之HQL查询
一、Hibernate 提供了以下几种检索对象的方式:
- 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象
- HQL 检索方式:使用面向对象的 HQL 查询语言
- QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种
API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口. - 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句
二、HIbernate的HQL查询
1. HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:
在查询语句中设定各种查询条件
- 支持投影查询, 即仅检索出对象的部分属性
- 支持分页查询
- 支持连接查询
- 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
- 提供内置聚集函数, 如 sum(), min() 和 max()
- 支持子查询
- 支持动态绑定参数
- 能够调用 用户定义的 SQL 函数或标准的 SQL 函数
2. HQL 检索方式包括以下步骤:
a、通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数
b、动态绑定参数
c、调用 Query 相关方法执行查询语句.
三、各种查询示例代码:
1、首先搭建测试环境:
两个测试实体类:
Employee类:
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;}public Employee(float salary, String email, Department dept) {super();this.salary = salary;this.email = email;this.dept = dept;}public Employee() {}@Overridepublic String toString() {return "Employee [id=" + id + "]";}
}
Department类:
public class Department {private Integer id;private String name;private Set<Employee> emps=new HashSet<Employee>();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;}@Overridepublic String toString() {return "Department [id=" + id + ", name=" + name + "]";}
}
2个实体类对应的hbm配置文件:
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-10-31 23:07:48 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.entity"><class name="Employee" table="EMPLOYEE"><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="Department" ><column name="DEPT_ID" /></many-to-one></class><query name="salaryEmp"><![CDATA[ from Employee e where e.salary> :minSal and e.salary < :maxSal ]]></query>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-10-31 23:07:48 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.entity"><class name="Department" table="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="EMPLOYEE" inverse="true" lazy="true"><key><column name="DEPT_ID" /></key><one-to-many class="Employee" /></set></class>
</hibernate-mapping>
Hibernate配置文件:hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC"-//Hibernate/Hibernate Configuration DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration><session-factory><!-- hibernate数据库连接信息配置 --><property name="connection.username">root</property><property name="connection.password">root123</property><property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property><property name="connection.driver_class">com.mysql.jdbc.Driver</property><!-- hibernate基本配置 --> <!-- hibernate的数据库方言 --><property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <property name="hbm2ddl.auto">update</property><property name="show_sql">true</property><property name="format_sql">true</property><!--设置hibernate事务的隔离级别 --><property name="connection.isolation">2</property><!-- 需要关联的hibernate映射文件 hbm.xml文件 --><mapping resource="com/elgin/hibernate/entity/Department.hbm.xml"/> <mapping resource="com/elgin/hibernate/entity/Employee.hbm.xml"/> </session-factory>
</hibernate-configuration>
Hibernate查询单元测试类:
public class HibernateTest2 {//如此声明只为方便测试,生产环境不能这么用private SessionFactory sessionFactory;private Session session;private Transaction transcation;@Beforepublic void init(){Configuration cfg=new Configuration().configure();ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();sessionFactory=cfg.buildSessionFactory(serviceRegistry);session=sessionFactory.openSession();transcation=session.beginTransaction();}public void insert(int i){Employee employee=new Employee();employee.setName("name"+i);employee.setEmail("name"+i+"@qq.com");employee.setSalary(1000*i);session.save(employee);}@Test//初始化2个表中的数据,方便查询public void test(){for (int i = 14; i < 21; i++) {insert(i);}}@Afterpublic void destory(){transcation.commit();session.close();sessionFactory.close();}
}
上述类为基础测试类,如下的测试代码均需加入到上述类中运行。至此,测试环境搭建完成,下面逐一进行测试:
2 绑定参数:
- Hibernate 的参数绑定机制依赖于 JDBC API 中的 PreparedStatement 的预定义 SQL 语句功能.
- HQL 的参数绑定由两种形式:
按参数名字绑定: 在 HQL 查询语句中定义命名参数, 命名参数以 “:” 开头.
按参数位置绑定: 在 HQL 查询语句中用 “?”来定义参数位置
- 相关方法:
setEntity(): 把参数与一个持久化类绑定。
setParameter(): 绑定任意类型的参数. 该方法的第三个参数显式指定 Hibernate 映射类型。
测试代码:
@Testpublic void testHQLNamedParameters(){//1.创建 Query 对象// 基于命名参数String HQL="FROM Employee e WHERE e.salary> :salary AND e.email LIKE :email";Query query=session.createQuery(HQL);//2. 动态绑定参数query.setFloat("salary", 6000).setString("email", "%a%");//3. 执行查询List<Employee> emps = query.list();System.out.println(emps.size());}@Testpublic void testHQL(){//1.创建 Query 对象// 基于位置的参数String HQL="FROM Employee e WHERE e.salary> ? AND e.email LIKE ?";Query query=session.createQuery(HQL);//2. 动态绑定参数// Query对象调用setXxx方法,支持方法链的编程query.setFloat(0, 6000).setString(1, "%a%");//3. 执行查询List<Employee> emps = query.list();System.out.println(emps.size());}
3 分页查询:
- setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象开始检索
- setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象
/*** HQL分页查询* */@Testpublic void testPageQuery(){String HQL="from Employee";int pageNo=2;int pageSize=5;List<Employee> emps= session.createQuery(HQL).setFirstResult((pageNo-1)*pageSize).setMaxResults(pageSize).list();System.out.println(emps);}
4.在映射文件中定义命名查询语句
Hibernate 允许在映射文件中定义字符串形式的查询语句.
元素用于定义一个 HQL 查询语句, 它和 元素并列.
在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象.
本例在Employee.hbm.xml映射文件中定义了如下:
<query name="salaryEmp"><![CDATA[ from Employee e where e.salary> :minSal and e.salary < :maxSal ]]></query>
之后就可以使用如下代码来使用次查询语句:
/*** HQL命名查询(HQL语句配置在hbm文件中的query标签中,使用CDATA包裹)* */@Testpublic void testNamedQuery(){Query query=session.getNamedQuery("salaryEmp");List<Employee> emps=query.setFloat("minSal", 2000).setFloat("maxSal", 5000).list();System.out.println(emps);}
5.投影查询:
- 投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现.
- Query 的 list() 方法返回的集合中包含的是数组类型的元素, 每个对象数组代表查询结果的一条记录
- 可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录, 使程序代码能完全运用面向对象的语义来访问查询结果集.
- 可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素
测试代码:
/*** HQL投影查询,结果类型为List<Object[]>* */@Testpublic void testFieldQuery(){String hql="select e.email,e.salary,e.dept from Employee e where e.dept=:dept";Department dept=new Department();dept.setId(6);Query query=session.createQuery(hql).setEntity("dept", dept);List<Object[]> emps=query.list();for (Object[] employee : emps) {System.out.println(Arrays.asList(employee));} }
若想要把投影查询的结果映射到对象上,则需要在Employee对象加入相应的构造方法,映射对象示例:
/*** HQL投影查询,结果类型为List<Employee>* 1.HQL语句中使用new关键字将结果映射到对象上,* 前提是Employee对象中有对应的构造方法 */@Testpublic void testFieldQuery2(){String hql="select new Employee(e.salary,e.email,e.dept) from Employee e where e.dept=:dept";Department dept=new Department();dept.setId(6);Query query=session.createQuery(hql).setEntity("dept", dept);List<Employee> emps=query.list();for (Employee employee : emps) {System.out.println(employee.getEmail());System.out.println(employee.getSalary());System.out.println(employee.getDept());} }
6.报表查询
报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组, 用 HAVING 关键字对分组数据设定约束条件.
在 HQL 查询语句中可以调用以下聚集函数:
count()
min()
max()
sum()
avg()
示例:
/*** 报表查询,可以使用相关聚集函数* */@Testpublic void testGroupBy(){String hql="select min(e.salary),max(e.salary),e.dept from Employee e"+ " group by e.dept"+ " having min(e.salary) > :min"; Query query=session.createQuery(hql).setFloat("min", 3000);List<Object[]> emps=query.list();for (Object[] objects : emps) {System.out.println(Arrays.asList(objects));}}
7.HQL迫切左外连接:
- LEFT JOIN FETCH 关键字表示迫切左外连接检索策略.
- list() 方法返回的集合中存放实体对象的引用, 每个 Department 对象关联的 Employee 集合都被初始化,存放所有关联的 Employee 的实体对象.
- 查询结果中可能会包含重复元素, 可以通过一个 HashSet 来过滤重复元素
/*** HQL 迫切左外连接*/@Testpublic void testLeftJoinFetch(){String hql="select distinct d from Department d left join fetch d.emps";Query query=session.createQuery(hql);List<Department> depts=query.list();for (Department dept : depts) {System.out.println(dept.getName()+"-"+dept.getEmps().size());}}
7.HQL 左外连接:
- LEFT JOIN 关键字表示左外连接查询.
- list() 方法返回的集合中存放的是对象数组类型
- 根据配置文件来决定 Employee 集合的检索策略(是否延迟加载)
- 如果希望 list() 方法返回的集合中仅包含 Department 对象, 可以在HQL 查询语句中使用 SELECT 关键字
/*** HQL 左外连接*/@Testpublic void testLeftJoin(){String hql="select distinct d from Department d left join d.emps";Query query=session.createQuery(hql);List<Department> depts=query.list();for (Department dept : depts) {System.out.println(dept.getName()+"-"+dept.getEmps().size());}}
综上迫切左外连接和左外连接:
- 如果在 HQL 中没有显式指定检索策略, 将使用映射文件配置的检索策略.
- HQL 会忽略映射文件中设置的迫切左外连接检索策略, 如果希望 HQL 采用迫切左外连接策略, 就必须在 HQL 查询语句中显式的指定它
- 若在 HQL 代码中显式指定了检索策略, 就会覆盖映射文件中配置的检索策略
转载于:https://www.cnblogs.com/elgin-seth/p/5293753.html
Hibernate之HQL查询相关推荐
- Hibernate 笔记 HQL查询
http://www.cnblogs.com/zilong882008/archive/2011/11/05/2237123.html Hibernate 笔记 HQL查询(一)单属性,多属性查询 H ...
- java hql多条件查询_JSP 开发之hibernate的hql查询多对多查询
JSP 开发之hibernate的hql查询多对多查询 在hibernate的hql查询中,假如说分组信息与试题是多对多关系,那么我们要在hql查询中对含有多个分组信息的试题都要查询出来.并同时查询出 ...
- Hibernate(九)HQL查询
一.Hibernate提供的查询方式 OID查询方式:主键查询.通过get()或者load()方法加载指定OID的对象查询结果为一个 HQL查询方式:通过Query接口使用HQL语言进行查询 QBC查 ...
- hibernate的HQL查询语句
1.标准查询Criteria (主要应用于简单的查询) Session session=HibernateSessionFactory.getSession();Query query=null;Cr ...
- hibernate 之HQL查询实例
2019独角兽企业重金招聘Python工程师标准>>> 配置文件hibernate.cfg.xml: <?xml version='1.0' encoding='UTF-8'? ...
- hibernate的hql查询语句总结
来自: http://www.cnblogs.com/xiaoluo501395377/p/3376256.html 转载于:https://www.cnblogs.com/rambo12932713 ...
- Hibernate 学习笔记(二)—— Hibernate HQL查询和 QBC 查询
目录 一.Hibernate 的 HQL 查询 1.1.查询所有数据 1.2.条件查询 1.3.排序查询 1.4.统计查询 1.5.分页查询 1.6.投影查询 二.Hibernate 的 QBC 查询 ...
- Hibernate的查询 HQL查询 查询某几列
HQL 是Hibernate Query Language的简写,即 hibernate 查询语言:HQL采用面向对象的查询方式.HQL查询提供了更加丰富的和灵活的查询特性,因此Hibernate将H ...
- Hibernate中HQL函数汇总及其说明
2019独角兽企业重金招聘Python工程师标准>>> Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Lang ...
- hql 字符串where语句_hibernate的hql查询语句总结
4.3 使用HQL查询 Hibernate提供了异常强大的查询体系,使用Hibernate有多种查询方式.可以选择使用Hibernate的HQL查询,或者使用条件查询,甚至可以使用原生的SQL查询语句 ...
最新文章
- xml笔记整理_基础概括
- delphi 数据 上移 下移_脑图-数据库查询优化器的艺术
- python基础教程第二版下载-Python基础教程(第2版)
- 战神背光键盘如何关系_显瘦又有肌肉 神舟战神Z7MKP5GZ评测
- DevExpress WinFormsSuite 本地化(Simplified Chinese OR Traditional Chinese)
- 说说每月至少一次的那点事,文末有彩蛋!
- android studio访问webservice如何传递类对象报错_小白学习web service,这是最最最基础的了,只用JDK还不会吗?...
- PAT (Basic Level) Practice1024 科学计数法
- Servlet线程安全问题
- 【ModBus】基础使用:【01】MThings国产调试工具
- ubuntu linux崩溃,ubuntu linux qq崩溃问题的解决方法以及原因
- 获取webshell的方法
- discuz 模板php代码,自定义HTML模板DIY支持PHP代码解析
- Java实验1:个人银行账户管理系统总结
- 全栈学习之CSS基础学习
- DOM案例练习-推荐几个DOM小案例练习有示例代码
- 【马修笔记】大波段顶底反转的节奏交易.
- mongodb mysql配置_Mongodb 配置
- iOS 常用第三方库及插件
- 玩转 Jasper Report(1) Jaspersoft Studio 安装使用教程
热门文章
- 如何将显示器连接到 Mac?
- 如何将Mac“桌面”和“文稿”文件添加到 iCloud 云盘中?
- 5G Next Generation of Communication
- Vuex之state和getters
- 【转】 pycharm快捷键、常用设置、配置管理(后两者详见原博客)
- 用户自定义多选框checkbox
- ListView中动态显示和隐藏HeaderFooter
- Linux之Inode详解 作者:羽飞博客 http://www.opsers.org/
- 专注于钢铁行业电子商务的服务网站,钢铁行业的网上贸易市场 一起成长
- Maven仓库—Nexus环境搭建及简单介绍