Spring Data实战

978-7-115-34370-3
作者: 【美】Mark Pollack Oliver Gierke Thomas Risberg Jon Brisbin Michael Hunger
译者: 张卫滨文建国
编辑: 杜洁
分类: Spring

图书目录:

详情

本书从Spring Data背景知识、关系型数据库、NoSQL、快速应用开发、大数据、数据网格6个方面深度解析了数据访问技术,其中文档数据库、图数据库、键/值存储、Hadoop以及GemFire数据结构是最重要的内容。本书不但阐述了借助Spring Data如何简化NoSQL和大数据的访问,还涵盖了使用Spring Roo和Spring Data REST导出功能如何实现应用的快速开发.

图书摘要

Copyright © 2013 by O’Reilly Media. Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts & Telecom Press, 2013.

Authorized translation of the English edition, 2013 O’Reilly Media, Inc., the owner of all rights to publish

and sell the same.

All rights reserved including the rights of reproduction in whole or in part in any form.

本书中文简体字版由O’Reilly Media, Inc.授权人民邮电出版社出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


数据访问领域正在发生一场变革,关系型数据库无法解决的问题需要新的数据访问技术来解决。Spring Data项目就是一种简化Java应用构建的数据访问技术,它可以帮助开发人员高效地使用最新的数据处理和管理工具,同时还能够以最新的方式使用传统的数据库。

本书从Spring Data背景知识、关系型数据库、NoSQL、快速应用开发、大数据、数据网格6个方面深度解析了数据访问技术,介绍的内容都是最流行和前沿的,其中文档数据库、图数据库、键/值存储、Hadoop以及GemFire数据结构等是最重要的内容。本书介绍了Spring Data、Repository、Querydsl的基础理念,然后阐述了借助Spring Data如何简化NoSQL和大数据的访问,并且涵盖了使用Spring Roo和Spring Data REST导出功能如何实现应用的快速开发,除此之外,书中还涉及与其他Spring子项目的协同工作,如Spring Integration和Spring Batch。

本书面向实战、结构清晰,示例丰富,适用于各类Java开发人员和数据库开发人员,也可以作为各大、中专院校相关专业师生的参考用书和相关培训机构的培训教材。


感谢我的妻子Daniela、我的儿子Gabriel 和Alexandre,因为他们的宽容才使得我 能够挤出时间来撰写这本书。

—Mark Pollack

我要感谢我的家人、朋友、音乐家以及迄今为止与我共同奋斗的每位同事;还有带 来这段精彩旅程的整个Spring Data 和SpringSource 团队;最后,事实上首先要感 谢的是Sabine,她给了我无尽的关爱和支持。

—Oliver Gierke

致我的妻子Carol 和我的儿子Alex,感谢你们让我的人生多姿多彩,并给予我无限 的支持和鼓励。

—Thomas Risberg

致我的妻子Tisha,我的儿子Jack、Ben 和Daniel,我的女儿Morgan 和Hannah, 感谢你们对我的关爱、支持和容忍。如果没有你们,所有的这一切都没有意义。

—Jon Brisbin

特别感谢Rod 和Emil 启动了Spring Data 项目,特别感谢Oliver,他使得这个项目 变得意义非凡。感谢我的家人,你们总是非常支持我疯狂工作;有如此善解人意的 女人在我身边,我心怀感激。

—Michael Hunger

我要感谢我的妻子Nanette 和我的孩子们,他们给予我无限的支持、宽容和理解。 同样要感谢Rod 和Spring Data 团队的同事们,他们使得这一切成为可能。

—David Turanski


我们生活在一个很有意思的时代,新的业务流程驱动着新的需求。我们以前认为理所应当的事情正面临着被颠覆的威胁──其中有一条就是关系型数据库是实现持久化的默认可选方案。尽管这个理念还被广泛认可,但是对于如何更高效地适应新世界,还远远没有明晰。

众多可选的数据存储方案导致了碎片化。Java开发人员以前会将应用中的数据存储到关系型数据库之中,相对于此,新的存储形式需要开发者付出更多的努力才行。

本书将会帮助你解决这个现实问题。它能够帮助你全面了解当前的硬件条件下存储领域的现状,并阐述对于现代的业务问题,NoSQL为什么那么重要。

由于保守的企业级市场对语言的认同度较低(也可能是因为Java对象-关系映射(ORM)解决方案的复杂性),Java开发人员传统上往往不会涉及到NoSQL领域。还好,现在状况发生了变化,进而产生了这本重要和及时的图书。Spring Data是一个重要的项目,它能够帮助开发人员征服新的挑战。

Spring带来了众多价值,因此其成为企业级Java开发人员首选的平台,在持久化方案碎片化的现状下它能够带来特殊的收益。Spring所提供的一部分价值就在于能够以一致的方式集成不同的技术(并不会将所有人拉低到一个最低的通用标准)。独特的“Spring方式(Spring way)”有助于降低开发人员的学习曲线并简化代码的维护。如果你已经熟悉Spring,就会发现Spring Data能够帮助你探索和采用并不是非常熟悉的数据存储形式。如果你对Spring还不熟悉的话,这是一个很好的机会去了解Spring如何简化代码并使其保持更加一致。

本书作者是最有资格阐述Spring Data的人,因为他们就是项目的领导者。他们对Spring有深刻的了解,同时将多种现代数据存储紧密结合了起来。他们很好地阐述了Spring Data背后的驱动力以及如何延续Spring一贯的数据访问方式。另外,本书涵盖了Spring Data如何与其他Spring组成部分协同工作这部分内容,如Spring Integration和Spring Batch。书中还提供了除Spring之外其他很有意义的内容,如Repository的理念、类型安全查询的优点以及为什么Java持久化API(Java Persistence API,JPA)并不适合作为通用的数据访问解决方案。

尽管本书主要讨论的是数据访问而不是NoSQL的使用,但是你也会发现很有价值的NoSQL资料,因为它所介绍的概念和代码可能是你并不熟悉的。所有的内容都是最新的,重要的内容包括文档数据库、图数据库、键/值存储、Hadoop以及Gemfire数据结构。

我们这些编程人员通常追求实用,并且亲手实践时能够学得更好。因此,本书充分考虑到了实用性。在开始的时候,作者首先介绍了如何在业界领先的集成开发环境(Integrated Development Environment,IDE)中运行示例代码,甚至包含了方便学习的屏幕截图,还阐述了数据库驱动方面的需求以及数据库的基本安装过程。他们将代码托管在了GitHub上,这一点我很赞赏,这样每个人都可以对其进行访问和浏览。本书涵盖了众多的主题,所以要设计良好的样例,以便将所有内容尽量关联起来。

本书有一章介绍了Spring Roo,这也能够证明他们是非常重视实际开发的,Spring Roo是Spring提供的快速应用开发(Rapid Application Development,RAD)解决方案。大多数Roo的用户已经熟悉如何将其用于传统的JPA架构之中,作者展示了Roo所带来的生产率提升不仅限于关系型数据库。

读完本书之后,你会深刻理解现代的数据访问为何更加专门化和碎片化、NoSQL数据存储的主要分类、Spring Data如何帮助Java开发人员在新的环境下高效工作以及对于感兴趣的话题要到什么地方去寻找深入学习的资料。但最为重要的是,这是探索代码的绝佳起点。

Rod Johnson

Spring框架创始人


数据访问领域在过去的7年间发生了重要的变化。过去30年间一直占据企业级数据存储和处理核心位置的关系型数据库已经不能再独领风骚了。在过去的7年间诞生了很多可选的数据存储形式,当然也有的面临着消亡,它们被使用到了带有关键任务的企业级应用程序之中。这些新的数据存储形式是为了解决特定的数据访问问题而设计的,使用关系型数据库通常无法高效地解决这些问题。

将关系型数据库推到拐点的一个问题就是扩展性(scale)。试问,我们如何将几百甚至几千TB(terabyte)的数据存储到关系型数据库中?这个问题让我想到了一个笑话,病人说:“大夫,我一这样动就疼”而医生则说:“那就别这样动呗!”暂且把笑话放在一边,存储如此巨量数据的推动力是什么呢?在2001年,IDC报告说“人们创造和复制的数据将会超过1.8ZB(zettabytes),而且每隔两年就会翻番[1]”。新的数据涵盖各种类型,如媒体文件、日志文件、传感器数据(RFID、GPD、遥测设备……)、Twitter上的消息以及Facebook上的帖子。尽管对于企业来讲存储于关系型数据库中的数据依然非常重要,但是这些新型的数据并没有存储在关系型数据库之中。

一般用户所关注的需求是存储大量的媒体文件,而企业却发现存储和分析这些新型数据的重要性。在美国,各行各业的公司所存储的数据超过了100TB,有的公司的数据甚至超过了1PB(petabyte)[2]。大家的共识是持续地分析这些数据会为商业上带来明显的收益。例如,如果产品能够自动汇报其状况,那么公司就可以更容易地掌握产品的行为。为了更好地理解客户,公司在决策制定的过程中可以吸收社交媒体的数据。这甚至引起了主流媒体的报道,例如,Orbitz发现Mac用户偏好较为昂贵的酒店(http://on.wsj.com/UhSlNi),而Target会预测其客户家生孩子的时间(http://www.nytimes.com/2012/02/19/magazine/shopping-habits.html),从而能够在公开的出生记录发布之前给客户邮寄优惠券。

大数据(Big Data)通常指的是这样一种流程:存储大量的数据、保持其原始格式、持续地进行分析并且会与其他的数据源结合起来提供某个领域更深入的理解,这种领域可能是商业上的也可能是自然科学上的。

很多的公司和科研实验室在大数据这个词流行起来之前就开始这样做了。当前的过程与以往的不同在于,智能的数据分析所带来的价值要高于硬件的成本。现在执行这种类型的分析不再需要购买4万美元一颗的CPU了;商用的硬件集群中每颗CPU的价格是1000美元。对于大型的数据集,存储区域网络(Storage Area Network,SAN)以及网络附属存储(Network Attached Storage,NAS)的价格较为昂贵:每GB(gigabyte)是1~10美元,如果复本构建到数据库中而不是硬件之中,那本地磁盘的成本每GB只有0.05美元。对于商用的硬件集群,使用本地磁盘的数据传输率也要比基于SAN或NAS的系统更高──对于相同价格的系统,前者能快500倍。在软件方面,新的数据访问技术大多数都是开源的。尽管开源并不意味着零成本,但是这显然会降低使用门槛,相对于传统的商业软件,它们能够降低采购的整体成本。

另一个能够区分新型数据存储与关系型数据库的问题域就是关系型的数据模型。如果你想分析上百万人的社交图谱,图形数据库更接近这个领域的模型,使用这种数据库难道不是很自然的事情吗?如果需求持续地要求你修改关系型数据库管理系统(RDBMS)的模式(schema)以及对象关系映射(ORM)层,那该怎么办呢?可能“无模式(schema-less)”的文档数据库能够减少对象映射的复杂度,相对于僵化的关系型模型,它所提供的系统更易于演化。尽管每种不同的数据库各有其独特之处,但是可以基于其数据模型进行大致分类。基本的分类情况如下:

/

我们所熟悉的数据模型,类似于哈希表(hashtable)。

列族

扩展的键/值数据模型,值的数据类型也可以是键/值对的序列。

文档

半结构化数据的集合,如XML或JSON。

基于图论,数据模型中包括节点(node)和边(edge),它们都可以包含属性(property)。

这些新的数据库都可以归类在“NoSQL数据库”之下。回顾历史,这个名字尽管朗朗上口,但是并不精确,因为它容易让人觉得这些数据库不能进行查询,但事实并不是这样。它的基本含义是摆脱关系型数据模型以及关系型数据库的ACID特性(原子性、一致性、隔离性以及持久性)。

要摆脱ACID特性的主要驱动力在于,很多的应用程序提高了可扩展写(scaling write)的优先级,并且希望即便系统的某一部分失效,其他部分依然可以继续运作。尽管在关系型数据库中,可以通过在数据库之前使用内存缓存来实现可扩展读,但是进行可扩展写要困难得多。为了标识这类应用程序,通常将其命名为“BASE”系统,在这里缩写代表着基本可用(basically available)、可扩展性(scalable)、最终一致性(eventually consistent)。具有键/值数据模型的分布式数据网格并没有归类到这种新的NoSQL数据库之中。然而,它们提供了与NoSQL数据库类似的特性,如数据的可扩展性以及组合计算能力和数据的分布式计算功能。

从上面简短的介绍中,你能够了解到数据访问的现状,目前正在发生的是一场革命,关注数据的人会非常兴奋。关系型数据库并没有消亡,在很多企业的运作中它依然是核心,并且会持续很长的时间。但是,趋势很明显:新的数据访问技术解决了关系型数据库所无法解决的问题,因此作为开发人员,我们必须要扩充自己的技能,要能够处理这两种技术。

Spring框架长期以来都致力于简化Java应用程序的开发,尤其是使用Java数据库连接(Java Database Connectivity,JDBC)或对象关系映射器编写基于RDBMS的数据访问层方面。在本书中,我们力图帮助开发人员使用这些新技术高效地编写Java应用程序。Spring Data项目直接处理这些新的技术,因此你能够将已有的Spring知识延伸到它们之中,或者通过使用Spring Data,也能够更深入地学习Spring。不过,我们也没有抛弃关系型数据库。Spring Data为了Spring能支持RDBMS扩展了新功能。

本书希望为你提供实用的Spring Data项目的介绍,该项目的目的在于帮助Java开发人员使用最新的数据处理和管理工具,同时能够以最新的方式使用传统的数据库。我们首先会为你介绍这个项目,阐述SpringSource以及该团队背后的驱动力,并描述了示例工程的领域模型,这个例子将会在后面的章节中使用,此外还介绍了如何获取和搭建示例代码(第1章)。

接着将会讨论Spring Data Repository的基本理念,因为它们是后续各种数据存储中都会涉及的通用主题(第2章)。对于Querydsl也是如此,我们将会在第3章中讨论这个话题。这两章为探讨特定存储与Repository的集成以及高级查询功能奠定了坚实的基础。

为了从Java开发人员熟悉的领域开始,我们会用一些时间来介绍传统的持久化技术,如JPA(第4章)和JDBC(第5章)。这两章阐述了在Spring已有的对JPA和JDBC的支持之上,Spring Data的模块提供了什么新特性。

在完成这些之后,将会引入Spring Data项目所支持的NoSQL存储:以MongoDB为例介绍文档数据库(第6章),以Neo4j为例讲解图数据库(第7章),以Redis为例讲解键/值存储(第8章)。列族数据库HBase将会在稍后的章节中介绍(第12章)。这些章节中涵盖的内容包括了将领域类映射到特定存储的数据结构、通过所提供的应用程序编程接口(Application Programming Interface,API)与存储进行便捷地交互以及对Repository抽象的使用。

我们将会介绍Spring Data REST导出器(第10章)以及Spring Roo集成(第9章)。这两章的内容都基于Repository抽象并且能够很容易地将Spring Data所管理的实体导出到Web之中,可以作为表述性状态转移(Representational State Transfer,REST),也可以作为基于Spring Roo所构建的Web应用程序。

接下来本书将会进入大数据的世界──具体来说也就是Hadoop和Spring for Apache Hadoop,我们将会介绍如何使用Hadoop技术实现样例以及Spring Data模块如何明显简化Hadoop的使用(第11章)。基于这些内容,将会使用Spring Batch和Spring Integration项目来构建复杂的大数据管道──这些项目都非常适合于大数据的处理(第12章和第13章)。

最后一章将会讨论Spring Data对GemFire的支持,这是一个分布式的数据网格解决方案(第14章)。

本书中使用了如下的排版约定:

斜体字(Italic

表示新的术语、URL、电子邮箱、文件名以及文件扩展名。

等宽字体(Constant width

用于程序清单,以及在段落中对程序中元素的引用,如变量或函数名、数据库、数据类型、环境变量、语句和关键字。

加粗的等宽字体(Constant width bold

表示需要用户输入的命令或其他文本。

斜体的等宽字体(Constant width italic

表示这些文本需要根据用户提供的值或上下文确定的值进行替换。

这个图标代表提示、建议或一般说明。


这个图标代表警告或提醒。

这本书的目的在于帮助你做好工作。一般来说,可以在程序或文档中使用本书的代码,除非复制了本书中大部分的代码,否则不需要获得我们的许可。例如,如果你写了一个程序,使用了本书中的几段代码是不需要许可的。销售和发行刻有O'Reilly图书中示例的光盘(CD-ROM)则需要得到许可。如果引用本书和利用书中的示例代码来回答问题是不需要许可的。但是,如果在你的产品文档中大量使用本书的示例代码,那么就需要许可了。

我们赞赏大家在使用代码时注明信息来源,但这并不是强求的。信息来源通常要包括标题、作者、出版社以及ISBN。比如“Spring Data by Mark Pollack, Oliver Gierke, Thomas Risberg, Jon Brisbin, and Michael Hunger (O'Reilly). Copyright 2013 Mark Pollack, Oliver Gierke, Thomas Risberg, Jonathan L. Brisbin, and Michael Hun- ger, 978-1-449-32395-0”。

如果你觉得对示例代码的使用超出了合理引用或上面给出的许可范围,可以通过permissions@oreilly.com联系我们。

本书代码示例已发布在GitHub上(https://github.com/SpringSource/spring-data-book)。

Safari在线书店(www.safaribooksonline.com)是应需而变的数字图书馆,它能够以书籍或视频的形式提供专家级的内容(http://www.safaribooksonline.com/content),这些内容来自于世界范围内领先的技术和商业领域的作者。

技术专家、软件开发人员、Web设计师以及商业和创意人士都选择Safari在线书店作为研究、解决问题、学习以及认证培训的主要信息来源。

Safari在线书店针对组织(http://www.safaribooksonline.com/organizations-teams)、政府部门(http://www.safaribooksonline.com/government)以及个人(http://www.safaribooksonline.com/individuals)提供了多种产品(http://www.safaribooksonline.com/subscriptions)以及定价策略。订阅者可以通过一个完全可检索的数据库访问上千种图书、培训视频以及尚未出版的书稿,这些内容来自像O'Reilly Media、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill, Jones & Bartlett、Course Technology这样的几十家出版社(http://www.safaribooksonline.com/publishers)。想了解Safari在线书店的更多信息,请访问在线站点(http://www.safaribooksonline.com/)。

请把对本书的评论和问题发给出版社。

美国:

O'Reilly Media, Inc.
1005 Gravenstein Highway North
Sebastopol, CA 95472

中国:

北京市西城区西直门南大街2号成铭大厦C座807室(100035)
奥莱利技术咨询(北京)有限公司
O'Reilly的每一本书都有专属网页,可以在那找到关于本书的相关信息,包括勘误、样例以及其他信息。可以通过以下地址访问该页面:

http://oreil.ly/spring-data-1e

对于本书的评论和技术性的问题,请发送电子邮件到:

bookquestions@oreilly.com

关于本书的更多信息、会议、资料中心和网站,请访问以下网站:

http://www.oreilly.com

想了解我们的图书、培训课程、会议以及新闻等信息,可以访问我们的主页:

http://www.oreilly.com

http://www.oreilly.com.cn

我们要感谢Rod Johnson和Emil Eifrem,正是他们开启了Spring Data项目。

非常感谢David Turanski的贡献,他帮助我们编写了GemFire这一章。感谢Richard McDougall对大数据的分析,我们在本书的前言中用到了它,感谢Costin Leau帮忙编写Hadoop示例应用程序。

我们还要感谢O'Reilly Media,尤其是带领这个项目的Meghan Blanchette,制作编辑Kristen Borg以及文字编辑Rachel Monaghan。感谢Greg Turnquist、Joris Kuipers、Johannes Hiemer、Joachim Arrasz、Stephan Hochdörfer、Mark Spritzler、Jim Webber、Lasse Westh-Nielsen以及所有为本书提供技术审阅的人。感谢这个项目的社区,你们提交的反馈和缺陷促使我们不断进步。最后,还要特别感谢朋友和家人的宽容、理解和支持。

[1]  IDC; Extracting Value from Chaoshttp://www.emc.com/collateral/analyst-reports/idc-extracting-calue-from-chaos-ar.pdf).2011

[2]  IDC; US Bureau of Labor Statistics


Mark Pollack博士曾在布鲁克黑文国家实验室研究高能物理学方面的大数据解决方案,随后转移到金融服务领域担任前端交易系统的技术领导和架构师。他长期关注软件开发流程的最佳实践和改善,2003年就参与了核心Spring(Java)的开发,并在2004年成立了Microsoft对应的项目也就是Spring.NET。Mark现在领导着Spring Data项目,在使用大数据和NoSQL数据库这些新技术时,这个项目能够简化应用的开发。

Oliver Gierke是SpringSource的工程师,这是VMware[1]的一个子部门,目前他担任Spring Data JPA、MongoDB以及核心模块的领导者。他参与企业级应用和开源项目的开发已经超过了6年,其工作的关注点在软件架构、Spring以及持久化技术方面。他经常在德国以及一些国际会议上进行演讲,写过很多技术文章。

Thomas Risberg目前是Spring Data团队的成员,关注于MongoDB和JDBC扩展项目。他也是Spring框架项目的提交者,主要的贡献在于对JDBC框架的增强。Thomas在VMware的Cloud Foundry团队,为Cloud Foundry所支持的各种框架和语言开发集成方案。他是《Professional Java Development with the Spring Framework》[2]一书的合著者,这本书出版于2005年,作者还包括Rod Johnson、Juergen Hoeller、Alef Arendsen以及Colin Sampaleanu。

Jon Brisbin是SpringSource Spring Data团队的成员,致力于为开发人员提供有用的库,从而简化下一代数据形式的管理。他曾帮忙将Grails GORM的对象映射器转移到基于Java的应用程序之中,并为集成Riak数据存储与RabbitMQ消息代理提供组件。除此之外,他还针对事件应用模型撰写博客并发表演讲,他勤奋工作的领域还包括为前沿的非阻塞模式和传统的基于JVM的应用搭建桥梁。

Michael Hunger长期热衷于软件开发。他尤其关注开发软件的人、软件技艺、编程语言以及代码效率提升。最近两年间,他与Neo Technology协作开发Neo4j图数据库。作为Spring Data Neo4j的领导者,他为对象-图映射开发出了便利且完整的解决方案。他还参与Neo4j云托管。作为一名开发人员,Michael喜欢使用各种编程语言、每天学习新的东西、参与有趣且有前景的开源项目,并且参与编写了多本与编程相关的图书。Michael还是InfoQ活跃的编辑和采访者。

[1]  译者注:目前SpringSource和Cloud Foundry均已经被转移到了Pivotal之中。

[2]  译者注:本书中文名为《Java框架高级编程》。


张卫滨,软件工程师,InfoQ 社区编辑,熟悉Java 语言,对Java 开源框架有一定 研究,如Spring、Hibernate 以及Eclipse 等,熟悉Web 前端开发,了解相关技术以 及jQuery、Dojo、ExtJS 等框架,目前主要从事企业级软件的开发。译有《Spring 实战(第3 版)》以及《Java 应用架构设计:模块化模式与OSGi》。

文建国,系统架构师,精通Spring 等优秀开源技术在企业中的应用,主要研究方 向为云计算、大数据、业务基础平台、分布式等技术。曾参与过中国电信ITSP 3.0 技术架构规范编写,拥有多个大型云计算项目的架构和管理经验。



Spring Data项目是在“Spring One 2010开发者大会”上创建的,该项目起源于当年早些时候Rod Johnson(SpringSource)和Emil Eifrem(Neo Technologies)共同参与的一场黑客会议。他们试图把Neo4j图形数据库整合到Spring框架中,并评估了各种不同的方式。这次会议最终为初始版本的Spring Data Neo4j模块奠定了基础,这个新的SpringSource项目旨在迎合大众对于NoSQL数据存储日益增长的兴趣,而这种趋势一直持续到了今天。

从创立之初,Spring就为传统的数据访问技术提供了完善的支持。不管是使用JDBC、Hibernate、JDO、TopLink还是iBatis作为持久化技术,Spring都大大简化了数据访问层的实现。这种支持主要包括简化基础配置、资源管理并将异常转换成Spring的DataAccessExceptions。这种支持多年以来已经逐渐成熟,最新版本的Spring也对这一层提供了很好的支持。

过去涉及数据持久化时,关系型数据库是可供选择的主要工具,所以Spring对传统数据访问的支持只把关系数据库作为唯一的目标。但随着NoSQL的问世并成为工具箱中可行的替代方案,从支持开发人员的角度来看就有了新的领域需要补充。另一方面,对于传统关系型存储的支持也还有许多需要改善的地方。这两个方面是Spring Data项目的主要驱动力。Spring Data包含NoSQL存储的专有模块以及为关系型数据库提供更好支持的JPA和JDBC模块。

尽管用NoSQL这个术语统称一系列的新型数据存储,但所有的这些存储都有不同的特性和使用场景。具有讽刺意味的是,正是这种缺失特性的特点(缺乏对运行SQL 查询的支持)命名了这一系列数据库。由于这些存储的特征非常不同,所以它们的Java驱动要使用完全不同的API才能充分发挥其特性和功能。如果试图对这些差异进行抽象的话,就会失去每种NoSQL数据存储能带来的收益。图形数据库应该用来存储高度关联的数据;文件数据库应该存储树状以及聚合状的数据结构;如果需要类似缓存的功能和存取模式,那应该选择键/值(key/value)存储。

Java EE(企业版)领域通过JPA提供了持久化API,这个API或许可以当作NoSQL数据库前端实现的候选方案。但是令人遗憾的是,规范的前两句话已经预示了这一点似乎不可能实现:

本文档是关于在Java EE和Java SE中管理持久化和对象/关系映射的Java API规范。这项成果的技术目标是为Java应用开发人员提供一个对象/关系映射机制,借助它可以使用域模型来管理关系型数据库。

这一主题在规范的后面有清晰的体现,它定义了与关系型持久化领域紧密关联的概念和API。@Table注解对NoSQL数据库而言没有太大的意义,@Column@JoinColumn也是如此。在MongoDB这样的存储中如何实现事务API呢?要知道在这些环境中并没有提供跨多文档操作的事务语义。因此在NoSQL存储之上实现JPA层,最好采用一个基于配置文件的API。

另一方面,所有NoSQL存储提供的特殊功能(地理空间功能、map-reduce操作、图形遍历)都需要以专有的方式去实现,因为JPA并没有为它们提供抽象。因此我们可能会以“两边不讨好”(worst-of-both-world)的局面收场:有的部分可以通过JPA来实现,另外还需要使用专有的特性来重新启用与特定存储相关的功能。

上文排除了采用JPA作为这些存储的抽象API的可能性。Spring生态系统中的各种项目为开发人员带来了高效率以及一致的编程模型,我们依然希望将其用于简化对NoSQL存储的使用。为此,Spring Data团队发布了如下使命宣言:

针对NoSQL和关系型存储,Spring Data提供了基于Spring的熟知且一致的编程模型,同时保留特定存储的特性和功能。

因此,我们决定采取略有不同的方法。不再试图以单一的API将所有存储抽象化。相反,Spring Data项目对不同的存储实现都提供一致的编程模型,并使用了在Spring框架中大家已熟悉的模式和抽象。这样,在使用不同的存储时,会有一致的体验。

Spring Data的核心目标是:支持对所有的存储进行资源配置,从而实现对该存储的访问。这种支持主要是通过XML命名空间和Spring JavaConfig的支持类实现的,这可以使我们轻松地对Mongo数据库、嵌入式Neo4j实例等建立访问。除此之外,它也集成了Spring的核心功能,如JMX。这意味着某些存储可以通过原生API暴露统计数据,这些数据将会由Spring Data暴露给JMX。

大部分的NoSQL Java API并未支持将领域对象映射到存储的数据抽象(MongoDB中的文件,Neo4j中的节点与关系)。因此,当使用原生的Java驱动程序进行读取和写入操作时,通常需要编写大量的代码来将数据映射到应用程序的领域对象。所以Spring Data模块最核心的部分是一个映射和转换的API,用来获取要持久化的领域类中的元数据,使得任意领域对象都可以转换成存储用的数据类型。

在此基础上,就如同著名的Spring JdbcTemplate、JmsTemplate等,我们也会看到以模板模式实现的API,其中包括RedisTemplate、MongoTemplate等。或许你已经知道,这些模板提供了让我们可以执行常用操作的辅助方法。例如:在一条语句中持久化一个对象的时候,能够自动进行资源管理和异常处理。此外,还提供了回调接口的API,允许在资源管理和异常处理过程中使用存储原生的API,以提高灵活性。

这些功能给我们提供了一个工具箱,使得我们可以像使用传统的数据库那样来实现数据访问层。后面的章节将会详细介绍这些功能。为了让程序变得更简单,Spring Data还在模板实现的基础上提供了一个存储(repository)抽象,这将减少数据访问对象在实现一个普通接口时去定义通用场景的代价,如标准的CRUD(创建、读取、更新、删除)操作以及执行存储支持的查询语句。事实上,这种抽象位于最顶层,而且它会尽可能在合理范围内将不同存储API融合在一起。因此,存储的操作将拥有许多共同点。这也是后面会有专门的章节(第2章)来介绍基本编程模型的原因。

接着,我们来看一下用来展示这些特定存储模块功能所用的示例代码和领域模型。

为了说明各种Spring Data模块的用法,我们会使用电子商务部门的示例领域(如图1-1所示)。由于各种NoSQL数据存储通常具有特定的功能和适用场景,在个别章节会对领域的实现方式做出一些调整,甚至只有它的部分实现,这种做法不代表必须以一种特定的方法来实现领域,而是强调某些存储应该更适用于特定的应用场景。

在模型的核心,有客户(customer),包含客户的基本资料,如姓、名、电子邮箱地址、地址(一组包含街道、城市和国家的集合),还有由产品名称、描述、价格和其他属性构成的产品(product)。这些抽象是组成CRM(客户关系管理系统)和库存系统的基础。最重要的是客户可以订购订单(Order),订单信息包含订购的客户、邮寄和付款地址、订购时间、订单状态和一组商品明细。而这些商品明细又包含一个特定的产品、订购的数量和产品的价格。

图1-1 领域模型

本书的示例代码可从GitHub(https://github.com/SpringSource/spring-data-book)上获取。它是一个Maven项目,包含每一章的模块。另外,还需要在电脑中安装Maven 3或者一个能导入Maven项目的IDE,比如Spring Tool Suite(STS)。从下面的操作中可以看到,取得示例代码就如同复制版本库一样简单:

现在可以在命令行中执行Maven来构建代码:

这样Maven会解析依赖、编译和测试代码,执行测试,最终打包模块。

STS/Eclipse

由于STS已经配备了m2eclipse插件,所以可以在IDE中轻松使用Maven项目。如果已经下载并安装(详情请见第3章)了STS,即可从File菜单选择Import选项,并在弹出的对话框中选择Existing Maven Projects,如图1-2所示。

图1-2 导入Maven项目到Eclipse(步骤1/2)

在下一个窗口中,单击Browse按钮来选择刚刚签出的示例项目的文件夹。之后,在正下方的窗格中会列出并选中各个Maven模块(如图1-3所示)。单击Finish按钮进行下一步,STS会将选中的Maven模块导入到工作区。它将依照模块根目录下的pom.xml文件来解析所需的依赖和源文件夹。

图1-3 将Maven项目导入到Eclispe(步骤2/2)

最终会看到如图1-4所示的包或者项目资源管理器。这时项目应能成功编译并且不包含红色错误标记。

图1-4 完成导入的Eclipse Project Explorer

使用了Querydsl(详见第5章)的项目可能会引发红色的错误标记。原因是m2eclipse插件需要知道:在IDE构建的生命周期中,哪个阶段执行Querydsl关联的Maven插件。可以从m2e-querydsl扩展更新站点来安装这个插件,也可以在项目主页上找最新的版本(https://github.com/ilx/m2e-querydsl),复制最新版本的链接,并将它添加到可用的更新站点的列表中,如图1-5所示。然后安装在更新网站上发布了的功能,重新启动Eclipse,并更新Maven项目配置(在项目中单击鼠标右键,从弹出的快捷菜单中选择Maven→Update Project),这样就能去除Eclipse中的错误标记,并且成功地完成项目的编译。

图1-5 增加m2e-querydsl更新网站

IntelliJ IDEA

IDEA可以直接打开Maven项目而不需要其他额外的设置。选择菜单中的Open Project选项之后会弹出对话框(如图1-6所示)。

图1-6 将Maven项目导入到IDEA(步骤1/2)

IDE会打开项目并获取所需的依赖。在下一个步骤(如图1-7所示),它会探测已使用的框架(如Spring框架、JPA、WebApp等);可以使用弹出窗口的配置链接或者在事件日志中配置这些框架。

图1-7 将Maven项目导入到IDEA(步骤2/2)

这样项目就可以使用了。此时可以看到“Project”视图和“Maven Project”视图,如图1-8所示。然后便可以像往常一样编译项目了。

图1-8 打开Spring Data Book项目的IDEA

接下来,必须加入Spring Data JPA模块的JPA支持以启用finder方法以及版本库的错误检查功能。只需要右键单击该模块并选择“Add Framework Support”项,在弹出的对话框中勾选JavaEE持久化的支持并且选择Hibernate提供的持久化支持,如图1-9所示。接着它会生成一个持久化单元配置src/main/java/resources/META-INF/persistence.xml文件。

图1-9 在Spring Data JPA模块启用JPA支持


长期以来,实现应用程序的数据访问层一直是件繁琐的工作,因为我们经常需要编写大量的样板式代码,而且贫血(anemic)的领域类并没有按照真正面向对象或领域驱动方式来进行设计。因此Spring Data Repository抽象的目标就是大幅简化各种持久化存储持久层的实现。我们将会使用Spring Data JPA模块作为例子来讨论Repository抽象的基本理念。对于其他类型的存储,可以参考对应的例子。

我们选取领域模型中的Customer领域类,它会被持久化到任意的存储之中。这个类应该如示例2-1所示。

示例2-1 Customer领域类

传统的实现数据访问层的方式至少需要实现一个存储类(repository class),这个类会包含基本的CRUD(Create、Read、Update与Delete)方法以及通过限制条件来访问实体子集的查询方法。Spring Data Repository的方式能够避免大多数的代码,只需为这个实体存储声明简单的接口定义即可,如示例2-2所示。

示例2-2 CustomerRepository接口定义

正如你所见,我们扩展了Spring Data的Repository接口,它是通用的标识接口。它的主要职责是让Spring Data的基础设施识别出所有用户定义的Spring Data Repository。除此之外,它还会捕获托管的领域类以及实体的ID类型,稍后这些功能会提供很大的便利性。为了能够自动发现所声明的接口,可以使用存储特定的XML命名空间中的<repositories />元素(如示例2-3所示),或是在使用JavaConfig时借助相关的@Enable...Repositories注解(如示例2-4所示)。在示例中会使用JPA。我们只需将XML元素的base-package属性配置为我们的根包(root package),Spring Data会扫描它来查找Repository接口。如果没有给出更进一步的配置,那么它只会简单地检查包中带有注解的类。

示例2-3 使用XML激活Spring Data Repository

示例2-4 使用Java Config激活Spring Data Repository

XML和JavaConfig配置都需要添加存储专用的Bean声明来进行完善,如JPA的EntityManagerFactory以及DataSource等。对于其他形式的存储,我们只需使用对应的命名空间元素或注解即可。例如,示例2-5所示的配置片段,将会找到Spring Data Repository并创建Spring Bean,这些Bean实际上是由一组实现了所发现接口的代理所组成的。因此,现在可以继续编写客户端,通过Spring的自动装配就能访问这个Bean了。

CustomerRepository接口建立之后,我们就可以继续深入学习并添加一些易于声明的查询方法。常见的需求是通过电子邮件地址来获取Customer。为了做到这一点,我们添加合适的查询方法,如示例2-6所示。

示例2-5 客户端使用Spring Data Repository

示例2-6 声明查询方法

命名空间元素将会在容器启动的时候扫描到这个接口并触发Spring Data的基础设施为其创建Spring Bean。基础设施会探查接口中声明的方法并确定方法调用时要执行的查询。如果只是这样简单地定义方法的话,那么Spring Data将会根据其名字衍生出一个查询。在定义查询方面还有其他的途径可选,可以阅读2.2小节“定义查询方法”来了解更多信息。

在示例2-6中,由于我们遵循了领域对象属性的命名约定,因而查询可以衍生得到。查询方法名中的EmailAddress部分其实就对应了Customer类的emailAddress属性,因此,在使用JPA模块时,Spring Data会自动为声明的方法衍生出select C from Customer c where c.emailAddress = ?1。它还会检查方法声明中属性引用的合法性,如果发现任何错误则会在容器启动时,出现启动失败。现在,客户端可以很容易地执行这个方法,给定的方法参数会绑定到根据方法名衍生出来的查询之中并且执行该查询,如示例2-7所示。

示例2-7 执行查询方法

刚才看到的接口只声明了一个简单的查询方法。声明的方法会被基础设施探测到并进行解析,最终衍生出与存储相关的查询。但是,随着查询变得更加复杂,方法名会变得很冗长,显得很笨拙。对于更复杂的查询,依靠方法解析器所支持的关键字就不够了。因此,每种存储模块都提供了@Query注解,如示例2-8所示,它会接受存储相关的查询语言所支持的查询字符串,从而允许查询执行时进一步地定制化。

示例2-8 使用@Query注解手动定义查询

在这里,我们使用JPA作为例子并手动定义了一个查询,当然这个查询原本也是可以通过衍生得到的。

查询甚至可以外部化配置到属性文件中(它位于MATA-INF目录下的$store-named- queries.properties文件中),在这里$store是用于替换jpa、mongo以及neo4j等的占位符。key值必须要遵循$domainType.$methodName这样的约定。因此,为了将我们已有的方法替换成外部配置的命名查询,key将会是Customer.findByEmailAddress。如果是使用已命名查询的话,那就不需要使用@Query注解了。

如示例2-9所示,查询衍生机制内置于Spring Data Repository的基础设施之中,对基于Repository的实体来构建限制性的查询很有用处。我们会从方法中截取findBy、readBy以及getBy前缀并解析剩余的部分。一个基础的用法是,基于实体的属性来定义条件并使用And和Or将它们连接起来。

示例2-9 由方法名衍生查询

解析的实际结果依赖于我们所使用的数据存储。这里也有一些需要注意的通用事项。表达式通常会是属性的遍历以及操作符,它们可以连接起来。如示例2-9所示的那样,可以通过And以及Or来连接属性表达式。除此之外,对于属性表达式来说,还可以支持各种操作符,如Between、LessThan、GreaterThan以及Like。因为不同的数据存储之间所支持的操作符有所区别,所以要看查阅每种存储对应的章节。

属性表达式

属性表达式可以直接引用所管理实体的属性(如示例2-9中所示)。在查询创建的时候,我们已经确保所解析的属性就是领域类的属性。但是,依然可以遍历嵌套的属性来定义限制条件。在前面我们可以看到,Customer的Address中具有ZipCode属性。在这种情况下,如下这种方法名的查询将会创建x.address.zipCode这样的属性遍历。

这个方案的算法首先会将整体(AddressZipCode)作为一个属性进行解析并检查领域类中是否具有该名称的属性(第一个字母小写)。如果它存在的话,就会使用该属性。如果不存在,它会从右边开始将源信息按照“驼峰”命名的规则将其拆分为头部和尾部,然后尝试查找对应的属性(如AddressZip和Code)。如果按照这个头部信息找到了属性,那么我们将会使用尾部的信息继续往下构建树形的信息。因为示例中,第一次的分割并不匹配,我们将分割点继续左移(从“AddressZip、Code”移到“Address、ZipCode”)。

尽管这在大多数的场景下都是可行的,但是在一定情况下算法可能会选择错误的属性。假设Customer同时还有一个addressZip属性。那么我们的算法将会在第一次分割的时候就完成了匹配,这实际上选择了错误的属性,并且会导致最终的失败(因为addressZip类型可能并没有code属性)。为了解决这种模棱两可的问题,可以在方法名中使用下划线(_)来手动定义遍历点。所以,我们的方法名最终看起来是这样的:

如果查询所返回的结果数量增长很明显,那么分块访问数据就很有意义了。为了做到这一点,Spring Data提供了可与Repository一起使用的分页API。要读取哪一块数据的定义隐藏在Pageable接口及其实现PageRequest之中。得到的分页数据存放在Page中,它不仅包含了数据本身,还包含了元信息,这些信息包括它是不是第一页或最后一页以及一共有多少页等。为了计算这个元数据,除了初始的查询外,我们需要触发第二次查询。

借助于Repository,我们要使用分页功能时只需添加一个Pageable方法参数即可。不像其他的参数那样,这个参数是不与查询绑定的,用来限制返回的结果集。一种可选的方案就是返回Page类型,它会对结果集进行限制,但是需要另外一次查询来获取元信息(如可用元素的总数)。另一种可选的方案是使用List,它会避免额外的查询,但是不会提供元数据。如果不需要分页功能,只是想要排序,那么可以给方法签名上添加Sort参数,如示例2-10所示。

示例2-10 使用Pageable和Sort的查询方法

第一个方法允许传递Pageable实例到查询方法中,从而为静态定义的查询动态地增加分页功能。排序的功能可以通过Sort参数显式地传递给方法,也可以内嵌到PageRequest值对象中,如示例2-11所示。

示例2-11 使用Pageable和Sort

到目前为止,我们看到了带有查询方法的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

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

示例2-13 CrudRepository

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

示例2-14 PagingAndSortingRepository

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

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

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

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

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

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

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

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

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

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

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

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

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

 

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

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

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

现在,我们已经将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的注解属性中(查看各种存储相关的章节来了解更多)进行个性化设置。参考文档(https://bit.ly/VzYToo)中也包含了一些关于如何将自定义的行为应用于多个Repositor的学习材料。

在3.0版本中,Spring工具套件(Spring Tool Suite,STS)提供了与Spring Data Repository抽象进行集成的功能。STS为Spring Data所提供的核心支持是查找方法的查询衍生机制。它所能做到的第一件事就是在IDE中校验衍生查询方法的正确性,这样,不需要启动ApplicationContext就能立刻探测出方法名中引入的拼写错误。


STS是一个特殊的Eclipse发布版本,它内置了一些插件从而尽可能地便于进行Spring应用的构建。这个工具可以在项目的站点上(http://www. springsource.org/sts)下载或者使用一般的Eclipse发布版本并通过STS更新站点进行更新(基于Eclipse 3.8(http://dist.springsource.org/release/TOOLS/update/e3.8)或Eclipse 4.2(http://dist.springsource.org/release/TOOLS/update/e4.2))。

如图2-1所示,IDE检测到Descrption是非法的,因为Product类中并没有这样的属性。为了发现这些拼写错误,它会分析Product领域类(这些事情在启动Spring Data Repository时也会做)来获取属性并将方法名解析为属性的遍历树。为了尽早避免这种类型的拼写错误,STS的Spring Data辅助功能为属性名、条件关键字(criteria keyword)以及像And和Or这样的连接符提供了代码补全功能,如图2-2所示。

图2-1 Spring Data STS对衍生查询方法名进行校验

图2-2 对衍生查询方法的属性代码补全提示

Order类中有一些你可能想要引用的属性。假设我们要遍历billingAddress属性,Cmd+Space(或者在Windows中使用Ctrl+Space组合键)将会触发嵌套属性的遍历,这样将会提示出嵌套的属性并根据此时所遍历的属性类型提示所匹配的关键字(如图2-3所示)。因此,String类型的属性将会多一个Like的提示。

图2-3 嵌套属性和关键字提示

为了提供一些锦上添花的特性,Spring Data STS会将Repository作为IDE导航中的一等公民,使其带有众所周知的Spring Bean标识。除此之外,导航中的Spring元素(Spring Elements)节点将会包含一个专有的Spring Data Repositories节点,用来放置应用程序中所配置的所有Repository,如图2-4所示。

图2-4 在STS中,具备Spring Data支持的Eclipse项目资源管理器

可以看到,你能够快速找到Repository接口并跟踪它实际上来源于哪一个配置元素。

最后,启用JPA支持后,IDEA提供了Repository查找方法的补全功能,这种补全涵盖了衍生的属性名以及可用的关键字,如图2-5所示。

图2-5 在IDEA编辑器中,查询方法的补全功能


相关图书

深入浅出Spring Boot 3.x
深入浅出Spring Boot 3.x
云原生Spring实战Spring Boot与?Kubernetes实践
云原生Spring实战Spring Boot与?Kubernetes实践
Spring实战(第6版)
Spring实战(第6版)
Java研发自测入门与进阶
Java研发自测入门与进阶
Spring核心技术和案例实战
Spring核心技术和案例实战
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)

相关文章

相关课程