《Spring Data实战》——2.3 定义Repository

简介: 到目前为止,我们看到了带有查询方法的Repository接口,这些查询有的是从方法名中衍生出来的,有的是手动声明的,这取决于Spring Data为实际存储类型所提供的使用方式。为了衍生出这些查询,我们必须扩展Spring Data的特定标识接口:Repository。

本节书摘来自异步社区《Spring Data实战》一书中的第2章,第2.3节,作者: 【美】Mark Pollack , Oliver Gierke , Thomas Risberg , Jon Brisbin , Michael Hunger著,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.3 定义Repository

到目前为止,我们看到了带有查询方法的Repository接口,这些查询有的是从方法名中衍生出来的,有的是手动声明的,这取决于Spring Data为实际存储类型所提供的使用方式。为了衍生出这些查询,我们必须扩展Spring Data的特定标识接口:Repository。除了查询以外,在你的Repository中还需要一些其他的功能:存储对象,删除对象,根据ID进行查找,返回所有存储的实体或按页对它们进行访问。通过Repository接口来暴露这些功能的最简单方式就是使用一个Spring Data所提供的更为高级的Repository接口。

Repository

一个简单的标识接口,允许Spring Data的基础设施获取用户定义的Repository。

CrudRepository

扩展自Repository并添加了基本的持久化方法如对实体的保存、查找以及删除。

PagingAndSortingRepositories

扩展自CrudRepository并添加了按页访问实体以及根据给定的条件(criteria)进行排序的方法。

假设我们想让CustomerRepository暴露基本的CRUD方法,所需要做就是修改其声明,如示例2-12所示。

示例2-12 暴露CRUD方法的CustomerRepository

screenshot

CrudRepository接口如示例2-13所示。它包括了保存单个实体以及多个Iterable实体的方法、获取单个实体或所有实体的方法以及不同形式的delete(...)方法。

示例2-13 CrudRepository

screenshot

支持Repository方式的每个Spring Data模块都提供了这个接口的实现。因此,我们声明的命名空间元素会触发基础设施,这些设施不仅会启动那些用于执行查询方法的合适代码,同时还会使用一个通用Repository实现类的实例来在背后执行CrudRepository中所声明的方法,最终会将save(...)、findAll()等方法的调用委托给该实例。PagingAndSortingRepository(如示例2-14所示)扩展了CrudRepository并为通用的findAll(...)添加了处理Pageable和Sort实例的方法,从而能够实现逐页访问实体。

示例2-14 PagingAndSortingRepository

screenshot

要将这些功能引入到CustomerRepository中,只需简单地扩展PagingAndSorting Repository来取代CrudRepository即可。

2.3.1 调整Repository接口
正如我们在前面所见,通过扩展合适的Spring Data接口,可以很容易地引入大量预先定义的功能。这种级别的粒度实际上是一种权衡,那就是如果为所有的查找方法、所有的保存方法等都定义单独的接口,我们会暴露接口的数量(以及因此导致的复杂性)以及开发人员使用的便利性之间的权衡。

但是,可能会有这样的场景,那就是只想暴露读方法(CRUD中的R)或者只想在Repository接口中将删除方法屏蔽掉。如今,Spring Data允许定义个性化的基础Repository,只需按照以下的步骤操作即可。

1.创建一个接口,这个接口要么扩展自Repository,要么添加@RepositoryDefinition注解。

2.添加想要暴露的方法并确保它们与Spring Data基础Repository接口所提供的方法签名相同。

3.对于实体所对应的接口声明,要使用这个接口作为基础接口。

为了阐述这一点,假设我们只想暴露接收Pageable的findAll(...)方法以及save方法。这个基础接口看起来可能如示例2-15所示。

示例2-15 自定义基础Repository接口

screenshot

需要注意的一点是我们为这个接口添加了一个额外的注解@NoRepositoryBean,从而确保Spring Data Repository的基础设施不会试图为其创建Bean的实例。让CustomerRepository扩展这个接口就能精确做到只暴露你所定义的API。

接下来可以定义出各种基本的接口(如ReadOnlyRepository或SaveOnlyRepository)甚至组成它们的继承体系,这取决于项目的需要。通常建议本地定义的CRUD方法在开始的时候直接位于每个实体的具体Repository中,必要的话,再将它们要么转移到Spring Data提供的基础Repository中,要么转移到特制的Repository中。按照这种方式,可以保证随着项目复杂性的增长,构件(artifact)的数量能够自然地增长。

2.3.2 手动实现Repository方法
到目前为止,看到了两种类型的Repository方法:CRUD方法和查询方法。每种类型都是由Spring Data的基础设施实现的,要么通过背后的实现类,要么通过查询执行引擎。当构建应用程序的时候,这两种场景可能会覆盖你所面临的很大范围的数据访问操作。但是,有些场景需要手动实现代码。现在,让我们看一下如何做到这一点。

我们开始只实现那些需要手动实现的功能并在实现类中遵循一些命名的约定,如示例2-16所示。

示例2-16 为Repository实现自定义功能

  screenshot

接口和实现类均不需要了解Spring Data的任何事情。它与使用Spring手动实现代码非常类似。按照Spring Data来看,这个代码片段最有意思的地方在于实现类的名字遵循了命名的约定,也就是在核心Repository接口(在我们的场景中就是CustomerRepository)的名字上加Impl后缀。同时需要注意,我们将接口和实现类都设为包内私有(package private),从而阻止从包外访问它们。

最后一步是修改初始Repository接口的声明,使其扩展刚刚引入的接口,如示例2-17所示。

示例2-17 在CustomerRepository中包含自定义功能

screenshot

现在,我们已经将CustomerRepositoryCustom暴露的API引入到CustomerRepository之中了,这会使其成为Customer数据访问API的中心点。客户端代码现在就可以调用CustomerRepository.myCustomMethod(...)了。但是,这个实现类会如何被发现并置于最终执行的代理之中的呢?实际上,Repository的启动过程看起来是这样的。

1.发现repository接口(如CustomerRepository)。

2.尝试寻找一个Bean定义,这个Bean的名字为接口的小写形式并添加Impl后缀(如customerRepositoryImpl)。如果能够找到,就使用它。

3.如果没有找到,我们会扫描寻找一个类,这个类的名字为核心Repository接口的名字并添加Impl后缀(例如,在这个例子中CustomerRepositoryImpl会被找到)。如果找到了这样的类,那么将其注册为Spring Bean并使用它。

4.找到的自定义实现类将会装配到被发现接口的代理配置之中并且在方法调用时会作为潜在的目标类。

这种机制可以很容易地为特定Repository实现自定义代码。用于进行实现查找的后缀可以在XML命名空间中或启用Repository的注解属性中(查看各种存储相关的章节来了解更多)进行个性化设置。

相关文章
|
18天前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
74 6
|
21天前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
54 2
|
1月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
34 9
|
1月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
25 1
|
24天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
61 0
|
1月前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
48 0
|
2月前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
【Java笔记+踩坑】Spring Data JPA
|
3月前
|
Java Spring 数据库
怎样动动手指就能实现数据操作?Spring Data JPA背后的魔法揭秘
【8月更文挑战第31天】在Java开发中,数据库交互至关重要。传统的JDBC操作繁琐且难维护,而Spring Data JPA作为集成JPA的数据访问层解决方案,提供了CRUD等通用操作接口,显著减少代码量。通过继承`JpaRepository`,开发者能轻松实现数据的增删改查,甚至复杂查询和分页也不再困难。本文将通过示例详细介绍如何利用Spring Data JPA简化数据访问层的开发,提升代码质量和可维护性。
41 0
|
3月前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
134 0
|
3月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
154 0
下一篇
无影云桌面