返回介绍

11.3.1 定义查询方法

发布于 2024-08-17 00:45:49 字数 4460 浏览 0 评论 0 收藏 0

现在,SpitterRepository需要完成的一项功能是根据给定的username查找Spitter对象。比如,我们将SpitterRepository接口修改为如下所示的样子:

这个新的findByUserName()非常简单,但是足以满足我们的需求。现在,该如何让Spring Data JPA提供这个方法的实现呢?

实际上,我们并不需要实现findByUsername()。方法签名已经告诉Spring Data JPA足够的信息来创建这个方法的实现了。

当创建Repository实现的时候,Spring Data会检查Repository接口的所有方法,解析方法的名称,并基于被持久化的对象来试图推测方法的目的。本质上,Spring Data定义了一组小型的领域特定语言(domain-specific language ,DSL),在这里,持久化的细节都是通过Repository方法的签名来描述的。

Spring Data能够知道这个方法是要查找Spitter的,因为我们使用Spitter对JpaRepository进行了参数化。方法名findByUsername确定该方法需要根据username属性相匹配来查找Spitter,而username是作为参数传递到方法中来的。另外,因为在方法签名中定义了该方法要返回一个Spitter对象,而不是一个集合,因此它只会查找一个username属性匹配的Spitter。

findByUsername()方法非常简单,但是Spring Data也能处理更加有意思的方法名称。Repository方法是由一个动词、一个可选的主题(Subject)、关键词By以及一个断言所组成。在findByUsername()这个样例中,动词是find,断言是Username,主题并没有指定,暗含的主题是Spitter。

作为编写Repository方法名称的样例,我们参照名为readSpitterByFirstname-OrLastname()的方法,看一下方法中的各个部分是如何映射的。图11.1展现了这个方法是如何拆分的。

我们可以看到,这里的动词是read,与之前样例中的find有所差别。Spring Data允许在方法名中使用四种动词:getreadfindcount。其中,动词getreadfind是同义的,这三个动词对应的Repository方法都会查询数据并返回对象。而动词count则会返回匹配对象的数量,而不是对象本身。

图11.1 Repository方法的命名遵循一种模式,有助于Spring Data
生成针对数据库的查询

Repository方法的主题是可选的。它的主要目的是让你在命名方法的时候,有更多的灵活性。如果你更愿意将方法称为readSpittersByFirstnameOrLastname()而不是 readByFirstnameOrLastname()的话,那么你尽可以这么做。

对于大部分场景来说,主题会被省略掉。readSpittersByFirstnameOrLastname()与readPuppiesByFirstnameOrLastname()并没有什么差别,它们与readThose ThingsWeWantByFirstnameOrLastname()同样没有什么区别。要查询的对象类型是通过如何参数化JpaRepository接口来确定的,而不是方法名称中的主题。

在省略主题的时候,有一种例外情况。如果主题的名称以Distinct开头的话,那么在生成查询的时候会确保所返回结果集中不包含重复记录。

断言是方法名称中最为有意思的部分,它指定了限制结果集的属性。在readByFirstnameOrLastname()这个样例中,会通过firstname属性或lastname属性的值来限制结果。

在断言中,会有一个或多个限制结果的条件。每个条件必须引用一个属性,并且还可以指定一种比较操作。如果省略比较操作符的话,那么这暗指是一种相等比较操作。不过,我们也可以选择其他的比较操作,包括如下的种类:

IsAfter、After、IsGreaterThan、GreaterThan

IsGreaterThanEqual、GreaterThanEqual

IsBefore、Before、IsLessThan、LessThan

IsLessThanEqual、LessThanEqual

IsBetween、Between

IsNull、Null

IsNotNull、NotNull

IsIn、In

IsNotIn、NotIn

IsStartingWith、StartingWith、StartsWith

IsEndingWith、EndingWith、EndsWith

IsContaining、Containing、Contains

IsLike、Like

IsNotLike、NotLike

IsTrue、True

IsFalse、False

Is、Equals

IsNot、Not

要对比的属性值就是方法的参数。完整的方法签名如下所示:

要处理String类型的属性时,条件中可能还会包含IgnoringCase或IgnoresCase,这样在执行对比的时候就会不再考虑字符是大写还是小写。例如,要在firstname和lastname属性上忽略大小写,那么可以将方法签名改成如下的形式:

需要注意,IgnoringCase和IgnoresCase是同义的,你可以随意挑选一个最合适的。

作为IgnoringCase/IgnoresCase的替代方案,我们还可以在所有条件的后面添加AllIgnoringCase或AllIgnoresCase,这样它就会忽略所有条件的大小写:

注意,参数的名称是无关紧要的,但是它们的顺序必须要与方法名称中的操作符相匹配。

最后,我们还可以在方法名称的结尾处添加OrderBy,实现结果集排序。例如,我们可以按照lastname属性升序排列结果集:

如果要根据多个属性排序的话,只需将其依序添加到OrderBy中即可。例如,下面的样例中,首先会根据lastname升序排列,然后根据firstname属性降序排列:

可以看到,条件部分是通过And或者Or进行分割的。

我们不可能(至少很难)提供一个权威的列表,将使用Spring Data方法命名约定可以编写出来的方法种类全部列出来。但是,如下给出了几个符合方法命名约定的方法签名:

List<Pet> findPetsByBreedIn(List<String> breed)

int countProductsByDiscontinuedTrue()

List<Order> findByShippingDateBetween(Date start, Date end)

我们只是初步体验了所能声明的方法种类,Spring Data JPA会为我们实现这些方法。现在,我们只需知道通过使用属性名和关键字构建Repository方法签名,就能让Spring Data JPA生成方法实现,完成几乎所有能够想象到的查询。

不过,Spring Data这个小型的DSL依旧有其局限性,有时候通过方法名称表达预期的查询很烦琐,甚至无法实现。如果遇到这种情形的话,Spring Data能够让我们通过@Query注解来解决问题。

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

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

发布评论

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