Spring Data JPA框架自定义Repository接口


Posted in Java/Android onApril 28, 2022

自定义Repository接口

要定义一个repository接口,你首先需要自定义一个实体类专用的Repository接口。该接口必须扩展 Repository,并将其类型指定为实体类和实体类的 ID 类型。

如果你想为该实体类资源类型开放CRUD方法,请直接继承CrudRepository而不是Repository。

repository接口定义

通常,你的repository接口会扩展Repository、CrudRepository或PagingAndSortingRepository。

如果你不想扩展Spring Data接口,你也可以用@RepositoryDefinition来注解你的repository接口。

继承CrudRepository接口会公开一套完整的CRUD方法来操作你的实体类对象, 如果你希望自行决定暴露哪些方法,可以从CrudRepository中复制你想暴露的方法到你的自定义的repository接口中即可。

通过以上的操作可以让你在所提供的Spring Data Repositories功能的基础上定义自己的repository接口抽象。

下面通过实例展示了如何有选择地对外开放某些指定的CRUD方法(本例中对外开放findById和save接口方法)。

选择性对外暴露指定CRUD方法让其他人使用

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {
  Optional<T> findById(ID id);
  <S extends T> S save(S entity);
}
interface UserRepository extends MyBaseRepository<User, Long> {
  User findByEmailAddress(EmailAddress emailAddress);
}

在前面的例子中,我们为所有的repository定义了一个通用的基础接口,并暴露了findById(…)以及save(…)方法。

这些方法被路由到Spring Data提供的你所选择的store的基础repository实现(例如,如果你使用JPA,实现就是SimpleJpaRepository),因为它们与CrudRepository中的方法签名一致。所以UserRepository现在可以保存用户,通过ID找到单个用户,并触发查询,通过电子邮件地址找到用户对象。

自定义的中间repository接口上需要添加@NoRepositoryBean。但是请特别注意,在所有Spring Data需要在运行时动态创建实例的repository接口上一定不要添加该注解。

就比如上面的示例代码,

- MyBaseRepository就是中间repository接口, 我们需要使用他来自定义对外开放哪些CRUD方法,需要添加@NoRepositoryBean注解, 这个注解的意思就是一个标记,为了通知JPA不要创建该接口的bean对象

这个@NoRepositoryBean就是用在中间repository接口上的, 但是从中间接口派生出具体的repository接口, 对应上面的示例代码就是UserRepository接口, 在这个接口上一定不要添加@NoRepositoryBean注解,如果添加了, 这个UserRepository接口的bean对象就不会注入到容器中了

使用Repository接口

在多个Spring Data模块中使用Repository接口

在你的应用程序中使用一个唯一的的Spring Data模块使事情变得简单,因为定义范围内的所有存储库接口都绑定到Spring Data模块。有时,应用程序需要使用一个以上的Spring Data模块。在这种情况下,存储库定义必须区分持久化技术。当它检测到类classpath路径下有多个repository factory时,Spring Data会进入严格的respository配置模式。严格的配置使用respository或域类的细节来决定respository定义的Spring Data模块绑定。

如果资源库定义扩展了特定模块的资源库,那么它就是特定Spring Data模块的有效候选者。

如果域类被注解了特定模块的类型注解,它就是特定Spring Data模块的有效候选者。Spring Data模块接受第三方注解(如JPA的@Entity)或提供自己的注解(如Spring Data MongoDB和Spring Data Elasticsearch的@Document)。

下面的例子显示了一个使用特定模块接口的存储库(本例中为 JPA)。

  • 例1. 使用module-specific接口的repository定义
interface MyRepository extends JpaRepository<User, Long> { }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }
interface UserRepository extends MyBaseRepository<User, Long> { … }

MyRepository和UserRepository在其类型层次上扩展了JpaRepository。它们是Spring Data JPA模块的有效候选者。

下面的例子显示了一个使用通用接口的repository接口。

  • 例2. 使用通用接口的repository定义
interface AmbiguousRepository extends Repository<User, Long> { … }
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends CrudRepository<T, ID> { … }
interface AmbiguousUserRepository extends MyBaseRepository<User, Long> { … }

AmbiguousRepository和AmbiguousUserRepository在其类型层次结构中只扩展了Repository和CrudRepository。虽然在使用唯一的Spring Data模块时,这很好,但多个模块无法区分这些repository接口应该被绑定到哪个特定的Spring Data。

下面的例子显示了一个使用带注解的领域类的repository接口。

  • 例3. 使用带注解的domain类的repository定义
interface PersonRepository extends Repository<Person, Long> { … }
@Entity
class Person { … }
interface UserRepository extends Repository<User, Long> { … }
@Document
class User { … }

PersonRepository引用了Person,它被JPA的@Entity注解所注解,所以这个repository接口显然属于Spring Data JPA。UserRepository引用了User,它被Spring Data MongoDB的@Document注释所注解。

下面的坏例子显示了一个使用混合注解的domain类的repository接口。

  • 例4. 使用混合注解的领域类的repository定义
interface JpaPersonRepository extends Repository<Person, Long> { … }
interface MongoDBPersonRepository extends Repository<Person, Long> { … }
@Entity
@Document
class Person { … }

这个例子展示了一个同时使用JPA和Spring Data MongoDB注解的领域类。它定义了两个repository接口:JpaPersonRepository和MongoDBPersonRepository。一个用于JPA,另一个用于MongoDB的使用。Spring Data不再能够区分这些repository接口库,这导致了未定义的行为。

repository接口类型细节和区分domian类注释用于严格的repository接口配置,以确定特定Spring Data模块的repository接口候选者。在同一domain类型上使用多个持久化技术的特定注解是可能的,并且能够在多个持久化技术中重复使用domian类型。然而,Spring Data就不能再确定一个唯一的模块来绑定repository接口了。

区分repository的最后一个方法是通过对repository接口基础包的扫描。基础包定义了扫描repository接口定义的起点,这意味着将repository接口的定义放在适当的包中。默认情况下,注解驱动的配置使用配置类的包。基于XML的配置中的基础包是强制性的。

下面的例子显示了注释驱动的基本包的配置。

  • 例5. 注释驱动的基础包配置
@EnableJpaRepositories(basePackages = "com.acme.repositories.jpa")
@EnableMongoRepositories(basePackages = "com.acme.repositories.mongo")
public class Configuration { 
}

到此这篇关于Spring Data JPA框架快速入门之自定义Repository接口的文章就介绍到这了!


Tags in this post...

Java/Android 相关文章推荐
详解Java实践之建造者模式
Jun 18 Java/Android
分析设计模式之模板方法Java实现
Jun 23 Java/Android
springboot新建项目pom.xml文件第一行报错的解决
Jan 18 Java/Android
Java实现二分搜索树的示例代码
Mar 17 Java/Android
MybatisPlus EntityWrapper如何自定义SQL
Mar 22 Java/Android
零基础学java之方法的定义与调用详解
Apr 10 Java/Android
SpringCloud项目如何解决log4j2漏洞
Apr 10 Java/Android
Java处理延时任务的常用几种解决方案
Jun 01 Java/Android
SpringCloud中分析讲解Feign组件添加请求头有哪些坑梳理
Jun 21 Java/Android
SpringBoot使用ip2region获取地理位置信息的方法
Jun 21 Java/Android
Springboot集成kafka高级应用实战分享
Aug 14 Java/Android
Java中的Kafka为什么性能这么快及4大核心详析
Sep 23 Java/Android
Spring Data JPA框架持久化存储数据到数据库
Spring Data JPA框架的核心概念和Repository接口
Java 多态分析
Java由浅入深通关抽象类与接口(下篇)
Java由浅入深通关抽象类与接口(上篇)
Mybatis-Plus 使用 @TableField 自动填充日期
Apr 26 #Java/Android
Java 写一个简单的图书管理系统
Apr 26 #Java/Android
You might like
php面向对象的方法重载两种版本比较
2008/09/08 PHP
php面向对象全攻略 (三)特殊的引用“$this”的使用
2009/09/30 PHP
php中将时间差转换为字符串提示的实现代码
2011/08/08 PHP
PHP中常用的输出函数总结
2014/09/22 PHP
PHP创建XML的方法示例【基于DOMDocument类及SimpleXMLElement类】
2019/09/10 PHP
网页里控制图片大小的相关代码
2006/06/13 Javascript
javascript入门·图片对象(无刷新变换图片)\滚动图像
2007/10/01 Javascript
javascript prototype,executing,context,closure
2008/12/24 Javascript
javascript实现的在当前窗口中漂浮框的代码
2010/03/15 Javascript
js getBoundingClientRect() 来获取页面元素的位置
2010/11/25 Javascript
javascript定义函数的方法
2010/12/06 Javascript
jQuery蓝色风格滑动导航栏代码分享
2015/08/19 Javascript
jQuery实现向下滑出的平滑下拉菜单效果
2015/08/21 Javascript
jQuery实现的类似淘宝网站搜索框样式代码分享
2015/08/24 Javascript
JavaScript设计模式之单体模式全面解析
2016/09/09 Javascript
详解angular ui-grid之过滤器设置
2017/06/07 Javascript
深入理解ES7的async/await的用法
2017/09/09 Javascript
js取0-9随机取4个数不重复的数字代码实例
2019/03/27 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
详解React 元素渲染
2020/07/07 Javascript
用JavaScript实现贪吃蛇游戏
2020/10/23 Javascript
在vant中使用时间选择器和popup弹出层的操作
2020/11/04 Javascript
[46:25]DOTA2上海特级锦标赛主赛事日 - 4 败者组第五轮 MVP.Phx VS EG第二局
2016/03/05 DOTA
Python基于twisted实现简单的web服务器
2014/09/29 Python
python简单获取数组元素个数的方法
2015/07/13 Python
Python中字符串的处理技巧分享
2016/09/17 Python
Python中__init__.py文件的作用详解
2016/09/18 Python
解决Django Haystack全文检索为空的问题
2020/05/19 Python
Pytorch转keras的有效方法,以FlowNet为例讲解
2020/05/26 Python
美国奢侈品在线团购网站:Gilt City
2017/11/16 全球购物
给男朋友的道歉信
2014/01/12 职场文书
村安全生产责任书
2014/08/25 职场文书
党性锻炼的心得体会
2014/09/03 职场文书
幼儿园见习报告
2014/10/30 职场文书
Redis遍历所有key的两个命令(KEYS 和 SCAN)
2021/04/12 Redis
Python Pygame实战之塔防游戏的实现
2022/03/17 Python