- 作者简介
- 内容提要
- 关于本书
- 路线图
- 代码规范与下载
- 作者在线
- 封面插图简介
- 前言
- 译者序
- 致谢
- 第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.2.4 创建自动化的 Neo4j Repository
大多数Spring Data项目都具备的最棒的一项功能就是为Repository接口自动生成实现。我们已经在Spring Data JPA和Spring Data MongoDB中看到了这项功能。Spring Data Neo4j也不例外,它同样支持Repository自动化生成功能。
我们已经将@EnableNeo4jRepositories添加到了配置中,所以Spring Data Neo4j已经配置为支持自动化生成Repository的功能。我们所需要做的就是编写接口,如下的OrderRepository就是很好的起点:
与其他的Spring Data项目一样,Spring Data Neo4j会为扩展Repository接口的其他接口生成Repository方法实现。在本例中,OrderRepository扩展了GraphRepository,而后者又间接扩展了Repository接口。因此,Spring Data Neo4j将会在运行时创建OrderRepository的实现。
注意,GraphRepository使用Order进行了参数化,也就是这个Repository所要使用的实体类型。因为Neo4j要求图ID的类型为Long,因此在扩展GraphRepository的时候,没有必要再去指定ID类型。
现在,我们就能够使用很多通用的CRUD操作,这与JpaRepository和MongoRepository所提供的功能类似。表12.4描述了扩展GraphRepository所能够得到的方法。
表12.4 通过扩展GraphRepository,Repository接口能够继承多个CRUD操作,
它们会由Spring Data Neo4j自动实现
方 法 | 描 述 |
long count(); | 返回在数据库中,目标类型有多少实体 |
void delete(Iterable<?extendsT>); | 删除多个实体 |
void delete(Long id); | 根据ID,删除一个实体 |
void delete(T); | 删除一个实体 |
void deleteAll(); | 删除目标类型的所有实体 |
boolean exists(Long id); | 根据指定的ID,检查实体是否存在 |
EndResult<T> findAll(); | 获取目标类型的所有实体 |
Iterable<T> findAll(Iterable<Long>); | 根据给定的ID,获取目标类型的实体 |
Page<T> findAll(Pageable); | 返回目标类型分页和排序后的实体列表 |
EndResult<T> findAll(Sort); | 返回目标类型排序后的实体列表 |
EndResult<T> | 返回指定属性匹配给定值的所有实体 |
Iterable<T> findAllByTraversal(N, | 返回从某个节点开始,图遍历到达的节点 |
T findBySchemaPropertyValue (String,Object); | 返回指定属性匹配给定值的一个实体 |
T findOne(Long); | 根据ID,获得某一个实体 |
EndResult<T> query(String, | 返回匹配给定Cypher查询的所有实体 |
Iterable<T> save(Iterable<T>); | 保存多个实体 |
S save(S); | 保存一个实体 |
我们没有足够的篇幅介绍所有的方法,但是有些方法你可能会经常用到。例如,如下的代码能够保存一个Order实体:
当实体保存之后,save()方法将会返回被保存的实体,如果之前它使用@GraphId注解的属性值为null的话,此时这个属性将会填充上值。
我们还可以使用findOne()方法查询某一个实体。例如,下面的这行代码将会查询图ID为4的Order:
我们还可以查询所有的Order:
当然,你可能还希望删除某一个实体。这种情况下,可以使用delete()方法:
这将会从数据库中删除给定的Order节点。如果你只有图ID的话,那可以将其传递到delete()方法中,而不是再使用节点类型本身:
如果你希望进行自定义的查询,那么可以使用query()方法对数据库执行任意的Cypher查询。但是这与使用Neo4jTemplate的query()方法并没有太大的差别。其实,我们还可以为OrderRepository添加自定义的查询方法。
添加查询方法
我们已经看过如何按照命名约定使用Spring Data JPA和Spring Data MongoDB来添加自定义的查询方法。如果Spring Data Neo4j没有提供相同功能的话,那我们就该失望了。
如下面的程序清单所示,其实我们完全没有必要失望:
程序清单12.13 通过遵循命名约定来定义查询方法
这里,我们添加了两个方法。其中一个会查询customer属性等于给定String值的Order节点。另外一个方法与之类似,但是除了匹配customer属性以外,Order节点的type属性必须还要等于给定的类型值。
我们之前已经讨论过查询方法的命名约定,所以这里没有必要再进行深入地讨论。可以翻看之前学习Spring Data JPA的章节,重新温习如何编写这些方法。
指定自定义查询
当命名约定无法满足需求时,我们还可以为方法添加@Query注解,为其指定自定义的查询。我们之前已经见过@Query注解。在Spring Data JPA中,我们使用它来为Repository方法指定JPA查询。在Spring Data MongoDB中,我们使用它来指定匹配JSON的查询。但是,在使用Spring Data Neo4j的时候,我们必须指定Cypher查询:
在这里,findSiAOrders()方法上使用了@Query注解,并设置了一个Cypher查询,它会查找与Item关联并且product属性等于“Spring in Action”的所有Order节点。
混合自定义的Repository行为
当命名约定和@Query注解均无法满足满足需求的时候,我们还可以混合自定义的Repository逻辑。
例如,假设我们想自己编写findSiAOrders()方法的实现,而不是依赖于@Query注解。那么可以首先定义一个中间接口,该接口包含findSiAOrders()方法的定义:
然后,我们修改OrderRepository,让它扩展OrderOperations和GraphRepository:
最后,我们需要自己编写实现。与Spring Data JPA和Spring Data MongoDB类似,Spring Data Neo4j将会查找名字与Repository接口相同且添加“Impl”后缀的实现类。因此,我们需要创建OrderRepositoryImpl类。如下的程序清单展示了OrderRepositoryImpl类,它实现了findSiAOrders()方法。
程序清单12.14 将自定义功能混合到OrderRepository中
OrderRepositoryImpl中注入了一个Neo4jOperations(具体来讲,就是Neo4jTemplate的实例),它会用来查询数据库。因为query()方法返回的是Result<Map<String, Object>>,我们需要将其转换为List<Order>。第一步是调用Result的to()方法,产生一个EndResult<Order>。然后,使用Neo4j的IteratorUtil.asList()方法将EndResult<Order>转换为List<Order>,然后将其返回。
对于能够表达为节点和关联关系的数据,像Neo4j这样的图数据库是非常合适的。如果将我们生活的世界理解为各种互相关联的事物,那么图数据库能够适用于很大的范围。就我个人而言,我非常喜欢Neo4j。
但有些时候,我们需要的数据会更简单一些。有时,我们所需要的仅仅将某个value存储起来,稍后能够根据一个key将其提取出来。接下来,我们看一下Spring Data如何使用Redis key-value存储实现这种类型的数据持久化。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论