一、自定义方法的规则

Spring Data JPA框架在进行方法名解析时,会先把方法名多余的前缀截取掉,比如find,findBy,read,readBy,get,getBy,然后对剩下的部分进行解析。
假如创建如下的查询:findByUserDepUuid(),框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为Doc
1:先判断userDepUuid(根据POJO规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;
2:从右往左截取第一个大写字母开头的字符串此处为UUID),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,则重复第二步,继续从右往左截取;最后假设用户为查询实体的一个属性;
3:接着处理剩下部分(DepUuid),先判断用户所对应的类型是否有depUuid属性,如果有,则表示该方法最终是根据“Doc.user.depUuid”的取值进行查询;否则继续按照步骤2的规则从右往左截取,最终表示根据“Doc.user.dep.uuid”的值进行查询。
4:可能会存在一种特殊情况,比如Doc包含一个用户的属性,也有一个userDep属性,此时会存在混合。可以明确在属性之间加上“_”以显式表达意思,比如“findByUser_DepUuid )“或者”findByUserDep_uuid()"
关键词    样品    JPQL片段
IsNotNull findByAgeNotNull ...其中x.age 不为空【年龄不为空】
喜欢 findByNameLike ...其中x.name是什么样的?【模糊查找是......】
不喜欢 findByNameNotLike ...其中x.name不喜欢?【模糊查找不是......】
从...开始 findByNameStartingWith ...其中x.name类似?(参数绑定附加%)【模糊匹配,类似使用%结尾】
EndingWith findByNameEndingWith ...其中x.name类似于?(参数与预置%绑定)【模糊匹配,类似使用%开始】
含 findByNameContaining ...其中x.name like?(参数绑定在%中)[模糊匹配,类似使用%开头和结尾]
排序依据 findByAgeOrderByName ...其中x.age =?order by x.name desc 【查找后排序】
不 findByNameNot ...其中x.name <>?【查找列不是...的】
在 findByAgeIn ...哪里x.age在?
NotIn findByAgeNotIn ...其中x.age不在?
真正 findByActiveTrue ...其中x.avtive = true
产品嫁接 findByActiveFalse ...其中x.active = false
和 findByNameAndAge ...其中x.name =?和x.age =?2
要么 findByNameOrAge ...其中x.name =?或x.age =?2
之间 findBtAgeBetween ...其中x.age之间?和?2
少于 findByAgeLessThan ...其中x.age <?
比...更棒 findByAgeGreaterThan ...其中x.age>?
在那之后 ... ...
一片空白 findByAgeIsNull ...其中x.age为空

自定义查找实例:

    /**
* 根据id查用户
**/
List<User> findByIdOrName(Long id,String name); /**
* 根据id查用户
**/
User queryXXXXByName(String name); /**
* 根据id查name
**/
User readNameById(Long id); /**
* 查年龄为10岁的学生
**/
List<User> getByAge(int age);

三,Spring Data JPA分页查询:

    /**
* 分页查询左右用户
* @param pageable
* @return
*/
Page<User> findAll(Pageable pageable); /**
* 分页查询id不是传入id的用户
* @param id
* @param pageable
* @return
*/
Page<User> findByIdNot(Long id,Pageable pageable);

【注意】分页查询,的结果页,,页接口继承自切片,这个接口有以下方法

public interface Slice<T> extends Iterable<T> {
int getNumber();//返回当前页码 int getSize();//返回当前页大小(可能不是一整页) int getNumberOfElements();//返回当前的元素数量 List<T> getContent();//返回当前页的内容(查询结果) boolean hasContent();//判断是否有内容存在 Sort getSort();//返回排序方式 boolean isFirst();//判断是不是第一页 boolean isLast();//判断是不是最后一页 boolean hasNext();//判断是否还有下一页 boolean hasPrevious();//判断是否上一页 Pageable nextPageable();//返回下一页 Pageable previousPageable();//返回上一页,如果当前已经是第一个,则返回,请求前一个可以是【null】。在调用此方法之前,客户端应该检查是否收到一个非值。 <S> Slice<S> map(Converter<? super T, ? extends S> var1);//用给定的映射,映射当前的内容,为Slice
}
方法名    关键字    SQL
findById 其中id =?
findByIdIs 是 其中id =?
findByIdEquals 等于 其中id =?
findByNameAndAge 和 where name =?和年龄=?
findByNameOrAge 要么 where name =?或年龄=?
findByNameOrderByAgeDesc 按顺序排列 where name =?按年龄顺序排列
findByAgeNotIn 不在 年龄不在(?)
findByStatusTrue 真正 where status = true
findByStatusFalse 假 其中status = false
findByAgeBetween 之间 年龄在哪?和?
findByNameNot 不 名称<>?
findByAgeLessThan 少于 年龄<?
findByAgeLessThanEqual LessThanEqual 年龄<=?
findByAgeGreaterThan 比...更棒 年龄>?
findByAgeGreaterThanEqual GreaterThanEqual 年龄> =?
findByAgeAfter 后 年龄>?
findByAgeBefore 之前 年龄<?
findByNameIsNull 一片空白 其中名称为空
findByNameNotNull 不为空 其中名称不为空
findByNameLike 喜欢 哪里的名字像?
findByNameNotLike 不喜欢 哪里的名字不像?
findByNameStartingWith 从...开始 名称如'?%'
findByNameEndingWith EndingWith 名称如'%?'
findByNameContaining 含 名称如'%?%'

代码中几个复杂的。 
findByNameAndAgeAndSex:表示where name =?和年龄=?和性=? 
findByNameInAndAgeIsNull:表示(?)中的名称和年龄为null  
findByNameAndAgeInAndSexIn:表示where name =?年龄(?)和性别(?)

可以看出关键字是可以连用的,查找都是用findBy +表中列名,表的列名还有关键字等等拼接时,它们的首字母要大写。

二、懒加载引起的no-session解决方法之一,没有页面只有测试用例没有效果

  懒加载造成JPA提供的findOne方法和save 方法在关联表查询和保存时报错;所以适合单表操作,多表可以通过自定义方法分别执行

   保存和更新需要通过@Query的方法执行

三、@Query注解的使用

1. 一个使用@Query注解的简单例子

@Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
List<Book> findByPriceRange(long price1, long price2);

2.  Like表达式

@Query(value = "select name,author,price from Book b where b.name like %:name%")
List<Book> findByNameMatch(@Param("name") String name);

3. 使用Native SQL Query

所谓本地查询,就是使用原生的sql语句(根据数据库的不同,在sql的语法或结构方面可能有所区别)进行查询数据库的操作。

@Query(value = "select * from book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);

4. 使用@Param注解注入参数

@Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
@Param("price") long price);

5. SPEL表达式(使用时请参考最后的补充说明)

'#{#entityName}'值为'Book'对象对应的数据表名称(book)。

public interface BookQueryRepositoryExample extends Repository<Book, Long>{

@Query(value = "select * from #{#entityName} b where b.name=?1", nativeQuery = true)
       List<Book> findByName(String name);

}

6. 一个较完整的例子

public interface BookQueryRepositoryExample extends Repository<Book, Long> {
@Query(value = "select * from Book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);// 此方法sql将会报错(java.lang.IllegalArgumentException),看出原因了吗,若没看出来,请看下一个例子 @Query(value = "select name,author,price from Book b where b.price>?1 and b.price<?2")
List<Book> findByPriceRange(long price1, long price2); @Query(value = "select name,author,price from Book b where b.name like %:name%")
List<Book> findByNameMatch(@Param("name") String name); @Query(value = "select name,author,price from Book b where b.name = :name AND b.author=:author AND b.price=:price")
List<Book> findByNamedParam(@Param("name") String name, @Param("author") String author,
@Param("price") long price); }

7.  解释例6中错误的原因:

因为指定了nativeQuery = true,即使用原生的sql语句查询;否则表名需为实体类对象。使用java对象'Book'作为表名来查自然是不对的。只需将Book替换为表名book。

@Query(value = "select * from book b where b.name=?1", nativeQuery = true)
List<Book> findByName(String name);
@Param入参有此注解,则sql中用:name接收参数;否则用?1的占位符接收参数且顺序也要一致

8.   有同学提出来了,例子5中用'#{#entityName}'为啥取不到值啊?

  先来说一说'#{#entityName}'到底是个啥。从字面来看,'#{#entityName}'不就是实体类的名称么,对,他就是。

  实体类Book,使用@Entity注解后,spring会将实体类Book纳入管理。默认'#{#entityName}'的值就是'Book'。

  但是如果使用了@Entity(name = "book")来注解实体类Book,此时'#{#entityName}'的值就变成了'book'。

  只需要在用@Entity来注解实体类时指定name为此实体类对应的表名。在原生sql语句中,就可以把'#{#entityName}'来作为数据表名使用。

9.  @Modifying注解

    1、在@Query注解中编写JPQL实现DELETE和UPDATE操作的时候必须加上@modifying注解,以通知Spring Data 这是一个DELETE或UPDATE操作。

    2、UPDATE或者DELETE操作需要使用事务,此时需要 定义Service层,在Service层的方法上添加事务操作。  

spring-data-JPA repository自定义方法规则的更多相关文章

  1. spring data jpa方法命名规则

    关键字 方法命名 sql where字句 And findByNameAndPwd where name= ? and pwd =? Or findByNameOrSex where name= ? ...

  2. spring data jpa 使用方法命名规则查询

    按照Spring Data JPA 定义的规则,查询方法以findBy开头,涉及条件查询时,条件的属性用条件关键字连接,要注意的是:条件属性首字母需大写.框架在进行方法名解析时,会先把方法名多余的前缀 ...

  3. Spring Data JPA教程, 第八部分:Adding Functionality to a Repository (未翻译)

    The previous part of my tutorial described how you can paginate query results with Spring Data JPA. ...

  4. 快速搭建springmvc+spring data jpa工程

    一.前言 这里简单讲述一下如何快速使用springmvc和spring data jpa搭建后台开发工程,并提供了一个简单的demo作为参考. 二.创建maven工程 http://www.cnblo ...

  5. 【Spring】Spring Data JPA

    原始JDBC操作数据库 传统JDBC方式实现数据库操作 package com.imooc.util; import java.io.InputStream; import java.sql.*; i ...

  6. spring data jpa(一)

    第1章     Spring Data JPA的快速入门 1.1   需求说明 Spring Data JPA完成客户的基本CRUD操作 1.2   搭建Spring Data JPA的开发环境 1. ...

  7. Spring Data Jpa的四种查询方式

    一.调用接口的方式 1.基本介绍 通过调用接口里的方法查询,需要我们自定义的接口继承Spring Data Jpa规定的接口 public interface UserDao extends JpaR ...

  8. 12 Spring Data JPA:springDataJpa的运行原理以及基本操作(下)

    spring data jpaday1:orm思想和hibernate以及jpa的概述和jpa的基本操作 day2:springdatajpa的运行原理 day2:springdatajpa的基本操作 ...

  9. 黑马程序员spring data jpa 2019年第一版本

    第一步首先创建一个maven工程,导入对于的pom依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xs ...

  10. Spring Data JPA进阶——Specifications和Querydsl

    Spring Data JPA进阶--Specifications和Querydsl 本篇介绍一下spring Data JPA中能为数据访问程序的开发带来更多便利的特性,我们知道,Spring Da ...

随机推荐

  1. BZOJ 3669: [Noi2014]魔法森林(lct+最小生成树)

    传送门 解题思路 \(lct\)维护最小生成树.我们首先按照\(a\)排序,然后每次加入一条边,在图中维护一棵最小生成树.用并查集判断一下\(1\)与\(n\)是否联通,如果联通的话就尝试更新答案. ...

  2. 李宏毅机器学习课程---2、Regression - Case Study

    李宏毅机器学习课程---2.Regression - Case Study 一.总结 一句话总结: 分类讨论可能是比较好的找最佳函数的方法:如果 有这样的因素存在的话 模型不够好,可能是因素没有找全 ...

  3. delphi基础篇之单元文件

    Delphi单元文件 unit MainFrm; {库单元文件头} interface        {接口部分由Interface开始implementation结束.声明引用的单元,常量,数据类型 ...

  4. Python3 From Zero——{最初的意识:007~函数}

    一.编写可接受任意数量参数的函数:*.** >>> def test(x, *args, y, **kwargs): ... pass ... >>> test(1 ...

  5. 网络安全系列 之 TLS/SSL基本原理

    1. TLS/SSL基本工作方式: TLS/SSL的功能实现主要依赖于三类基本算法(参见"网络安全系列 之 密码算法"): 非对称加密算法:实现身份认证和密钥协商 对称加密算法: ...

  6. axios 基本运用

    axios是专门对ajax请求进行封装的一个插件,其返回一个promise对象,用法跟ES6的promise很相似 一.安装axios插件npm install axios 二.引入axios插件 在 ...

  7. CI的session操作

    在使用session之前,要对配置文件config.php 里面的$config['encryption_key']随便赋个值,例如1234 1. 首先要加载session类,固定写法:$this-& ...

  8. MySQL语句基本操作增删改查

    select * from 表名; --------->效率低

  9. HTML 5 基础

    HTML 参考手册 HTML 5 视频 controls 属性供添加播放.暂停和音量控件. <video src="movie.ogg" width="320&qu ...

  10. thinkphp 多层mvc

    hinkPHP基于MVC(Model-View-Controller,模型-视图-控制器)模式,并且均支持多层(multi-Layer)设计. 模型(Model)层 默认的模型层由Model类构成,但 ...