- 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 关键字
- 提供内置聚集函数, 如 sum(), min() 和 max()
- 支持子查询
- 支持动态绑定参数
- 能够调用 用户定义的 SQL 函数或标准的 SQL 函数
HQL 检索方式包括以下步骤:
- 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询. 语句. HQL 查询语句中可以包含命名参数
- 动态绑定参数
- 调用 Query 相关方法执行查询语句.
- Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型
HQL vs SQL:
- HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性
- SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段.
- 示例:使用HQL查询数据库
- 使用Hibernate链接Oracle数据库
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">scott</property>
<property name="connection.password">tiger</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521/mldn</property>
<!--设置每次从数据库中读取的记录数量-->
<property name="default_batch_fetch_size">100</property>
<!--设置每次执行批处理的sql语句数量-->
<property name="jdbc.batch_size">10</property>
<!--配置数据库方言-->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!--是否打印sql语句-->
<property name="show_sql">true</property>
<!--是否对sql语句进行格式化-->
<property name="format_sql">true</property>
<!--指定自动生成数据表-->
<property name="hbm2ddl.auto">update</property>
<!--设置数据库的隔离级别-->
<property name="connection.isolation">2</property>
<!--改变delet()方法的行为-->
<property name="use_identifier_rollback">true</property>
</session-factory>
</hibernate-configuration>
- 编写Employee程序类
public class Employee {
private Integer id;
private String name;
private float salary;
private String email;
private Department dept;
//getter和setter方法
}
- 编写 Employee.hbm.xml映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="mao.shu.vo" >
<class name="Employee" table="GG_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="email" type="java.lang.String">
<column name="EMAIL"/>
</property>
<property name="salary" type="float">
<column name="SALARY"/>
</property>
<many-to-one name="dept" class="Department">
<column name="DEPT_ID"/>
</many-to-one>
</class>
</hibernate-mapping>
- 编写Department程序类
public class Department {
private Integer id;
private String name;
private Set<Employee> emps = new HashSet<>();
//getter和setter方法
}
- 设置Department.hbm.xml映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="mao.shu.vo" >
<class name="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">
<key>
<column name="DEPT_ID"/>
</key>
<one-to-many class="Employee"></one-to-many>
</set>
</class>
</hibernate-mapping>
- 经这两个映射文件配置到Hibernate.cfg.xml文件之中
<mapping resource="mao/shu/vo/Department.hbm.xml"/>
<mapping resource="mao/shu/vo/Employee.hbm.xml"/>
- 编写测试文件
public class DepartmentTest {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void before(){
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder()
.applySettings(configuration.getProperties())
.buildServiceRegistry();
this.sessionFactory = configuration.buildSessionFactory(serviceRegistry);
this.session = this.sessionFactory.openSession();
this.transaction = this.session.beginTransaction();
}
@After
public void after(){
this.transaction.commit();
this.session.close();
this.sessionFactory.close();
}
@Test
public void test(){
for (int i = 0; i < 10; i++) {
Department department = new Department();
department.setName("部门 = "+i);
this.session.save(department);
for (int j = 0; j < 10; j++) {
Employee employee = new Employee();
employee.setName("xiemaoshu"+i);
employee.setSalary(100+i);
employee.setEmail(i*100+10+i+"@"+i*100+10+i+".com");
employee.setDept(department);
this.session.save(employee);
}
}
}
@Test
public void testHQL(){
String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ?";
Query query = this.session.createQuery(hql);
Department dept = new Department();
dept.setId(309);
query.setFloat(0,100).setString(1,"%8%").setEntity(2,dept);
List<Employee> emps = query.list();
System.out.println(emps);
}
}
- 输出结果
- 从测试中可以发现使用HQL查询语句中的占位符"?"即可以设置基本数据类型,也可以设置一个具体java对象
- 并且每一个Query的"setXxx()"方法都会返回一个Query类对象,这就可以使用代码链的方式进行设置占位符
- 在HQL语句之中还可以设置自定义的命名参数,参数在HQL语句中以":"开头
@Test
public void testHQLParameter(){
String hql = "FROM Employee e WHERE e.email LIKE :email";
Query query = this.session.createQuery(hql);
query.setString("email","%8%");
List<Employee> emps = query.list();
System.out.println(emps);
}
- 在HQL语句之中还可以使用"ORDER BY"关键字来对查询结果进行排序
@Test
public void testHQLParameter(){
String hql = "FROM Employee e WHERE e.email LIKE :email ORDER BY e.name";
Query query = this.session.createQuery(hql);
query.setString("email","%8%");
List<Employee> emps = query.list();
System.out.println(emps);
}