🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 【含义】 hql,即Hibernate Query  Language。它与我们熟知的sql很类似,它最大的特点就是对查询进行了面向对象的封装,下面会在具体例子中说明。 sql查询的是数据库中的表或字段,而hql是**面向对象**的,具有继承、多态、关联等特性,他针对的是对象。 ## 【使用】 那么如何使用hql进行查询呢?首先,我们需要宏观看一下hql的几种使用方式:**基本使用、外置命名和过滤器。** 基本使用即我们将hql语句写在代码中,执行操作。配置文件的方式是将我们所写的hql语句转移到配置文件中,这样就很容易对其进行修改了。第三种过滤器,类似Struts中的Filter过滤器。它对查询的内容进行过滤,在映射文件中定义过滤器,程序中启用过滤器,并为过滤器参数赋值。 ![](https://box.kancloud.cn/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://box.kancloud.cn/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,也是在配置文件中,我们需要开启过滤器,让他帮我们把符合条件的数据过滤出来。但这种方式在面对复杂条件查询的时候可能会不那么方便了。