Spring Data(二)查询

接着上一篇,我们继续讲解Spring Data查询的策略。

查询的生成

查询的构建机制对于Spring Data的基础是非常有用的。构建的机制将截断前缀find…By、read…By、query…By、count…By、get…By等,从剩余的部分开始解析。省略号可以进一步使用distinct等关键字创建查询。第一个By作为分界符,后面的部分将开始解析。最基础的,你可以使用实体中的属性定义条件并且可以使用And或Or连接它们。

方法名字生成查询:

interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname); // 使用distinct关键字构建查询
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname); // Enabling ignoring case for an individual property
List<Person> findByLastnameIgnoreCase(String lastname); // Enabling ignoring case for all suitable properties
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname); // 在查询中使用OrderBy
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

  

解析方法的实际结果取决于持久化的存储,但是其中有一些通用的东西要告诉大家:

  • 表达式通常遍历属性并且使用操作符连接。你可以连接属性使用表达式And或者Or,也可以使用其他的操作符Between、LessThan、GreaterThan、Like等。被支持的操作符非常的广泛,你可以查询适合的相关文档。

  • 方法解析器支持单个属性设置IgnoreCase的标识(例如:findByLastnameIgnoreCase(…)),或者一个类型的所有属性设置ignoring case(例如:findByLastnameAndFirstnameAllIgnoreCase(…))。不管ignoring cases是不是被广大的数据库支持,都要查询指定数据库的相关文档。

  • 你可以使用OrderBy使方法查询排序。

属性表达式

属性表达式仅仅涉及一个被管理实体的属性。在查询生成时,你已经确定解析的属性就是你管理的实体类中的属性。你也可以通过嵌套属性定义约束,假设一个Person类有一个Address类,Address类有一个ZipCode类,方法的命名如下:

List<Person> findByAddressZipCode(ZipCode zipCode);

生成的属性嵌套为:x.address.zipCode。解决的逻辑是从AddressZipCode开始,用这个名字(开头字母小写)去检查属性,如果找到了,就检查这个属性。如果没有找到,将从右侧按照驼峰规则进行分割,分割成一个头和一个尾,然后尝试找到合适的属性,我们的例子中,分割层AddressZip和Code。接着,如果用头找到了合适的属性,会用尾继续向下一层查找,将尾部按照上面的描述那样继续分割。如果第一次分割没有匹配成功,将分割点左移(Address和ZipCode)并继续。

虽然这中逻辑可以为大多数情况下工作,但是它也有可能选择错误的属性。假设Person也有一个addressZip的属性,这种逻辑将匹配第一次分割,选择了错误的属性并最终失败(addressZip没有code字段)。

为了解决中模糊不清的含义,我们可以在方法名字中使用“_”手动创建分割点。所以我们的方法名字如下:

List<Person> findByAddress_ZipCode(ZipCode zipCode);

我们将下划线作为保留字段,我们强烈建议使用java标准的命名规则。

特殊参数的处理

为了在查询中处理参数,你可以按照上面例子中的那样,简单的定义方法参数。除了这些之外,它还可以认识特殊的类型如:Pageable和Sort,他们可以在查询中应用分页和排序。例子如下:

Page<User> findByLastname(String lastname, Pageable pageable);
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);

第一个方法将通过Pageable实例在查询中添加分页,Page接口知道元素的总数和可用的分页。它是通过底层触发count方法进行总数查询,这将会依赖数据库的使用,我们可以使用Slice替换Page。Slice仅仅知道是否有下一个可用的Slice,这样在遍历大结果集是非常足够的。

排序选项也可以通过Pageable实例处理,如果仅仅需要排序,你可以简单在方法中加入Sort参数,返回的是一个简单List。为了找到你的查询有多少页,你必须触发一个额外的count查询,默认的,这个查询是从你触发的那个查询衍生出来的。

限制查询结果

查询方法的结果可以被关键字限制,如:first,top,它们可以被交换使用。后面跟随的数值将制定最大的结果集,如果数字没有设置,将返回一个结果。

用Top和First限制查询结果大小

User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);

限制的表达式也支持Distinct关键字,限制查询的结果集设置到一个实例中,将结果封装到Optional中也是支持的。

如果pagination或者slicing应用到限制的查询分页中,他们也是在限制的结果集中应用。

查询结果流

查询的结果也可以用java8的Stream<T>处理,这样可以使用stream的良好性能。

@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream(); Stream<User> readAllByFirstnameNotNull(); @Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);

  

由于stream使用了底层的资源,在使用后必须关闭,你可以使用close手动关闭,也可以使用java7的try-with-resources 块。

try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
stream.forEach(…);
}

现在并不是所有的Spring Data模块都支持Stream。

异步查询结果

仓库的查询方法可以异步执行,这意味着查询会提交到Spring TaskExecutor,并不会立即执行。

@Async
Future<User> findByFirstname(String firstname); @Async
CompletableFuture<User> findOneByFirstname(String firstname); @Async
ListenableFuture<User> findOneByLastname(String lastname);

第一个方法使用Future作为返回结果。

第二个方法使用java8的CompletableFuture作为返回结果。

第三个方法使用了Spring的ListenableFuture作为返回结果。

生成仓库实例

每一个Spring Data模块都包含一个repositories元素指定Spring 扫描的包路径。

Spring Data的xml配置方式

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"> <repositories base-package="com.acme.repositories" />
</beans:beans>

在上面的例子中,Spring扫描com.acme.repositories和它所有子包中,所有继承了Repository和它子类的所有几口,并将它们构造成仓库。每一个接口被发现,spring都将注册指定的持久化技术并生成合适的代理处理查询方法。每一个bean都是通过接口的名字注册而成,所以UserRepository接口将会注册成userRepository。base-package参数可以使用正则表达式。

使用JavaConfig注解的方式也可以配置包的扫描

@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {
@Bean
EntityManagerFactory entityManagerFactory() { // … }
}

在这里,我们使用Jpa作为例子。

Spring Data的Common模块就介绍到这里,欢迎大家在评论区多多交流。

Spring Data(二)查询的更多相关文章

  1. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  2. spring data jpa查询部分字段、多余附加字段

    spring data jpa查询部分字段 第一种方法:使用 model 查询时转化 首先建立一个 model ,写上自己想要查询的字段,然后写上构造函数,这步很重要,因为spring jpa 转化时 ...

  3. spring data 自定义查询

    spring data 自定义查询 https://www.cnblogs.com/airycode/p/6535635.html 在方法接口上面使用@Query

  4. spring data jpa 查询部分字段列名无效问题

    spring data jpa原生sql查询问题,我只要表其中的几个字段的值,本以为写个原生sql,拿实体类对象去接没问题 结果列名无效,测试了一下,把返回值类型改成List<Object> ...

  5. spring boot系列(五)spring boot 配置spring data jpa (查询方法)

    接着上面spring boot系列(四)spring boot 配置spring data jpa 保存修改方法继续做查询的测试: 1 创建UserInfo实体类,代码和https://www.cnb ...

  6. Spring Data JPA 查询结果返回至自定义实体

    本人在实际工作中使用Spring Data Jpa框架时,一般查询结果只返回对应的Entity实体.但有时根据实际业务,需要进行一些较复杂的查询,比较棘手.虽然在框架上我们可以使用@Query注解执行 ...

  7. spring data jpa 查询自定义字段,转换为自定义实体

    目标:查询数据库中的字段,然后转换成 JSON 格式的数据,返回前台. 环境:idea 2016.3.4, jdk 1.8, mysql 5.6, spring-boot 1.5.2 背景:首先建立 ...

  8. Spring Data @Query查询注解的使用(六)

    按照上一篇文章 我们知道  我们定义的方法  都要根据它的规范进行定义  不然就没法实用 这篇我们讲@Query 查询注解   我们就可以不需要遵循它的方法规则去编写  咱们讲@Query定义到方法上 ...

  9. spring data jpa 查询No property ... found for...Did you mean '...'?

    原文地址:https://blog.csdn.net/earthhour/article/details/79271816 实体类字段定义: private String sku_no; dao中接口 ...

  10. Spring Data Jpa 查询返回自定义对象

    转载请注明出处:http://www.wangyongkui.com/java-jpa-query. 今天使用Jpa遇到一个问题,发现查询多个字段时返回对象不能自动转换成自定义对象.代码如下: //U ...

随机推荐

  1. Tomcat启动出现:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/SpringMvc]]解决办法

    严重: ContainerBase.addChild: start: org.apache.catalina.LifecycleException: Failed to start component ...

  2. sqlite不存在记录则插入数据

    问题:如下图在Sqlite数据库中存在一张Student表,现需要向表中插入数据,如果不存在同名记录则插入,否则不进行插入操作. 解答:利用not exists语句,如下: insert into [ ...

  3. rxjs-流式编程

    前言 第一次接触rxjs也是因为angular2应用,内置了rxjs的依赖,了解之后发现它的强大,是一个可以代替promise的框架,但是只处理promise的东西有点拿尚方宝剑砍蚊子的意思. 如果我 ...

  4. MySQL取得某一范围随机数

    ①直接取值 若要在i ≤ R ≤ j 这个范围得到一个随机整数R ,需要用到表达式 FLOOR(i + RAND() * (j – i + 1)). 例如, 若要在7 到 12 的范围(包括7和12) ...

  5. hdu 2045 递推

    从n>=4开始考虑,只考虑n-1和1的颜色是否相等情况.推出公式F(n)=F(n-1)+2*F(n-2) AC代码: #include<cstdio> const int maxn= ...

  6. POJ - 3087 模拟 [kuangbin带你飞]专题一

    模拟洗牌的过程,合并两堆拍的方式:使先取s2,再取s1:分离成两堆的方式:下面C张放到s1,上面C张到s2.当前牌型与第一次相同时,说明不能搜索到答案. AC代码 #include<cstdio ...

  7. spring boot admin + spring boot actuator + erueka 微服务监控

    关于spring boot actuator简单使用,请看 简单的spring boot actuator 使用,点击这里 spring boot admin 最新的正式版本是1.5.3 与 spri ...

  8. 记Windows10下安装Docker的步骤

    本文主要是记录吾八哥本人在Windows10下安装Docker的过程,当然这些步骤也是在网上搜索查阅资料得知而来的!具体步骤如下: 一.启用Hyper-V 打开控制面板 - 程序和功能 - 启用或关闭 ...

  9. JAVA多线程与并发学习总结

    1.      计算机系统 使用高速缓存来作为内存与处理器之间的缓冲,将运算需要用到的数据复制到缓存中,让计算能快速进行:当运算结束后再从缓存同步回内存之中,这样处理器就无需等待缓慢的内存读写了. 缓 ...

  10. 我的Java设计模式-责任链模式

    今天来说说程序员小猿和产品就关于需求发生的故事.前不久,小猿收到了产品的需求. 产品经理:小猿,为了迎合大众屌丝用户的口味,我们要放一张图,要露点的. 小猿:......露点?你大爷的,让身为正义与纯 ...