- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第1部分 Spring 的核心
- 第1章 Spring 之旅
- 第2章 装配 Bean
- 第3章 高级装配
- 第4章 面向切面的 Spring
- 第2部分 Web 中的 Spring
- 第5章 构建 Spring Web 应用程序
- 第6章 渲染 Web 视图
- 第7章 Spring MVC 的高级技术
- 第8章 使用 Spring Web Flow
- 第9章 保护 Web 应用
- 第3部分 后端中的 Spring
- 第10章 通过 Spring 和 JDBC 征服数据库
- 第11章 使用对象-关系映射持久化数据
- 第12章 使用 NoSQL 数据库
- 第13章 缓存数据
- 第14章 保护方法应用
- 第4部分 Spring 集成
- 第15章 使用远程服务
- 第16章 使用 Spring MVC 创建 REST API
- 第17章 Spring消息
- 第18章 使用 WebSocket 和 STOMP 实现消息功能
- 第19章 使用 Spring 发送 Email
- 第20章 使用 JMX 管理 Spring Bean
- 第21章 借助 Spring Boot 简化 Spring 开发
12.1.4 编写 MongoDB Repository
为了理解如何使用Spring Data MongoDB来创建Repository,让我们先回忆一下在第11章中是如何使用Spring Data JPA的。在程序清单11.4中,我们创建了一个扩展自JpaRepository的SpitterRepository接口。在那一小节中,我们还启用了Spring Data JPA Repository功能。这样的结果就是Spring Data JPA能够自动创建接口的实现,其中包括了多个内置的方法以及我们所添加的遵循命名约定的方法。
我们已经通过@EnableMongoRepositories注解启用了Spring Data MongoDB的Repository功能,接下来需要做的就是创建一个接口,Repository实现要基于这个接口来生成。不过,在这里,我们不再扩展JpaRepository,而是要扩展MongoRepository。如下程序清单中的OrderRepository扩展了MongoRepository,为Order文档提供了基本的CRUD操作。
程序清单12.6 Spring Data MongoDB会自动实现Repository接口
因为OrderRepository扩展了MongoRepository,因此它就会传递性地扩展Repository标记接口。回忆一下我们在学习Spring Data JPA时所了解的知识,任何扩展Repository的接口将会在运行时自动生成实现。在本例中,并不会实现与关系型数据库交互的JPA Repository,而是会为OrderRepository生成读取和写入数据到MongoDB文档数据库的实现。
MongoRepository接口有两个参数,第一个是带有@Document注解的对象类型,也就是该Repository要处理的类型。第二个参数是带有@Id注解的属性类型。
尽管OrderRepository本身并没有定义任何方法,但是它会继承多个方法,包括对Order文档进行CRUD操作的方法。表12.2描述了OrderRepository继承的所有方法。
表12.2 通过扩展MongoRepository,Repository接口能够继承多个CRUD操作,它们会由Spring Data MongoDB自动实现
方 法 | 描 述 |
long count(); | 返回指定Repository类型的文档数量 |
void delete(Iterable<? extends T); | 删除与指定对象关联的所有文档 |
void delete(T); | 删除与指定对象关联的文档 |
void delete(ID); | 根据ID删除某一个文档 |
void deleteAll(); | 删除指定Repository类型的所有文档 |
boolean exists(Object); | 如果存在与指定对象相关联的文档,则返回true |
boolean exists(ID); | 如果存在指定ID的文档,则返回true |
List<T> findAll(); | 返回指定Repository类型的所有文档 |
List<T> findAll(Iterable<ID>); | 返回指定文档ID对应的所有文档 |
List<T> findAll(Pageable); | 为指定的Repository类型,返回分页且排序的文档列表 |
List<T> findAll(Sort); | 为指定的Repository类型,返回排序后的所有文档列表 |
T findOne(ID); | 为指定的ID返回单个文档 |
Save( terable<s>) ; | 保存指定Iterable中的所有文档 |
save ( < S > ); | 为给定的对象保存一条文档 |
表12.2中的方法使用了传递进来和方法返回的泛型。OrderRepository扩展了MongoRepository<Order, String>,那么T就映射为Order,ID映射为String,而S映射为所有扩展Order的类型。
添加自定义的查询方法
通常来讲,CRUD操作是很有用的,但我们有时候可能希望Repository提供除内置方法以外的其他方法。
在11.3.1小节中,我们学习了Spring Data JPA支持方法命名约定,它能够帮助Spring Data为遵循约定的方法自动生成实现。实际上,相同的约定也适用于Spring Data MongoDB。这意味着我们可以为OrderRepository添加自定义的方法:
这里我们有四个新的方法,每一个都是查找满足特定条件的Order对象。其中第一个用来获取customer属性等于传入值的Order列表;第二个方法获取customer属性like传入值的Order列表;接下来方法会返回customer和type属性等于传入值的Order对象;最后一个方法与前一个类似,只不过customer在对比的时候使用的是like而不是equals。
其中,find这个查询动词并不是固定的。如果喜欢的话,我们还可以使用get作为查询动词:
如果read更适合的话,你还可以使用这个动词:
除此之外,还有一个特殊的动词用来为匹配的对象计数:
与Spring Data JPA类似,在查询动词与By之前,我们有很大的灵活性。例如,我们可以标示要查找什么内容:
其中,Orders这个词没并没有什么特殊之处,它不会影响要获取的内容。我们也可以将方法按照如下的方式命名:
其实,并不是必须要返回List<Order>,如果只想要一个Order对象的话,我们可以只需简单地返回Order:
这里,所返回的就是原本List中的第一个Order对象。如果没有匹配元素的话,方法将会返回null。
指定查询
在11.3.2小节中,@Query注解可以为Repository方法指定自定义的查询。@Query能够像在JPA中那样用在MongoDB上。唯一的区别在于针对MongoDB时,@Query会接受一个JSON查询,而不是JPA查询。
例如,假设我们想要查询给定类型的订单,并且要求customer的名称为“Chuck Wagon”。OrderRepository中如下的方法声明能够完成所需的任务:
@Query中给定的JSON将会与所有的Order文档进行匹配,并返回匹配的文档。需要注意的是,type属性映射成了“?0”,这表明type属性应该与查询方法的第零个参数相等。如果有多个参数的话,它们可以通过“?1”、“?2”等方式进行引用。
混合自定义的功能
在11.3.3小节中,我们学习了如何将完全自定义的方法混合到自动生成的Repository中。对于JPA来说,这还涉及到创建一个中间接口来声明自定义的方法,为这些自定义方法创建实现类并修改自动化的Repository接口,使其扩展中间接口。对于Spring Data MongoDB来说,这些步骤都是相同的。
假设我们想要查询文档中type属性匹配给定值的Order对象。我们可以通过创建签名为List<Order> findByType(String t)的方法,很容易实现这个功能。但是,如果给定的类型是“NET”,那我们就查找type值为“WEB”的Order对象。要实现这个功能的话,这就有些困难了,即便使用@Query注解也不容易实现。不过,混合实现的做法能够完成这项任务。
首先,定义中间接口:
这非常简单。接下来,我们要编写混合实现,具体实现如下面的程序清单所示。
程序清单12.7 将自定义的Repository功能注入到自动生成的Repository中
可以看到,混合实现中注入了MongoOperations(也就是MongoTemplate所实现的接口)。findOrdersByType()方法使用MongoOperations对数据库进行了查询,查找匹配条件的文档。
剩下的工作就是修改OrderRepository,让其扩展中间接口OrderOperations:
将这些关联起来的关键点在于实现类的名称为OrderRepositoryImpl。这个名字前半部分与OrderRepository相同,只是添加了“Impl”后缀。当Spring Data MongoDB生成Repository实现时,它会查找这个类并将其混合到自动生成的实现中。
如果你不喜欢“Impl”后缀的话,那么可以配置Spring Data MongoDB,让其按照名字查找具备不同后缀的类。我们需要做的就是设置@EnableMongoRepositories的属性(在Spring配置类中):
如果使用XML配置的话,我们可以设置<mongo:repositories>的repository-impl-postfix属性:
不管采用哪种方式,我们现在都让Spring Data MongoDB查找名为OrderRepositoryStuff的类,而不再查找OrderRepositoryImpl。
像MongoDB这样的文档数据库能够解决特定类型的问题,但是就像关系型数据库不是全能型数据库那样,MongoDB同样如此。有些问题并不是关系型数据库或文档型数据库适合解决的,不过,幸好我们的选择并不仅限于这两种。
接下来,我们看一下Spring Data如何支持Neo4j,这是一种很流行的图数据库。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论