《Spring Data实战》——2.2 定义查询方法

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 如果查询所返回的结果数量增长很明显,那么分块访问数据就很有意义了。为了做到这一点,Spring Data提供了可与Repository一起使用的分页API。要读取哪一块数据的定义隐藏在Pageable接口及其实现PageRequest之中。

本节书摘来自异步社区《Spring Data实战》一书中的第2章,第2.2节,作者: 【美】Mark Pollack , Oliver Gierke , Thomas Risberg , Jon Brisbin , Michael Hunger著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.2 定义查询方法

2.2.1 查找查询的策略
刚才看到的接口只声明了一个简单的查询方法。声明的方法会被基础设施探测到并进行解析,最终衍生出与存储相关的查询。但是,随着查询变得更加复杂,方法名会变得很冗长,显得很笨拙。对于更复杂的查询,依靠方法解析器所支持的关键字就不够了。因此,每种存储模块都提供了@Query注解,如示例2-8所示,它会接受存储相关的查询语言所支持的查询字符串,从而允许查询执行时进一步地定制化。

示例2-8 使用@Query注解手动定义查询

screenshot

在这里,我们使用JPA作为例子并手动定义了一个查询,当然这个查询原本也是可以通过衍生得到的。

查询甚至可以外部化配置到属性文件中(它位于MATA-INF目录下的$store-named- queries.properties文件中),在这里$store是用于替换jpa、mongo以及neo4j等的占位符。key值必须要遵循$domainType.$methodName这样的约定。因此,为了将我们已有的方法替换成外部配置的命名查询,key将会是Customer.findByEmailAddress。如果是使用已命名查询的话,那就不需要使用@Query注解了。

2.2.2 衍生查询
如示例2-9所示,查询衍生机制内置于Spring Data Repository的基础设施之中,对基于Repository的实体来构建限制性的查询很有用处。我们会从方法中截取findBy、readBy以及getBy前缀并解析剩余的部分。一个基础的用法是,基于实体的属性来定义条件并使用And和Or将它们连接起来。

示例2-9 由方法名衍生查询

screenshot

解析的实际结果依赖于我们所使用的数据存储。这里也有一些需要注意的通用事项。表达式通常会是属性的遍历以及操作符,它们可以连接起来。如示例2-9所示的那样,可以通过And以及Or来连接属性表达式。除此之外,对于属性表达式来说,还可以支持各种操作符,如Between、LessThan、GreaterThan以及Like。因为不同的数据存储之间所支持的操作符有所区别,所以要看查阅每种存储对应的章节。

属性表达式
属性表达式可以直接引用所管理实体的属性(如示例2-9中所示)。在查询创建的时候,我们已经确保所解析的属性就是领域类的属性。但是,依然可以遍历嵌套的属性来定义限制条件。在前面我们可以看到,Customer的Address中具有ZipCode属性。在这种情况下,如下这种方法名的查询将会创建x.address.zipCode这样的属性遍历。

screenshot

这个方案的算法首先会将整体(AddressZipCode)作为一个属性进行解析并检查领域类中是否具有该名称的属性(第一个字母小写)。如果它存在的话,就会使用该属性。如果不存在,它会从右边开始将源信息按照“驼峰”命名的规则将其拆分为头部和尾部,然后尝试查找对应的属性(如AddressZip和Code)。如果按照这个头部信息找到了属性,那么我们将会使用尾部的信息继续往下构建树形的信息。因为示例中,第一次的分割并不匹配,我们将分割点继续左移(从“AddressZip、Code”移到“Address、ZipCode”)。

尽管这在大多数的场景下都是可行的,但是在一定情况下算法可能会选择错误的属性。假设Customer同时还有一个addressZip属性。那么我们的算法将会在第一次分割的时候就完成了匹配,这实际上选择了错误的属性,并且会导致最终的失败(因为addressZip类型可能并没有code属性)。为了解决这种模棱两可的问题,可以在方法名中使用下划线(_)来手动定义遍历点。所以,我们的方法名最终看起来是这样的:

screenshot

2.2.3 分页和排序
如果查询所返回的结果数量增长很明显,那么分块访问数据就很有意义了。为了做到这一点,Spring Data提供了可与Repository一起使用的分页API。要读取哪一块数据的定义隐藏在Pageable接口及其实现PageRequest之中。得到的分页数据存放在Page中,它不仅包含了数据本身,还包含了元信息,这些信息包括它是不是第一页或最后一页以及一共有多少页等。为了计算这个元数据,除了初始的查询外,我们需要触发第二次查询。

借助于Repository,我们要使用分页功能时只需添加一个Pageable方法参数即可。不像其他的参数那样,这个参数是不与查询绑定的,用来限制返回的结果集。一种可选的方案就是返回Page类型,它会对结果集进行限制,但是需要另外一次查询来获取元信息(如可用元素的总数)。另一种可选的方案是使用List,它会避免额外的查询,但是不会提供元数据。如果不需要分页功能,只是想要排序,那么可以给方法签名上添加Sort参数,如示例2-10所示。

示例2-10 使用Pageable和Sort的查询方法

screenshot

第一个方法允许传递Pageable实例到查询方法中,从而为静态定义的查询动态地增加分页功能。排序的功能可以通过Sort参数显式地传递给方法,也可以内嵌到PageRequest值对象中,如示例2-11所示。

示例2-11 使用Pageable和Sort

screenshot

相关文章
|
12天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
17 1
|
13天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
23 1
|
18天前
|
存储 安全 Java
|
18天前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
74 6
|
21天前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
54 2
|
1月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
34 9
|
10天前
|
前端开发 Java Spring
Spring MVC源码分析之DispatcherServlet#getHandlerAdapter方法
`DispatcherServlet`的 `getHandlerAdapter`方法是Spring MVC处理请求的核心部分之一。它通过遍历预定义的 `HandlerAdapter`列表,找到适用于当前处理器的适配器,并调用适配器执行具体的处理逻辑。理解这个方法有助于深入了解Spring MVC的工作机制和扩展点。
15 0
|
1月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
25 1
|
24天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
61 0
|
2月前
|
Java 应用服务中间件 Spring
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
IDEA 工具 启动 spring boot 的 main 方法报错。已解决
下一篇
无影云桌面