- 译者序
- 前言
- 本书怎么使用
- 本书排版字体约定
- 本书网站
- 致谢
- 第一部分 Hibernate 快速入门
- 第 1 章 安装和设置
- 第 2 章 映射简介
- 第 3 章 驾驭 Hibernate
- 第 4 章 集合与关联
- 第 5 章 更复杂的关联
- 第 6 章 自定义值类型
- 第 7 章 映射标注
- 第 8 章 条件查询
- 第 9 章 浅谈 HQL
- 第二部分 与其他工具的集成
- 第 10 章 将 Hibernate 连接到 MySQL
- 第 11 章 Hibernate 与 Eclipse:Hibernate Tools 使用实战
- 第 12 章 Maven 进阶
- 第 13 章 Spring 入门:Hibernate 与 Spring
- 第 14 章 画龙点睛:用 Stripes 集成 Spring 和 Hibernate
- 附录 A Hibernate 类型
- 附录 B Criteria API
- 附录 C Hibernate SQL 方言
- 附录 D Spring 事务支持
- 附录 E 参考资源
- 作者简介
- 封面介绍
建立查询的更好方法
如本章前面所述,HQL 让你不必使用 JDBC 风格的查询占位符,就能方便地将参数整合到查询中。可以使用命名参数(named parameter)和命名查询(named query)来让程序更易于阅读和维护。
为何在意
命名参数之所以可以让代码更容易理解,是因为不管在查询本身内部,还是在建立查询的 Java 代码内部,都清晰地表达了参数的意图。这种自描述性(self-documenting)的本质就是命名参数的价值所在,同时也减少了引发错误的潜在可能,因为使用命名参数时,你不用计算 SQL 语句中逗号和问号的个数。可以在一个单独的查询中多次使用相同的参数,这样在一定程度上也可以提高程序的性能。
命名查询可以将查询完全从 Java 代码中分离出来。将查询语句和 Java 源代码分离开,会使其更易于阅读和编辑,因为查询语句不再是原来一大堆跨越多行的 Java 字符串序列,且交织着大量的问号、反斜线以及其他 Java 标点符号。第一次输入这样的语句是相当麻烦的,但是如果你需要对这种嵌入在程序中的查询做重要的修改时,就得四处移动问号和加号,尽可能让语句行再次在适当的位置断开。
应该怎么做
对于 Hibernate 而言,这些能力的关键就是 Query 接口。我们在例 3-7 中就已经使用过这个接口,因为从 Hibernate 3 开始,Query 接口是惟一 Hibernate 不反对使用(nondeprecated)的执行查询的接口。所以,和本节介绍的其他功能相比,现在更容易了。
我们先修改查询语句,使用命名参数,如例 3-10 所示。(对于这种只有单一参数的查询语句而言,这并不是什么难事,但宝贵的是从现在起就养成正确的习惯。当你开始为实际的项目打造一大堆难以看清的查询语句时,你会很感激这个习惯的!)
例 3-10:修改查询语句,改用命名参数
public static List tracksNoLongerThan(Time length, Session session){
Query query=session.createQuery("from Track as track"+
"where track.playTime<=:length");
query.setTime("length",length);
return query.list();
}
在查询语句内部,命名参数通过在它们的名称前面加一个冒号“:”作为标识。此处,我们将“?”号替换为":length"。会话对象提供了一个 createQuery()方法,可以返回一个 Query 接口的实现,以供我们使用。为了设置命名参数的值,Query 提供了一整套类型安全的方法。这里,我们传递的是一个 Time 类型的值,所以我们使用了 setTime()方法。即使在如此简单的情况下,和原来的查询语句相比,使用命名参数以后的语法更为自然和方便阅读。如果我们原来传递参数使用的是值和类型的匿名数组(anonymous array)(必需传递多个参数),这样的改进就显得更重要了。此外,我们又多加了一层编译时(compile-time)的类型检查,这总是很受开发人员欢迎的调整。
运行这一版本的程序产生的结果和原来的程序完全相同。
那么,我们怎么将查询语句文本放到 Java 源代码以外呢?同样,这个查询太简单了,以至于这样做的需要不像在实际项目中那样令人印象深刻。但是,这是处理查询语句的最佳方法,所以开始练习吧!就像你预料的那样,我们存放查询语句的地方就是映射文档内部。例 3-11 显示了映射文档中的查询语句。我们必须使用有点笨重的 CDATA 结构,因为查询语句中可能会包含一些破坏 XML 解析器处理的字符(例如,像“<”这样的字符)。
例 3-11:映射文档中的查询语句
<query name="com.oreilly.hh.tracksNoLongerThan">
<![CDATA[
from Track as track
where track.playTime<=:length
]]>
</query>
将这些内容放在 Track.hbm.xml 中类定义的闭合标签(</class>)之后(就在</hibernate-mapping>那一行的前面)。然后,对 QueryTest.java 做最后一次修改,如例 3-12 所示。同样地,程序产生的结果和最初版本完全相同,只是现在组织得更好。如果我们需要使用更复杂的查询,有这些基础已经相当好了。
例 3-12:查询方法的最终版本
public static List tracksNoLongerThan(Time length, Session session){
Query query=session.getNamedQuery(
"com.oreilly.hh.tracksNoLongerThan");
query.setTime("length",length);
return query.list();
}
除了这里探讨的内容以外,Query 接口还有很多其他有用的功能。可以使用接口控制要取回多少条记录(并可以指定特定的记录行)。如果 JDBC 驱动程序支持可滚动的(scrollable)ResultSet,通过 Query 接口也可以使用这一功能。相关更多的细节,可以查阅 JavaDoc 和 Hibernate 的参考手册。
其他
完全不使用类 SQL 语言?或者深入 HQL,探索更为复杂的查询?这两种方法都是本书后面将要介绍的内容。
第 8 章会讨论条件查询(criteria query)。条件查询是一种很有趣的机制,可以让你用普通的 Java API 表达出想要对实体施加的限制条件。这样就可以构建 Java 对象来表示你想要找到的数据,对于非数据库专家来说,这种方法更容易理解。这种方法还可以让你利用 IDE 的代码完成(code completion)功能作为一种辅助编辑方法,甚至可以提供编译时的语法检查。此外,Hibernate 还支持一种“按照例子来查询”(query by example)的方法,就是要找什么对象,先提供与之类似的对象例子。这些对实现应用程序的查询搜索接口都很有帮助。
想多看点 HQL 的 SQL 老手可以跳到第 9 章,那一章将讨论 HQL 的更多其他能力和独特功能。就目前而言,接下来我们要继续探索对象/关系映射中如何处理对象之间的相互关系,这在任何稍复杂的实际应用中都会遇到。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论