返回介绍

12.2.4 创建自动化的 Neo4j Repository

发布于 2024-08-17 00:45:49 字数 6427 浏览 0 评论 0 收藏 0

大多数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>
findAllBySchemaPropertyValue(String,Object);

返回指定属性匹配给定值的所有实体

Iterable<T> findAllByTraversal(N,
TraversalDescription);

返回从某个节点开始,图遍历到达的节点

T findBySchemaPropertyValue (String,Object);

返回指定属性匹配给定值的一个实体

T findOne(Long);

根据ID,获得某一个实体

EndResult<T> query(String,
Map<String,Object>);

返回匹配给定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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文