11.3.2 声明自定义查询

假设我们想要创建一个 Repository 方法,用来查找 E-mail 地址是 Gmail 邮箱的 Spitter。有一种方式就是定义一个 findByEmailLike() 方法,然后每次想查找 Gmail 用户的时候就将 “%gmail.com” 传递进来。不过,更好的方案是定义一个更加便利的 findAllGmailSpitters() 方法,这样的话,就不用将 Email 地址的一部分传递进来了:

List<Spitter> findAllGmailSpitters();

不过,这个方法并不符合 Spring Data 的方法命名约定。当 Spring Data 试图生成这个方法的实现时,无法将方法名的内容与 Spitter 元模型进行匹配,因此会抛出异常。 如果所需的数据无法通过方法名称进行恰当地描述,那么我们可以使用 @Query 注解,为 Spring Data 提供要执行的查询。对于 findAllGmailSpitters() 方法,我们可以按照如下的方式来使用 @Query 注解:

@Query("select s from Spitter s where s.email like '%gmail.com'")
List<Spitter> findAllGmailSpitters();

我们依然不需要编写 findAllGmailSpitters() 方法的实现,只需提供查询即可,让 Spring Data JPA 知道如何实现这个方法。可以看到,当使用方法命名约定很难表达预期的查询时,@Query 注解能够发挥作用。如果按照命名约定,方法的名称特别长的时候,也可以使用这个注解。例如,考虑如下的查询方法:

List<Order> findByCustomerAddressZipCodeOrCustomerNameAndCustomerAddressState();

这真的是一个方法的名称!我不得不在返回类型后将其断开,这样才能适应本书页面的宽度。

我承认这是一个有点牵强的例子。但在现实世界中,确实存在这样的需求,使用 Repository 方法所执行的查询会得到一个很长的方法名。在这种情况下,你最好使用一个较短的方法名,并使用 @Query 来指定该方法要如何查询数据库。

对于 Spring Data JPA 的接口来说,@Query 是一种添加自定义查询的便利方式。但是,它仅限于单个 JPA 查询。如果我们需要更为复杂的功能,无法在一个简单的查询中处理的话,该怎么办呢?

Last updated