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. 小白学习Python之路---py文件转换成exe可执行文件

    一.背景 今天闲着无事,写了一个小小的Python脚本程序,然后给同学炫耀的时候,发现每次都得拉着其他人过来看着自己的电脑屏幕,感觉不是很爽,然后我想着网上肯定有关于Python脚本转换成可执行文件的 ...

  2. Django-Model模型Field选项中null和blank的区别

    - Option-**blank**设置为True时代表填写表单的时候可以为空,即在save()执行时此字段可以没有,如果字段没有就在数据库上存储一个空字符串: - Option-**null**设置 ...

  3. 2020-04-06:为什么HashMap不一直使用红黑树?

    红黑树的阈值是8,当链表大于等于8时链表变成了红黑树结构,大大减少了查找的时间. 当长度低于6时会由红黑树转成链表,TreeNodes占用空间是普通Nodes的两倍,所以只有当bin包含足够多的节点时 ...

  4. C#LeetCode刷题之#59-螺旋矩阵 II(Spiral Matrix II)

    目录 问题 示例 分析 问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3678 访问. 给定一个正整数 n,生成一 ...

  5. C#LeetCode刷题之#172-阶乘后的零(Factorial Trailing Zeroes)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3854 访问. 给定一个整数 n,返回 n! 结果尾数中零的数量. ...

  6. C#LeetCode刷题之#876-链表的中间结点(Middle of the Linked List)

    问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/3836 访问. 给定一个带有头结点 head 的非空单链表,返回链 ...

  7. 学习java的第五周

    java流程控制 顺序结构 语句与语句之间,框与框之间是按从上到下的顺序进行的,它是由若干个依次执的处理步骤组成的,它是任何-一个算法都离不开的一种基本算法结构. 选择结构 if结构 if(布尔表达式 ...

  8. HotSpot的垃圾回收算法

    这系列文章只简单介绍一下HotSpot垃圾回收中涉及到的算法及相关的垃圾回收器,并不进行源代码分析,后面会开一个系列对HotSpot的垃圾回收以及内存管理进行源代码解读. 涉及到的垃圾回收算法一共有 ...

  9. three.js 制作逻辑转体游戏(上)

    今天郭先生又出来制作游戏了,最近有小伙伴要做一个逻辑转体小游戏,我怎么能不先来试试呢.玩法可以看上面的连接,下面附几张图.线案例请点击博客原文. 游戏规则不懂得可以看自行百度哈,其实玩起来还挺有难度的 ...

  10. xpath和css选择器对比

    基本语法对比 都可以在html中提取内容,但xpath可以提取xml的内容.