基于JPA的Repository使用详解

目录
  • Spring Data JPA
  • Repository
    • CrudRepository
    • PagingAndSortingRepository
    • JpaRepository
    • JpaSpecificationExecutor
  • JpaRepository查询功能
    • Jpa方法命名规则
    • 使用方法
    • 解析过程
  • JPA自定义Repository方法
    • 下面是具体的实现
    • 经过实践发现

Spring Data JPA

Spring Data是Spring提供的操作数据的框架,Spring Data JPA是Spring Data的一个模块,通过Spring data 基于jpa标准操作数据的模块。

Spring Data的核心能力,就是基于JPA操作数据,并且可以简化操作持久层的代码。

它使用一个叫作Repository的接口类为基础,它被定义为访问底层数据模型的超级接口。而对于某种具体的数据访问操作,则在其子接口中定义。

Spring Data可以让我们只定义接口,只要遵循spring data的规范,就无需写实现类,不用写sql语句直接查询数据。

Repository

  • Repository

提供了findBy + 属性 方法

  • CrudRepository

继承了Repository 提供了对数据的增删改查

  • PagingAndSortRepository

继承了CrudRepository 提供了对数据的分页和排序,缺点是只能对所有的数据进行分页或者排序,不能做条件判断

  • JpaRepository: 继承了PagingAndSortRepository

开发中经常使用的接口,主要继承了PagingAndSortRepository,对返回值类型做了适配

  • JpaSpecificationExecutor

提供多条件查询

CrudRepository

CrudRepository继承Repository,添加了一组对数据的增删改查的方法

PagingAndSortingRepository

PagingAndSortingRepository继承CrudRepository,添加了一组分页排序相关的方法

JpaRepository

JpaRepository继承PagingAndSortingRepository,添加了一组JPA规范相关的方法。对继承父接口中方法的返回值进行了适配,因为在父类接口中通常都返回迭代器,需要我们自己进行强制类型转化。而在JpaRepository中,直接返回了List。

开发中最常用JpaRepository

JpaSpecificationExecutor

这个接口比较特殊,单独存在,没有继承以上接口。主要提供了多条件查询的支持,并且可以在查询中添加分页和排序。因为这个接口单独存在,因此需要配合以上说的接口使用。

JpaRepository查询功能

Jpa方法命名规则

JpaRepository支持接口规范方法名查询。意思是如果在接口中定义的查询方法符合它的命名规则,就可以不用写实现,目前支持的关键字如下。

Keyword Sample JPQL snippet
And findByNameAndPwd where name= ? and pwd =?
Or findByNameOrSex where name= ? or sex=?
Is,Equals findById,findByIdEquals where id= ?
Between findByIdBetween where id between ? and ?
LessThan findByIdLessThan where id < ?
LessThanEquals findByIdLessThanEquals where id <= ?
GreaterThan findByIdGreaterThan where id > ?
GreaterThanEquals findByIdGreaterThanEquals where id > = ?
After findByIdAfter where id > ?
Before findByIdBefore where id < ?
IsNull findByNameIsNull where name is null
isNotNull,NotNull findByNameNotNull where name is not null
Like findByNameLike where name like ?
NotLike findByNameNotLike where name not like ?
StartingWith findByNameStartingWith where name like ‘?%'
EndingWith findByNameEndingWith where name like ‘%?'
Containing findByNameContaining where name like ‘%?%'
OrderBy findByIdOrderByXDesc where id=? order by x desc
Not findByNameNot where name <> ?
In findByIdIn(Collection<?> c) where id in (?)
NotIn findByIdNotIn(Collection<?> c) where id not in (?)
True findByAaaTue where aaa = true
False findByAaaFalse where aaa = false
IgnoreCase findByNameIgnoreCase where UPPER(name)=UPPER(?)
top findTop10 top 10/where ROWNUM <=10

使用方法

使用时自定义接口继承JpaRepository,传入泛型,第一个参数为要操作的实体类,第二个参数为该实体类的主键类型

public interface SpuRepository extends JpaRepository<Spu, Long> {
    Spu findOneById(Long id);
    Page<Spu> findByCategoryIdOrderByCreateTimeDesc(Long cid, Pageable pageable);
    Page<Spu> findByRootCategoryIdOrderByCreateTime(Long cid, Pageable pageable);
}

解析过程

1. Spring Data JPA框架在进行方法名解析时

会先把方法名多余的前缀截取掉,比如find,findBy,read,readBy,get,getBy,然后对剩下的部分进行解析。

2. 假设创建如下查询findByCategoryId()

框架在解析该方法时,首先剔除findBy,然后对剩下的属性进行解析,假设查询实体为Spu

(1) 先判断categoryId(根据POJO 规范,首字母变为小写)是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;如果没有该属性,继续第二步;

(2) 从右往左截取第一个大写字母开头的字符串此处为Id),然后检查剩下的字符串是否为查询实体的一个属性,如果是,则表示根据该属性进行查询;

如果没有该属性,则重复第二步,继续从右往左截取;最后假设user为查询实体的一个属性;

(3) 接着处理剩下部分(CategoryId),先判断用户所对应的类型是否有categoryId属性,如果有,则表示该方法最终是根据"Spu.categoryId"的取值进行查询;

否则继续按照步骤2的规则从右往左截取。

(4) 可能会存在一种特殊情况,比如Spu包含一个categoryId 的属性,也有一个 rootCategoryId属性,此时会存在混淆。可以明确在属性之间加上"_" 以显式表达意图,比如 "findByRoot_CategoryId()"

3. 特殊参数

可以直接在方法的参数上加入分页或排序的参数,比如:

Page<Spu> findByCategoryId(Long cid, Pageable pageable);
List<Spu> findByCategoryId(Long cid, Sort sort);

4. JPA的@NamedQueries

(1) 在实体类上使用@NamedQuery

@NamedQuery(name = "Spu.findByRootCategoryId",query = "select s from Spu s where s.rootCategoryId >= ?1")

(2) 在自己实现的DAO的Repository接口里面定义一个同名的方法,示例如下:

public List<Spu> findByRootCategoryId(Long rootCategoryId);

(3) 然后Spring会先找是否有同名的NamedQuery,如果有,那么就不会按照接口定义的方法来解析。

5. 使用@Query

在方法上标注@Query来指定本地查询

参数nativeQuery默认为false,nativeQuery=false时,value参数写的是JPQL,JPQL是用来操作model对象的

@Query(value="select s from Spu s where s.title like %?1" )
public List<Spu> findByTitle(String title);

nativeQuery=true时,value参数写的是原生sql

@Query(value="select * from spu s where s.title like %?1",nativeQuery=true )
public List<Spu> findByTitle(String title);

6. 使用@Param命名化参数

@Query(value = "select s from Spu s where s.title in (:titles)")
List<Spu> findByTitle(@Param("titles") List<String> titles);

JPA自定义Repository方法

如果不使用SpringData的方法,想要自己实现,该怎么办呢?

定义一个接口:声明要添加的, 并自实现的方法

提供该接口的实现类:类名需在要声明的 Repository 后添加 Impl, 并实现方法

声明 Repository 接口, 并继承 1) 声明的接口

注意:默认情况下, Spring Data 会在 base-package 中查找 "接口名Impl" 作为实现类. 也可以通过 repository-impl-postfix 声明后缀.

这张图是类与接口之间的关系

下面是具体的实现

包结构

类与接口之间的关系代码

public interface PersonRepositoiry extends JpaRepository<Person, Integer> ,PersonDao{
public interface PersonDao {
 void test();
}

@Repository
public class PersonRepositoiryImpl implements PersonDao{
 @PersistenceContext
 private EntityManager em;

 @Override
 public void test() {
  //只是用来测试
  Person person = em.find(Person.class, 1);
  System.out.println(person);
 }
}

测试代码

@Test
 public void testCustomerRepositoryMethod() {
  personRepositoiry.test();
 }

经过实践发现

XXXRepositoryImpl 与XXXRepository前面的名字必须相同,后面的也需要按照规则写

若将XXXRepositoryImpl与XXXRepository接口放在同意包下,XXXRepositoryImpl不需要添加@Repository注解,但是当XXXRepositoryImpl与XXXRepository接口不在同一包下,需要在在XXXRepositoryImpl类上加@Repository注解进行修饰

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • JpaRepository 实现简单条件查询

    目录 JpaRepository 简单条件查询 创建持久化类 定义数据访问层接口 定义业务层类 定义控制器类 测试应用 JpaRepository 查询规范 1.JpaRepository支持接口规范方法名查询 2.JpaRepository相关查询功能 a.Spring DataJPA框架在进行方法名解析时 b.假如创建如下的查询 c.特殊的参数 d.也可以使用JPA的NamedQueries,方法如下 e.还可以使用@Query来指定本地查询 f.创建查询的顺序 JpaRepository

  • spring data jpa如何使用自定义repository实现类

    目录 spring data jpa使用自定义repository实现类 创建MyJpaRepository实现类 创建MyJpaRepositoryFactoryBean 配置JPA JPA自定义 Repository 方法 包结构 类与接口之间的关系代码 经过实践发现 spring data jpa使用自定义repository实现类 spring data jpa中使用JpaRepository等接口定义repository时,将默认使用SimpleJpaRepository 可通过自定义

  • spring-data-jpa使用自定义repository来实现原生sql

    目录 使用自定义repository实现原生sql 自定义Repository接口 创建自定义RepositoryFactoryBean SpringDataJpa原生SQL查询 a.首先在StudentRepository里添加如下方法 b.在StudentController里面进行调用以上方法 使用自定义repository实现原生sql Spring Data JPA中的Repository是接口,是JPA根据方法名帮我们自动生成的.但很多时候,我们需要为Repository提供一些自定

  • JPA中JpaRepository接口的使用方式

    目录 JPA JpaRepository接口的使用 SpringData的所有接口 jpa Repository继承自定义接口的主意事项 整体代码如下 解决方案 JPA JpaRepository接口的使用 SpringData的所有接口 CrudRepository接口 ,其中提供了这些方法提供使用,同时继承了其父接口的方法 其中saveAndFlush()方法就相当于hibernate中的saveOrUpdate()和JPA中的merge() @Test public void JpaRep

  • JPA-JpaRepository方法命名语法说明

    目录 前言 JPA的语法分为如下5种: 1.count相关,返回值为int 或 long 2.exists相关,返回值只能是 boolean 3.find相关,返回值是数组List<aaa> 4.findFirst相关,返回值是aaa 5.delete相关,返回值是int,删除行数 前言 梳理了一遍JPA的方法命名语法,记录一下,以便后续备查. 注:本文不介绍JPL语法,版本为spring-data-jpa-2.3.0.RELEASE. 假设实体类名为 aaa,且定义如下: import lo

  • JpaRepository如何实现增删改查并进行单元测试

    目录 JpaRepository增删改查进行单元测试 项目结构 单元测试 SpringDataJPA的Repository理解 repository抽取扩展理解 接下来贴一贴代码 JpaRepository增删改查进行单元测试 项目结构 创建UserInfoDaoI.java文件,继承JpaRepository.(不需要实现类) 根据条件查询/删除 更新 参考此文章进行开发 单元测试 SpringDataJPA的Repository理解 repository抽取扩展理解 在SpringDataJ

  • 基于JPA的Repository使用详解

    目录 Spring Data JPA Repository CrudRepository PagingAndSortingRepository JpaRepository JpaSpecificationExecutor JpaRepository查询功能 Jpa方法命名规则 使用方法 解析过程 JPA自定义Repository方法 下面是具体的实现 经过实践发现 Spring Data JPA Spring Data是Spring提供的操作数据的框架,Spring Data JPA是Sprin

  • spring boot + jpa + kotlin入门实例详解

    spring boot +jpa的文章网络上已经有不少,这里主要补充一下用kotlin来做. kotlin里面的data class来创建entity可以帮助我们减少不少的代码,比如现在这个User的Entity,这是Java版本的: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; private String firstName; private S

  • 基于注解的组件扫描详解

    在使用组件扫描时,需要现在XML配置中指定扫描的路径 <context:component-scan back-package="yangjq.test"> 容器实例化会扫描yangjq.test包及其子包下的所有组件类. 只有当组件类定义前面有下面的注解标记时,这些组件类才会被扫描到Spring容器 - @Component 通用注解 - @Name 通用注解 - @Repository 持久化层组件注解 - @Service 业务层组件注解 - @Controller

  • Spring data jpa的使用与详解(复杂动态查询及分页,排序)

    一. 使用Specification实现复杂查询 (1) 什么是Specification Specification是springDateJpa中的一个接口,他是用于当jpa的一些基本CRUD操作的扩展,可以把他理解成一个spring jpa的复杂查询接口.其次我们需要了解Criteria 查询,这是是一种类型安全和更面向对象的查询.而Spring Data JPA支持JPA2.0的Criteria查询,相应的接口是JpaSpecificationExecutor. 而JpaSpecifica

  • Java Spring-IOC容器与Bean管理之基于注解的方式案例详解

    Spring-IOC容器-Bean管理-基于注解方式 什么是注解? (1)注解是代码特殊标记,格式:@注解名称(属性名称=属性值, 属性名称=属性值-) (2)使用注解,注解作用在类上面,方法上面,属性上面 (3)使用注解目的:简化 xml 配置 Spring 针对 Bean 管理中创建对象提供注解 下面四个注解功能是一样的,都可以用来创建 bean 实例 (1)@Component (2)@Service (3)@Controller (4)@Repository 基于注解方式实现对象创建 ①

  • 基于GORM实现CreateOrUpdate方法详解

    目录 正文 GORM 写接口原理 Create Save Update & Updates FirstOrInit FirstOrCreate 方案一:FirstOrCreate + Assign 方案二:Upsert 总结 正文 CreateOrUpdate 是业务开发中很常见的场景,我们支持用户对某个业务实体进行创建/配置.希望实现的 repository 接口要达到以下两个要求: 如果此前不存在该实体,创建一个新的: 如果此前该实体已经存在,更新相关属性. 根据笔者的团队合作经验看,很多

  • 基于tomcat配置文件server.xml详解

    1. 入门示例:虚拟主机提供web服务 该示例通过设置虚拟主机来提供web服务,因为是入门示例,所以设置极其简单,只需修改$CATALINA_HOME/conf/server.xml文件为如下内容即可.其中大部分都采用了默认设置,只是在engine容器中添加了两个Host容器. <?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SH

  • 基于JavaScript表单脚本(详解)

    什么是表单? 一个表单有三个基本组成部分: 表单标签:这里面包含了处理表单数据所用CGI程序的URL以及数据提交到服务器的方法. 表单域:包含了文本框.密码框.隐藏域.多行文本框.复选框.单选框.下拉选择框和文件上传框等. 表单按钮:包括提交按钮.复位按钮和一般按钮:用于将数据传送到服务器上的CGI脚本或者取消输入,还可以用表单按钮来控制其他定义了处理脚本的处理工作. JavaScript与表单间的关系:JS最初的应用就是用于分担服务器处理表单的责任,打破依赖服务器的局面,尽管目前web和jav

  • 基于AngularJS的简单使用详解

    Angular Js 的初步认识和使用 一: 1.模块化 定义模块和控制器 ng-app="myapp" controller="myctrl" 指定模型 ng-model="" 获取的属性值: ng-bind="属性名"或者{{属性名}} 2.初始化模块(在Script中进行) var myapp1 =angular.module("myapp",[]); 3.定义模块的控制器,并依赖注入, $scope

  • 基于Vue单文件组件详解

    本文将详细介绍Vue单文件组件 概述 在很多 Vue 项目中,使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多中小规模的项目中运作的很好,在这些项目里 JavaScript 只被用来加强特定的视图.但当在更复杂的项目中,或者前端完全由 JavaScript 驱动的时候,下面这些缺点将变得非常明显: 1.全局定义 (Global definitions) 强制要求每个 compon

随机推荐