Hibernate(十二):HQL查询(一)
- 概述
Hibernate提供了以下几种检索对象的方式
1)导航对象图检索方式:根据已经加载的对象导航到其他对象;
2)OID检索方式:按照对象的OID来检索对象;
3)HQL检索方式:使用面向对象的HQL查询语言;
4)QBC检索方式:使用QBC(Query By Criteria)API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
5)本地SQL检索的方式:使用本地数据的SQL查询语句。
HQL(Hibernate Query Language)面向对象的查询语言,它和SQL查询语言有些相似。在Hibernate提供的各种检索方式中,HQL是使用最广泛的一种检索方式。它有如下功能:
1)在查询语句中设定各种查询条件
2)支持投影查询,即仅检索出对象的部分属性
3)支持分页查询
4)支持连接查询
5)支持分组查询,允许使用“HAVING”和“GROUP BY”关键字
6)提供内置聚集函数,如:SUM()、MIN()、Max()
7)支持子查询
8)支持动态绑定参数
9)能够调用用户定义的SQL函数或标准的SQL函数。
HQL检索方式包括以下步骤
1)通过Session的createQuery()方法创建一个Query对象,它包括一个HQL查询语句。HQL查询语句中可以包括命名参数
2)动态绑定参数
3)调用Query相关方法执行查询语句
Query接口支持方法链编程风格
它的setXxx()方法返回自身实例,而不是void类型。
HQL vs SQL
1)HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象-关系映射文件中的映射信息,把HQL查询语句翻译成相应的SQL语句。HQL查询语句中的主题是域模型中的类与类的属性
2)SQL查询语句是与关系数据库绑定在一起的。SQL查询语句中的主体是数据库表及表的字段。
绑定参数
1)Hibernate的参数绑定机制依赖于JDBC API中的PreparedStatement的预定义SQL语句功能。
2)HQL的参数绑定两种形式:
按参数名称绑定:在HQL查询语句定义命名参数,命名参数以“.”开头
按参数位置绑定:在HQL查询语句中用“?”来定定义参数位置
3)相关参数
setEntity():把参数与一个持久类绑定
setParamenter():绑定任意类型的参数,该方式的第三个参数显式指定Hibernate映射类性。
HQL采用ORDER BY关键字对查询结果排序
在映射文件中定义命名查询语句
1)Hibernate允许在映射文件中定义字符串形式的查询语句
2)<query>元素用于定义一个HQL查询语句,它和<class>元素并列
1 <query name="findNewsByTitle"> 2 <![CDATA[ 3 FROM News n WHERE n.title LIKE :title 4 ]]> 5 </query>
3)在程序中通过Session的getNameQuery()方法获取查询语句对应的Query对象。
- 新建项目
新建工程Hibernate09,在根目录导入hibernate(required)开发包及mysql驱动包,在src下新建hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <property name="hibernate.connection.username">root</property> 8 <property name="hibernate.connection.password">123456</property> 9 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 10 <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_09</property> 11 12 <!-- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 13 <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> --> 14 <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> 15 16 <property name="hibernate.show_sql">true</property> 17 18 <property name="hibernate.format_sql">true</property> 19 20 <property name="hibernate.hbm2ddl.auto">update</property> 21 22 <property name="hibernate.current_session_context_class">thread</property> 23 24 <property name="hibernate.c3p0.max_size">500</property> 25 <property name="hibernate.c3p0.min_size">20</property> 26 <property name="hibernate.c3p0.max_statements">10</property> 27 <property name="hibernate.c3p0.timeout">2000</property> 28 <property name="hibernate.c3p0.idle_test_period">2000</property> 29 <property name="hibernate.c3p0.acquire_increment">10</property> 30 31 <mapping resource="com/dx/hibernate09/hql01/Department.hbm.xml" /> 32 <mapping resource="com/dx/hibernate09/hql01/Employee.hbm.xml" /> 33 34 </session-factory> 35 </hibernate-configuration>
在src下新建包com.dx.hibernate09.hql01,在该包下新建:
Department.java
1 package com.dx.hibernate09.hql01; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class Department { 7 private Integer id; 8 private String name; 9 private Set<Employee> employees = new HashSet<>(); 10 11 public Department() { 12 13 } 14 15 public Department(String name) { 16 super(); 17 this.name = name; 18 } 19 20 public Integer getId() { 21 return id; 22 } 23 24 public void setId(Integer id) { 25 this.id = id; 26 } 27 28 public String getName() { 29 return name; 30 } 31 32 public void setName(String name) { 33 this.name = name; 34 } 35 36 public Set<Employee> getEmployees() { 37 return employees; 38 } 39 40 public void setEmployees(Set<Employee> employees) { 41 this.employees = employees; 42 } 43 44 }
Department.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-6-9 23:13:49 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate09.hql01.Department" table="DX_DEPARTMENT"> 7 <id name="id" type="java.lang.Integer"> 8 <column name="ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="name" type="java.lang.String"> 12 <column name="NAME" /> 13 </property> 14 15 <set name="employees" table="DX_EMPLOYEE" inverse="true" lazy="true"> 16 <key> 17 <column name="DEPARTMENT_ID" /> 18 </key> 19 <one-to-many class="com.dx.hibernate09.hql01.Employee" /> 20 </set> 21 </class> 22 </hibernate-mapping>
Employee.java
1 package com.dx.hibernate09.hql01; 2 3 public class Employee { 4 private Integer id; 5 private String name; 6 private float salary; 7 private String email; 8 private Department department; 9 10 public Employee() { 11 12 } 13 14 public Employee(String name, float salary, String email) { 15 super(); 16 this.name = name; 17 this.salary = salary; 18 this.email = email; 19 } 20 21 public Integer getId() { 22 return id; 23 } 24 25 public void setId(Integer id) { 26 this.id = id; 27 } 28 29 public String getName() { 30 return name; 31 } 32 33 public void setName(String name) { 34 this.name = name; 35 } 36 37 public float getSalary() { 38 return salary; 39 } 40 41 public void setSalary(float salary) { 42 this.salary = salary; 43 } 44 45 public String getEmail() { 46 return email; 47 } 48 49 public Department getDepartment() { 50 return department; 51 } 52 53 public void setDepartment(Department department) { 54 this.department = department; 55 } 56 57 public void setEmail(String email) { 58 this.email = email; 59 } 60 61 }
Employee.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <!-- Generated 2017-6-9 23:13:49 by Hibernate Tools 3.5.0.Final --> 5 <hibernate-mapping> 6 <class name="com.dx.hibernate09.hql01.Employee" table="DX_EMPLOYEE"> 7 <id name="id" type="java.lang.Integer"> 8 <column name="ID" /> 9 <generator class="native" /> 10 </id> 11 <property name="name" type="java.lang.String"> 12 <column name="NAME" /> 13 </property> 14 <property name="salary" type="float"> 15 <column name="SALARY" /> 16 </property> 17 <property name="email" type="java.lang.String"> 18 <column name="EMAIL" /> 19 </property> 20 <many-to-one name="department" class="com.dx.hibernate09.hql01.Department"> 21 <column name="DEPARTMENT_ID" /> 22 </many-to-one> 23 </class> 24 </hibernate-mapping>
注意:
1)上边新建的类Employee与Department是多对一关系;
2)hbm.xml配置的是双向一对多映射关系。
新建测试类TestMain.java
1 package com.dx.hibernate09.hql01; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.Transaction; 6 import org.hibernate.boot.Metadata; 7 import org.hibernate.boot.MetadataSources; 8 import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; 9 import org.hibernate.boot.registry.StandardServiceRegistry; 10 import org.hibernate.boot.registry.StandardServiceRegistryBuilder; 11 import org.junit.After; 12 import org.junit.Before; 13 import org.junit.Test; 14 15 public class TestMain { 16 private SessionFactory sessionFactory = null; 17 private Session session = null; 18 private Transaction transaction = null; 19 20 @Before 21 public void init() { 22 StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build(); 23 Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); 24 25 sessionFactory = metadata.getSessionFactoryBuilder().build(); 26 session = sessionFactory.getCurrentSession(); 27 transaction = session.beginTransaction(); 28 } 29 30 @Test 31 public void test() { 32 33 } 34 35 @After 36 public void destory() { 37 transaction.commit(); 38 session.close(); 39 sessionFactory.close(); 40 } 41 }
- 初始化数据库
执行空的测试函数test(),生成数据表,后台执行的sql:
1 Hibernate: 2 3 create table DX_DEPARTMENT ( 4 ID integer not null auto_increment, 5 NAME varchar(255), 6 primary key (ID) 7 ) engine=InnoDB 8 Hibernate: 9 10 create table DX_EMPLOYEE ( 11 ID integer not null auto_increment, 12 NAME varchar(255), 13 SALARY float, 14 EMAIL varchar(255), 15 DEPARTMENT_ID integer, 16 primary key (ID) 17 ) engine=InnoDB 18 Hibernate: 19 20 alter table DX_EMPLOYEE 21 add constraint FKqv35rmky1hq7k2ovpiohhpmvh 22 foreign key (DEPARTMENT_ID) 23 references DX_DEPARTMENT (ID)
查询数据
添加testInsertData()测试函数,给数据表填充数据:
1 @Test 2 public void testInsertData() { 3 Department department1 = new Department("开发部门"); 4 Department department2 = new Department("测试部门"); 5 Department department3 = new Department("业务部门"); 6 Department department4 = new Department("财务部门"); 7 Department department5 = new Department("行政部门"); 8 9 session.save(department1); 10 session.save(department2); 11 session.save(department3); 12 session.save(department4); 13 session.save(department5); 14 15 department1.setId(1); 16 department2.setId(2); 17 department3.setId(3); 18 department4.setId(4); 19 department5.setId(5); 20 21 for (int i = 0; i < 80; i++) { 22 Employee employee = new Employee("tommy" + i, 1000 * i, "tommy" + i + "@dx.com"); 23 if (i % 5 == 0) { 24 employee.setDepartment(department1); 25 } else if (i % 5 == 1) { 26 employee.setDepartment(department2); 27 } else if (i % 5 == 2) { 28 employee.setDepartment(department3); 29 } else if (i % 5 == 3) { 30 employee.setDepartment(department4); 31 } else if (i % 5 == 4) { 32 employee.setDepartment(department5); 33 } 34 session.save(employee); 35 } 36 37 }
执行结果查询
- HQL带参数查询:
1)基于位置的参数
1 /** 2 * 基于位置的参数 3 */ 4 @Test 5 public void testHQLPositionParameter() { 6 String hql = "From Employee e Where e.salary>? and e.name like ?"; 7 8 Query query = session.createQuery(hql).setFloat(0, 6000).setString(1, "%1%"); 9 10 List<Employee> employees = query.list(); 11 System.out.println(employees.size()); 12 System.out.println(employees); 13 }
2)基于命名的参数
1 /** 2 * 基于命名的参数 3 */ 4 @Test 5 public void testHQLNameParameter() { 6 String hql = "From Employee e Where e.salary>:salary and e.name like :name"; 7 8 Query query = session.createQuery(hql).setFloat("salary", 6000).setString("name", "%1%"); 9 10 List<Employee> employees = query.list(); 11 System.out.println(employees.size()); 12 System.out.println(employees); 13 }
- HQL Order By排序查询:
1 /** 2 * Order By 3 */ 4 @Test 5 public void testHQLOrderBy() { 6 String hql = "From Employee e Where e.salary>? and e.name like ? Order By e.salary Desc"; 7 8 Query query = session.createQuery(hql).setFloat(0, 6000).setString(1, "%1%"); 9 10 List<Employee> employees = query.list(); 11 System.out.println(employees.size()); 12 System.out.println(employees); 13 }
- HQL 设置实体参数查询:
1 /** 2 * 基于实体的查询 3 */ 4 @Test 5 public void testHQLEntity() { 6 String hql = "From Employee e Where e.salary>? and e.name like ? and e.department=? Order By e.salary Desc"; 7 8 Department depart = new Department(); 9 depart.setId(1); 10 11 @SuppressWarnings("deprecation") 12 Query query = session.createQuery(hql).setFloat(0, 6000).setString(1, "%1%").setEntity(2, depart); 13 14 List<Employee> employees = query.list(); 15 System.out.println(employees.size()); 16 System.out.println(employees); 17 }
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。