一、自定义方法的规则

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. 一次Spring Transactional嵌套事务使用不同的rollbackFor的分析

    起因: 项目期间由于一次异常回滚问题,发现自己在事务知识方面知识的遗漏,趁着这次机会,做了几次rollbackFor的测试. 测试:   现在有两个事务,事务oute包含事务Inner.事务A回滚规则 ...

  2. 图片转换为base64

    明天中秋了,先祝大家中秋快乐!哈哈,最近见有人在群里问怎么把图片转换成base64格式,之前刚好写过就把代码贴出来. 主要用到canvas中的toDataURL方法 <!DOCTYPE html ...

  3. delphi 备注一些函数

    Delphi的StringReplace 字符串替换函数 function StringReplace (const S, OldPattern, NewPattern: string; Flags: ...

  4. BZOJ 3626: [LNOI2014]LCA(树剖+差分+线段树)

    传送门 解题思路 比较有意思的一道题.首先要把求\(\sum\limits_{i=l}^r dep[lca(i,z)]\)这个公式变一下.就是考虑每一个点的贡献,做出贡献的点一定在\(z\)到根节点的 ...

  5. NX二次开发-UFUN适应窗口UF_VIEW_fit_view

    NX9+VS2012 #include <uf.h> #include <uf_view.h> #include <uf_modl.h> UF_initialize ...

  6. 完美解决 IE6 position:fixed 固定定位问题

    关于 position:fixed; 属性 生成绝对定位的元素,相对于浏览器窗口进行定位. 元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定. pos ...

  7. 创建一个学生表student,默认的表空间为users,字段自定,同时为表的各个字段分别添加合适的约束,然后测试约束的验证状态。

    create table student(id number(4) constraint prim_key primary key,name varchar(8) not null,sex varch ...

  8. POST提交数据之---Content-Type的理解

    Content-Type是指http/https发送信息至服务器时的内容编码类型,contentType用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据. 在网络请求 ...

  9. C++之控制内存分配

    一.内存分配方式 在C++中,内存分成5个区,他们分别是堆.栈.自由存储区.全局/静态存储区和常量存储区.栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释 ...

  10. thinkphp cbd模式

    ThinkPHP从3.0版本开始引入了全新的CBD(核心Core+行为Behavior+驱动Driver)架构模式,因为从底层开始,框架就采用核心+行为+驱动的架构体系,核心保留了最关键的部分,并在重 ...