【SSH】——hql的使用方式及实现原理
最后更新于:2022-04-01 11:27:35
## 【含义】
hql,即Hibernate Query Language。它与我们熟知的sql很类似,它最大的特点就是对查询进行了面向对象的封装,下面会在具体例子中说明。
sql查询的是数据库中的表或字段,而hql是**面向对象**的,具有继承、多态、关联等特性,他针对的是对象。
## 【使用】
那么如何使用hql进行查询呢?首先,我们需要宏观看一下hql的几种使用方式:**基本使用、外置命名和过滤器。**
基本使用即我们将hql语句写在代码中,执行操作。配置文件的方式是将我们所写的hql语句转移到配置文件中,这样就很容易对其进行修改了。第三种过滤器,类似Struts中的Filter过滤器。它对查询的内容进行过滤,在映射文件中定义过滤器,程序中启用过滤器,并为过滤器参数赋值。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-27_57206b09e4b1e.jpg)
## 【基本使用】
我们先通过例子,了解下hql的基本使用,再介绍其实现原理。
~~~
/**
* 实体对象查询,
*/
public void testquery(){
Session session=null;
try{
//获得Hibernate Session
session=HibernateUtil.getSession();
//开启事务
session.beginTransaction();
//以hql语句创建Query对象,Query调用list方法返回全部实例
List shelfList=session.createQuery("from Shelf").list();
//迭代显示数据
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Shelf shelf=(Shelf)iter.next();
System.out.println(shelf.getLocation());
}
//提交事务
session.getTransaction().commit();
}catch(Exception e){
//发生异常,事务回滚
e.printStackTrace();
session.getTransaction().rollback();
}finally{
//关闭Session
HibernateUtil.closeSession(session);
}
}
/**
* 封装类
*/
public class HibernateUtil {
private static SessionFactory factory;
/**
* 完成sessionFactory的初始化
*/
static{
try{
//读取hibernate.cfg.xml配置文件
Configuration cfg=new Configuration().configure();
//建立sessionFactory,可访问mysql
factory=cfg.buildSessionFactory();
}catch(Exception e){
e.printStackTrace();
}finally{
}
}
//获得session
public static Session getSession(){
return factory.openSession();
}
//关闭session
public static void closeSession(Session session){
if(session!=null){
if(session.isOpen()){
session.close();
}
}
}
//返回sessionFactory
public static SessionFactory getSessionFactory(){
return factory;
}
}
~~~
Session——对象的增删改查操作
Query,Criteria——执行数据库查询
SessionFactory——初始化Hibernate,创建Session对象。
Configuration——负责配置、启动Hibernate,创建SessionFactory对象。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-27_57206b0a09319.jpg)
## 【外置命名】
外置命名和下面要说的过滤器都是些在配置文件中的,灵活性较好。
需求是,查询Shelf中"code>1"的数据。我们需要在配置文件中,加入hql语句。
~~~
<hibernate-mapping >
<class name="com.hibernate.Shelf" table="t_shelf" >
<!-- 映射主键 -->
<id name="code">
<generator class="native"></generator>
</id>
</class>
<!--外置命名-->
<query name="queryShelf">
<![CDATA[
select s from Shelf s where s.code>?
]]>
</query>
</hibernate-mapping>
~~~
接下来,代码中就不需要再写hql语句了,但需要注意的是,要使用session的getNameQuery()方法,还要给hql中的问号占位符赋值,这里类似参数化查询的东西,也很好理解。
~~~
<span style="white-space:pre"> </span>List shelfList=session.getNamedQuery("queryShelf").setParameter(0, 1).list();
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Shelf shelf=(Shelf)iter.next();
System.out.println(shelf.getLocation());
}
~~~
## 【过滤器】
过滤器的配置同样也是在配置文件中,这里,我们需要命名过滤器名称和参数名,以及哪个类使用过滤器
~~~
<hibernate-mapping >
<class name="com.hibernate.Shelf" table="t_shelf" >
<!-- 映射主键 -->
<id name="code">
<generator class="native"></generator>
</id>
<filter name="testFilter" condition="code < :myParam"></filter>
</class>
<!-- 过滤器 -->
<filter-def name="testFilter">
<filter-param name="myParam" type="integer"/>
</filter-def>
</hibernate-mapping>
~~~
代码中也和外置命名类似。
~~~
session.enableFilter("testFilter").setParameter("myParam", 2);//在session中都被启用
List shelfList=session.createQuery("from Shelf").list();
for(Iterator iter=shelfList.iterator();iter.hasNext();){
Book book=(Book)iter.next();
System.out.println(book.getName());
}
~~~
## 【小结】
在介绍基本使用方法时,主要是以理解hql的查询原理,不能只停留在会用而已。
外置命名将hql语句抽离出来放到配置文件中,并给了他一个参数名,我们只需要在代码中用这个参数名就可以了。这样如果需求有不太大的变动时,我们就能轻松应对了。
过滤器类似Filter,也是在配置文件中,我们需要开启过滤器,让他帮我们把符合条件的数据过滤出来。但这种方式在面对复杂条件查询的时候可能会不那么方便了。