站长百科 | 数字化技能提升教程 数字化时代生存宝典
首页
数字化百科
电子书
建站程序
开发
服务器
办公软件
开发教程
服务器教程
软件使用教程
运营教程
热门电子书
WordPress教程
宝塔面板教程
CSS教程
Shopify教程
导航
程序频道
推广频道
网赚频道
人物频道
网站程序
网页制作
云计算
服务器
CMS
论坛
网店
虚拟主机
cPanel
网址导航
WIKI使用导航
WIKI首页
最新资讯
网站程序
站长人物
页面分类
使用帮助
编辑测试
创建条目
网站地图
站长百科导航
站长百科
主机侦探
IDCtalk云说
跨境电商导航
WordPress啦
站长专题
网站推广
网站程序
网站赚钱
虚拟主机
cPanel
网址导航专题
云计算
微博营销
虚拟主机管理系统
开放平台
WIKI程序与应用
美国十大主机
编辑“
HQL
”
人物百科
|
营销百科
|
网赚百科
|
站长工具
|
网站程序
|
域名主机
|
互联网公司
|
分类索引
跳转至:
导航
、
搜索
警告:
您没有登录。如果您做出任意编辑,您的IP地址将会公开可见。如果您
登录
或
创建
一个账户,您的编辑将归属于您的用户名,且将享受其他好处。
反垃圾检查。
不要
加入这个!
[[Image:hibernet.jpg|right|200px|thumb|hibernet[[logo]]]] '''HQL''' 是Hibernate Query Language的简写,即 [[hibernate]] 查询语言:HQL采用[[面向对象]]的查询方式。HQL查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖[[Criteria]]查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的[[封装]]。 == HQL的用法 == 一个完整的HQL语句形式如下: <pre> Select/update/delete……from……where……groupby……having……orderby……asc/desc </pre> 其中的update/delete为Hibernate3中所新添加的功能,可见HQL查询非常类似于标准SQL查询。由于HQL查询在整个Hibernate实体操作体系中的核心地位,这一节我将专门围绕HQL操作的具体技术细节进行讲解。 ===实体查询=== *有关实体查询技术,其实我们在先前已经有多次涉及,比如下面的例子: <pre> String hql=”from User user”; List list=session.CreateQuery(hql).list(); </pre> *上面的代码执行结果是,查询出User实体对象所对应的所有数据,而且将数据封装成User实体对象,并且放入List中返回。这里需要注意的是,Hibernate的实体查询存在着对继承关系的判定 *比如讨论映射实体继承关系中的Employee实体对象,它有两个子类分别是HourlyEmployee,SalariedEmployee,如果有这样的HQL语句:from Employee *当执行检索时Hibernate会检索出所有Employee类型实体对象所对应的数据(包括它的子类HourlyEmployee,SalariedEmployee对应的数据)。 *因为HQL语句与标准SQL语句相似,所以我们也可以在HQL语句中使用where字句,并且可以在where字句中使用各种表达式,比较操作符以及使用“and”,”or”连接不同的查询条件的组合。 <pre> from User user where user.age=20; from User user where user.age between 20 and 30; from User user where user.agein(20,30); from User user where user.name is null; from User user where user.name like‘%zx%’; from User user where(user.age%2)=1; from User user where user.age=20 and user.name like‘%zx%’; </pre> ===实体的更新和删除=== *利用HQL进行实体更新和删除的技术。 *这项技术功能是Hibernate3的新加入的功能,在Hibernate2中是不具备的。 *比如在Hibernate2中,如果我们想将[[数据库]]中所有18岁的用户的年龄全部改为20岁,那么要首先将年龄在18岁的用户检索出来,然后将他们的年龄修改为20岁,最后调用Session.update()语句进行更新。在Hibernate3中对这个问题提供了更加灵活和更具效率的解决办法,如下面的代码: <pre> Transaction trans=session.beginTransaction(); String hql=”update User user set user.age=20 where user.age=18”; Query queryupdate=session.createQuery(hql); intret=queryupdate.executeUpdate(); trans.commit(); </pre> *通过这种方式可以在Hibernate3中,一次性完成批量数据的更新,对性能的提高是相当的可观。同样也可以通过类似的方式来完成delete操作,如下面的代码: <pre> Transaction trans=session.beginTransaction(); Stringhql=”delete from User user where user.age=18”; Queryqueryupdate=session.createQuery(hql); intret=queryupdate.executeUpdate(); trans.commit(); </pre> *这种操作方式在Hibernate3中称为bulkdelete/update,这种方式能够在很大程度上提高操作的灵活性和运行效率,但是采用这种方式极有可能引起[[缓存]]同步上的问题。 ===属性查询=== *很多时候在检索数据时,并不需要获得实体对象所对应的全部数据,而只需要检索实体对象的部分属性所对应的数据。这时候就可以利用HQL属性查询技术,如下面[[程序]]示例: <pre> List list=session.createQuery(“selectuser.namefromUseruser”).list(); for(int i=0;i<list.size();i ){ System.out.println(list.get(i)); } </pre> *只检索了User实体的name属性对应的数据,此时返回的包含结果集的list中每个条目都是String类型的name属性对应的数据。我们也可以一次检索多个属性,如下面程序: <pre> List list=session.createQuery(“select user.name,user.age from User user ”).list(); for(int i=0;i Object[] obj=(Object[])list.get(i); System.out.println(obj[0]); System.out.println(obj[1]); } </pre> *此时返回的结果集list中,所包含的每个条目都是一个Object[]类型,其中包含对应的属性数据值。可能会觉得上面返回Object[]不够符合面向对象风格,可以利用HQL提供的动态构造实例的功能对这些平面数据进行封装,如下面的程序代码: <pre> Listlist=session.createQuery(“selectnewUser(user.name,user.age)fromUseruser”).list(); for(inti=0;i Useruser=(User)list.get(i); System.out.println(user.getName()); System.out.println(user.getAge()); } </pre> 通过动态构造实例对象,对返回结果进行了封装,使程序更加符合面向对象风格,但是这里有一个问题必须注意,那就是这时所返回的User对象,仅仅只是一个普通的Java对象而以,除了查询结果值之外,其它的属性值都为null(包括主键值id),也就是说不能通过[[Session]][对象]]对此对象执行持久化的更新操作。如下面的代码: <pre> Listlist=session.createQuery(“selectnewUser(user.name,user.age)fromUseruser”).list(); for(inti=0;i Useruser=(User)list.get(i); user.setName(“gam”); session.saveOrUpdate(user); //这里将会实际执行一个save操作, //而不会执行update操作,因为这个User对象的id属性为null, //Hibernate会把它作为一个自由对象 //(请参考持久化对象状态部分的论述), //因此会对它执行save操作。 } </pre> ===分组与排序=== *Orderby子句: 与SQL语句相似,HQL查询也可以通过orderby子句对查询结果集进行排序,并且可以通过[[asc]]或者[[desc]]关键字指定排序方式,如下面的代码: <pre>fromUseruserorderbyuser.nameasc,user.agedesc;</pre> 上面HQL查询语句,会以name属性进行升序排序,以age属性进行降序排序,而且与SQL语句一样,默认的排序方式为asc,即升序排序。 *Groupby子句与统计查询: 在HQL语句中同样支持使用groupby子句分组查询,还支持groupby子句结合聚集函数的分组统计查询,大部分标准的SQL聚集函数都可以在HQL语句中使用,比如:count(),sum(),max(),min(),avg()等。如下面的程序代码: <pre> Stringhql=”selectcount(user),user.agefromUserusergroupbyuser.agehavingcount(user)>10”; Listlist=session.createQuery(hql).list(); </pre> *优化统计查询: 假设现在有两张数据库表,分别是customer表和order表,它们的结构如下: <pre> customer IDvarchar2(14) agenumber(10) namevarchar2(20) </pre> <pre> order IDvarchar2(14) order_numbernumber(10) customer_IDvarchar2(14) </pre> 现在有两条HQL查询语句,分别如下: <pre> fromCustomercinnerjoinc.ordersogroupbyc.age;(1) selectc.ID,c.name,c.age,o.ID,o.order_number,o.customer_ID fromCustomercinnerjoinc.orderscgroupbyc.age;(2) </pre> 这两条语句使用了HQL语句的内连接查询,现在可以看出这两条查询语句最后所返回的结果是一样的,但是它们其实是有明显区别的 语句(1)检索的结果会返回Customer与Order持久化对象,而且它们会被置于Hibernate的Session缓存之中,并且Session会负责它们在缓存中的唯一性以及与后台数据库数据的同步,只有事务提交后它们才会从缓存中被清除; 而语句(2)返回的是关系数据而并非是持久化对象,因此它们不会占用Hibernate的Session缓存,只要在检索之后应用程序不在访问它们,它们所占用的[[内存]]就有可能被[[JVM]]的垃圾回收器回收,而且Hibernate不会同步对它们的修改。 ===参数绑定=== Hibernate中对动态查询参数绑定提供了丰富的支持,那么什么是查询参数动态绑定呢?其实如果我们熟悉传统[[JDBC]]编程的话,我们就不难理解查询参数动态绑定,如下代码传统JDBC的参数绑定: <pre> PrepareStatementpre=connection.prepare(“select*fromUserwhereuser.name=?”); pre.setString(1,”zhaoxin”); ResultSetrs=pre.executeQuery(); </pre> 在Hibernate中也提供了类似这种的查询参数绑定功能,而且在Hibernate中对这个功能还提供了比传统JDBC操作丰富的多的特性,在Hibernate中共存在4种参数绑定的方式,下面我们将分别介绍: *按参数名称绑定: 在HQL语句中定义命名参数要用”:”开头,形式如下: <pre> Queryquery=session.createQuery(“fromUseruserwhereuser.name=:customernameanduser:customerage=:age”); query.setString(“customername”,name); query.setInteger(“customerage”,age); </pre> 上面代码中用:customername和:customerage分别定义了命名参数customername和customerage,然后用Query接口的setXXX()方法设定名参数值,setXXX()方法包含两个参数,分别是命名参数名称和命名参数实际值。 *按参数位置邦定: 在HQL查询语句中用”?”来定义参数位置,形式如下: <pre> Queryquery=session.createQuery(“fromUseruserwhereuser.name=?anduser.age=?”); query.setString(0,name); query.setInteger(1,age); </pre> 同样使用setXXX()方法设定绑定参数,只不过这时setXXX()方法的第一个参数代表邦定参数在HQL语句中出现的位置编号(由0开始编号),第二个参数仍然代表参数实际值。 *setParameter()方法: 在Hibernate的HQL查询中可以通过setParameter()方法邦定任意类型的参数,如下代码: <pre> Stringhql=”fromUseruserwhereuser.name=:customername”; Queryquery=session.createQuery(hql); query.setParameter(“customername”,name,Hibernate.STRING); </pre> 如上面代码所示,setParameter()方法包含三个参数,分别是命名参数名称,命名参数实际值,以及命名参数映射类型。对于某些参数类型setParameter()方法可以更具参数值的Java类型,猜测出对应的[[映射]]类型,因此这时不需要显示写出映射类型,像上面的例子,可以直接这样写: query.setParameter(“customername”,name);但是对于一些类型就必须写明映射类型,比如java.util.Date类型,因为它会对应Hibernate的多种映射类型,比如Hibernate.DATA或者Hibernate.TIMESTAMP。 *setProperties()方法: 在Hibernate中可以使用setProperties()方法,将命名参数与一个对象的属性值绑定在一起,如下程序代码: <pre> Customercustomer=newCustomer(); customer.setName(“pansl”); customer.setAge(80); Queryquery=session.createQuery(“fromCustomercwherec.name=:nameandc.age=:age”); query.setProperties(customer); </pre> setProperties()方法会自动将customer对象实例的属性值匹配到命名参数上,但是要求命名参数名称必须要与实体对象相应的属性同名。 还有一个特殊的setEntity()方法,它会把命名参数与一个持久化对象相关联,如下面代码所示: <pre> Customercustomer=(Customer)session.load(Customer.class,”1”); Queryquery=session.createQuery(“fromOrderorderwhereorder.customer=:customer”); query.setProperties(“customer”,customer); Listlist=query.list(); </pre> 上面的代码会生成类似如下的SQL语句: Select*fromorderwherecustomer_ID=’1’; *使用绑定参数的优势: ①、可以利用数据库实施性能优化,因为对Hibernate来说在底层使用的是PrepareStatement来完成查询,因此对于语法相同参数不同的SQL语句,可以充分利用预编译SQL语句缓存,从而提升查询效率。 ②、可以防止SQLInjection安全漏洞的产生 == 相关条目 == *[[SQL]] *[[SQL SERVER]] *[[Hibernet]] *[[JAVA]] == 参考来源 == *http://blog.csdn.net/rigger21/archive/2007/08/09/1733821.aspx *http://www.hudong.com/wiki/hql [[category:数据库|H]] [[category:java|H]] [[category:Hibernate|H]]
摘要:
请注意,您对站长百科的所有贡献都可能被其他贡献者编辑,修改或删除。如果您不希望您的文字被任意修改和再散布,请不要提交。
您同时也要向我们保证您所提交的内容是您自己所作,或得自一个不受版权保护或相似自由的来源(参阅
Wordpress-mediawiki:版权
的细节)。
未经许可,请勿提交受版权保护的作品!
取消
编辑帮助
(在新窗口中打开)