Spring JPA 查询创建

这是JPA内容的核心部分,可以收藏用作参阅文档。

1. 查询转化和关键字

例:一个JPA查询的转化

public interface UserRepository extends Repository<User, Long> {

  List<User> findByEmailAddressAndLastname(String emailAddress, String lastname);
}

我们使用JPA 标准API创建一个查询,但从本质上讲,这将转换为以下查询:select u from User u where u.emailAddress = ?1 and u.lastname = ?2,Spring Data JPA执行属性检查并遍历嵌套属性,如属性表达式中所述。

下表描述了JPA支持的关键字,以及包含该关键字的方法可以转换成什么查询语句:

表:查询关键字及对应查询语句

关键字 样例 JPQL片段(转化的查询语句)
And findByLastnameAndFirstname … where x.lastname = ?1 and x.firstname = ?2
Or findByLastnameOrFirstname … where x.lastname = ?1 or x.firstname = ?2
Is, Equals findByFirstname,findByFirstnameIs,findByFirstnameEquals … where x.firstname = ?1
Between findByStartDateBetween … where x.startDate between ?1 and ?2
LessThan findByAgeLessThan … where x.age < ?1
LessThanEqual findByAgeLessThanEqual … where x.age <= ?1
GreaterThan findByAgeGreaterThan … where x.age > ?1
GreaterThanEqual findByAgeGreaterThanEqual … where x.age >= ?1
After findByStartDateAfter … where x.startDate > ?1
Before findByStartDateBefore … where x.startDate < ?1
IsNull, Null findByAge(Is)Null … where x.age is null
IsNotNull, NotNull findByAge(Is)NotNull … where x.age not null
Like findByFirstnameLike … where x.firstname like ?1
NotLike findByFirstnameNotLike … where x.firstname not like ?1
StartingWith findByFirstnameStartingWith … where x.firstname like ?1 (参数绑定附加 %)
EndingWith findByFirstnameEndingWith … where x.firstname like ?1 (参数绑定附加 %)
Containing findByFirstnameContaining … where x.firstname like ?1 (参数绑定附加 %)
OrderBy findByAgeOrderByLastnameDesc … where x.age = ?1 order by x.lastname desc
Not findByLastnameNot … where x.lastname <> ?1
In findByAgeIn(Collection<Age> ages) … where x.age in ?1
NotIn findByAgeNotIn(Collection<Age> ages) … where x.age not in ?1
True findByActiveTrue() … where x.active = true
False findByActiveFalse() … where x.active = false
IgnoreCase findByFirstnameIgnoreCase … where UPPER(x.firstame) = UPPER(?1)

InNotIn也接受集合的任何子类以及数组作为一个参数或可变参数。对于相同逻辑运算符的其他语法版本,请检查存储库查询关键字。

2. 使用@Query 自定义查询

​ 使用自命名查询声明实体的查询是一种有效的方法,该方法适用于少量查询。由于查询本身绑定到执行它们的Java方法上,实际上可以通过使用Spring Data JPA @Query注释直接绑定,而不用将它们注释到域类。这将域类从特定于持久性的信息中解放出来,并将查询合并到该存储库接口:

​ 注释@Query查询优先于使用@NamedQuery定义的查询和在orm.xml中声明的自命名查询。

例:使用@Query在查询方法上声明查询

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.emailAddress = ?1")
User findByEmailAddress(String emailAddress);
}

3. 使用高级LIKE表达式

​ 使用@Query创建的自命名查询的查询执行机制允许在查询定义中定义高级LIKE表达式,如下面的示例所示:

例:@Query中定义的LIKE表达式

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname like %?1")
List<User> findByFirstnameEndsWith(String firstname);
}

​ 在前面的示例中,识别了LIKE的分隔符字符(%),并将查询转换为有效的JPQL查询(移除%)。在执行查询时,传递给方法调用的参数将使用之前识别的LIKE模式进行扩充。

4. 使用原生查询

​ 将nativeQuery标志设置为true, @Query注释允许运行原生查询,如下面的示例所示:

例:使用@Query在查询方法上声明一个原生查询

public interface UserRepository extends JpaRepository<User, Long> {

  @Query(value = "SELECT * FROM USERS WHERE EMAIL_ADDRESS = ?1", nativeQuery = true)
User findByEmailAddress(String emailAddress);
}

Spring Data JPA目前不支持原生查询的动态排序,因为它必须操作声明的实际查询,而这对本地SQL来说是不可靠的。但是,您可以通过自己指定count查询来对本机查询的结果进行分页,如下面的示例所示:

例:通过使用@Query在查询方法上声明用于分页的本机计数查询

public interface UserRepository extends JpaRepository<User, Long> {

  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
nativeQuery = true)
Page<User> findByLastname(String lastname, Pageable pageable);
}

5.使用Sort

​ 我们可以通过PageRequestSort直接完成排序,SortOrder实例中实际使用的属性需要与您的域模型(持久化模型)匹配。这意味着它们需要解析为查询中使用的属性或别名。JPQL将其定义为状态字段路径表达式。

使用任何不可引用的路径表达式都会导致异常。

​ 但是,使用Sort@Query可以让您插入包含Order BY子句在内的函数非路径检查的Order实例,您可以使用JpaSort。添加可能不安全的排序。

例:使用SortJpaSort

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.lastname like ?1%")
List<User> findByAndSort(String lastname, Sort sort); @Query("select u.id, LENGTH(u.firstname) as fn_len from User u where u.lastname like ?1%")
List<Object[]> findByAsArrayAndSort(String lastname, Sort sort);
} repo.findByAndSort("lannister", new Sort("firstname")); //在域模型中指向属性的有效排序表达式
repo.findByAndSort("stark", new Sort("LENGTH(firstname)")); //包含函数调用的无效排序。Thows 异常
repo.findByAndSort("targaryen", JpaSort.unsafe("LENGTH(firstname)")); //包含显式不安全顺序的有效排序。
repo.findByAsArrayAndSort("bolton", new Sort("fn_len")); //指向别名函数的有效排序表达式。

6.使用(自)命名参数

​ 默认情况下,Spring Data JPA使用基于位置的参数绑定,如上面的所有示例所述,即参数和?的位置一一顺序对应。这使得查询方法在重构参数位置时容易出错。要解决这个问题,可以使用@Param注释为方法参数提供一个具体名称,并在查询中绑定该名称,如下面的示例所示:

例:使用命名参数

public interface UserRepository extends JpaRepository<User, Long> {

  @Query("select u from User u where u.firstname = :firstname or u.lastname = :lastname")
User findByLastnameOrFirstname(@Param("lastname") String lastname,
@Param("firstname") String firstname);
}

这样子就不需要再保证位置的一一对应了,只需要保证名称的对应即可,方法参数根据它们在定义的查询中的顺序进行切换

参考文档

1.翻译:【JPA Query Methods】

Spring JPA 查询创建的更多相关文章

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

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

  2. Spring JPA 定义查询方法

    Spring JPA 定义查询方法 翻译:Defining Query Methods ​ 存储库代理有两种方式基于方法名派生特定域的查询方式: 直接从方法名派生查询 自定义查询方式 ​ 可用选项基于 ...

  3. Spring JPA使用CriteriaBuilder动态构造查询

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://www.cnblogs.com/mzdljgz/p/11495723. ...

  4. spring jpa 自定义查询数据库的某个字段

    spring jpa 提供的查询很强大, 就看你会不会用了. 先上代码, 后面在解释吧 1. 想查单个表的某个字段 在repository中 @Query(value = "select i ...

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

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

  6. Spring JPA学习笔记

    目录 什么是JPA? 引入配置 新建一个Entity Bean类 JPA的增删改查 新建操作接口 新建测试类 总结 什么是JPA? 什么是JDBC知道吧?数据库有Mysql,SQL Server,Or ...

  7. 使用Spring JPA中Page、Pageable接口和Sort类完成分页排序

    显示时,有三个参数,前两个必填,第几页,一页多少个size,第三个参数默认可以不填. 但是发现这个方法已经过时了,通过查看它的源码发现,新方法为静态方法PageRequest of(page,size ...

  8. spring jpa和mybatis整合

    spring jpa和mybatis整合 前一阵子接手了一个使用SpringBoot 和spring-data-jpa开发的项目 后期新加入一个小伙伴,表示jpa相比mybatis太难用,多表联合的查 ...

  9. spring.jpa.open-view问题

    由ReentrantLock和JPA(spring.jpa.open-in-view)导致的死锁问题原因分析. 问题 在压测过程中,发现服务经过一段时间压测之后出现无响应,且无法自动恢复. 分析 从上 ...

随机推荐

  1. 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper

    1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...

  2. (数据科学学习手札92)利用query()与eval()优化pandas代码

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 利用pandas进行数据分析的过程,不仅仅是计算 ...

  3. 致敬平凡的程序员--《SOD框架“企业级”应用数据架构实战》自序

    “简单就是美” “平凡即是伟大” 上面两句话不知道是哪位名人说的,又或者是广大劳动人民总结的,反正我很小的时候就常常听到这两句话,这两句话也成了我的人生格言,而且事实上我也是一个生活过得比较简单的平凡 ...

  4. Java 字节流

    OutputStream此抽象类,是表示输出字节流的所有类的超类.操作的数据都是字节,定义了输出字节流的基本共性功能方法. OutputStream有很多子类,其中子类FileOutputStream ...

  5. 2020-07-06:一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录

    福哥答案2020-07-06:表a和表b的字段都是id和tid,数据类型都是int.查询结果顺序上以 表a 为准.1.JOIN.SELECT * FROM a JOIN b ON a.tid = b. ...

  6. FCOS: Fully Convolutional One-Stage Object Detection

    论文:FCOS: Fully Convolutional One-Stage Object Detection   目录 0.简介 1.网络结构 2.框回归--直接.自由 3.Center-ness ...

  7. 面试中的老大难-mysql事务和锁,一次性讲清楚!

    众所周知,事务和锁是mysql中非常重要功能,同时也是面试的重点和难点.本文会详细介绍事务和锁的相关概念及其实现原理,相信大家看完之后,一定会对事务和锁有更加深入的理解. 本文主要内容是根据掘金小册& ...

  8. SpringMVC常见问题Error configuring application listener of class org.springframework.web.context.ContextLoaderListenejava.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener

    六月 20, 2018 9:43:34 下午 org.apache.catalina.core.StandardContext listenerStart 严重: Error configuring ...

  9. C++用递归实现斐波那契数列

    [题目描述] 菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和. 给出一个正整数a,要求菲波那契数列中第a个数是多少. [输入] 第1行是测试数据的组数n, ...

  10. Kubernetes实战总结 - 自定义Prometheus

    一.概述 首先Prometheus整体监控结构略微复杂,一个个部署并不简单.另外监控Kubernetes就需要访问内部数据,必定需要进行认证.鉴权.准入控制, 那么这一整套下来将变得难上加难,而且还需 ...