返回介绍

在关联中应用条件查询

发布于 2025-04-21 21:42:13 字数 3099 浏览 0 评论 0 收藏 0

到目前为止,在条件查询的构建上,我们看到的都是查询同一个类的各种属性。当然,在真实的系统中,对象之间有丰富的关联关系。有时,我们想用于过滤结果的细节是来源于这些关联。幸好,条件查询 API 提供了一种相当简明的方式可以执行这样的搜索。

应该怎么做

假设我们想找出与特定艺人相关联的所有曲目。我们需要的查询就是检查每个 Track 对象的 artists 属性中包含的值。artists 属性是一个集合,包含与某个曲目相关的所有 Artist 对象的关联。为了让查询过程更有趣些,再假设我们想找到姓名属性匹配特定子字符串(substring)的艺人相关联的所有曲目。

我们在 QueryTest.java 里新增加一个方法来实现这一功能。新增的方法如例 8-16 所示,就放在 tracksNoLongerThan()方法之后。

例 8-16:根据艺人关联来过滤曲目

/**

*Retrieve any tracks associated with artists whose name matches a SQL

*string pattern.

*

*@param namePattern the pattern which an artist's name must match

*@param session the Hibernate session that can retrieve data.

*@return a list of{@link Track}s meeting the artist name restriction.

*/

public static List tracksWithArtistLike(String namePattern, Session session)

{

Criteria criteria=session.createCriteria(Track.class);

Criteria artistCriteria=criteria.createCriteria("artists");❶

artistCriteria.add(Restrictions.like("name",namePattern));❷

artistCriteria.addOrder(Order.asc("name").ignoreCase());❸

return criteria.list();

}

❶前面开始的代码看起来很熟悉,这一行接着再用曲目对象的 artists 属性,又创建了一个 Criteria 实例,附加到我们用于选择曲目的那个 Criteria 实例上。这意味着我们或者可以增加约束到 criteria 上(应用到 Track 自身的属性),或者加到 artistCriteria 上(应用到与曲目关联的 Artist 实体的属性)。

❷在这个例子中,我们只对艺人的信息感兴趣,所以我们将结果限制为与艺人相关联的曲目,这些曲目的艺人中至少要有一个艺人的名称必须匹配指定的模式(再一次,通过将约束应用到两个 Criteria 实例上,我们就能够同时限制 Track 和 Artist 的属性)。

注意:最终,在本书的这一版本中,能够看到我原本期望已久的输出结果。

❸我们要求按艺人的名字排序。编写本书第 1 版时,与当时可以使用的只有尝试性质的 Criteria API 相比,这是 Hibernate3 带来的又一个改进。原来只能够对最外层的条件查询进行排序,但不能对为关联而创建的子条件查询进行排序。如果试图这么做,就会得到一个 UnsupportedOperationException。

为了看到这一查询的执行结果,我们还得做个修改。修改 main()方法,让它调用这个新查询,如例 8-17 所示。

例 8-17:调用新的曲目艺人姓名查询

……

//Ask for a session using the JDBC information we've configured

Session session=sessionFactory.openSession();

try{

//Print tracks associated with an artist whose name ends with"n"

List tracks=tracksWithArtistLike("%n",session);

for(ListIterator iter=tracks.listIterator();

……

现在执行 ant qtest,可以得到例 8-18 所示的结果。

例 8-18:与姓名以字母"n"结尾的艺人相关联的所有曲目

qtest:

[java]Track:"The World'99"(Pulp Victim, Ferry Corsten)00:07:05,

from Digital Audio Stream

[java]Track:"Adagio for Strings(Ferry Corsten Remix)"(William Orbit,

Samuel Barber, Ferry Corsten)00:06:35,from Compact Disc

[java]Track:"Gravity's Angel"(Laurie Anderson)00:06:06,from Compact

Disc

发生了什么事

注意:你也可以为用到的关联建立别名,并在表达式中使用。这会让情形变得更复杂,但是有用。改天研究一下吧。

如果查看这三个曲目的艺人列表,就会发现每个曲目的艺人姓名中至少有一个以"n"结尾,符合我们的要求。另外注意,我们也可以访问与曲目相关联的所有艺人,而并非只限于匹配 name 条件的艺人。这正是预期的效果,也是想要的效果,因为我们已经检索回实际的 Track 实体。你可以调用 setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP)方法来以不同的模式执行条件查询,让它返回一个层次式的 Map 对象的列表,条件查询会将结果过滤到这个 Map 列表的每个层次中。这部分主题已经超出本书讨论的范围,但是在 Hibernate 参考手册和 API 文档中提供了一些示例。

如果供你取回对象的数据表可能含有重复的实体,可以调用 Criteria 对象的 setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)方法,以达到与 SQL 语句的"select distinct"相同的效果。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。