此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Data Neo4j 7.5.2spring-doc.cadn.net.cn

Spring Data Neo4j 扩展

Spring Data Neo4j 存储库的可用扩展

Spring Data Neo4j 提供了几个可以添加到存储库中的扩展或“混合”。什么是混合?根据维基百科,mixin 是一种语言概念,允许程序员注入一些代码 进入一个类。Mixin 编程是一种软件开发风格,其中功能单元在类中创建 然后与其他班级混在一起。spring-doc.cadn.net.cn

Java 在语言层面不支持这个概念,但我们确实通过几个接口和运行时来模拟它 这为添加了适当的实现和拦截器。spring-doc.cadn.net.cn

默认添加的 mixin 是QueryByExampleExecutorReactiveQueryByExampleExecutor分别。这些接口是 在示例查询中进行了详细说明。spring-doc.cadn.net.cn

提供的其他混合包括:spring-doc.cadn.net.cn

向生成的查询添加动态条件

两个QuerydslPredicateExecutorCypherdslConditionExecutor提供相同的概念:SDN 生成查询,您 提供将添加的“谓词”(查询 DSL)或“条件”(Cypher DSL)。我们推荐 Cypher DSL,因为它是 SDN 本机使用的内容。您甚至可能需要考虑使用生成 一个适合您的静态元模型。spring-doc.cadn.net.cn

这是如何工作的?如上所述声明您的存储库,并添加以下接口之一spring-doc.cadn.net.cn

interface QueryDSLPersonRepository extends
        Neo4jRepository<Person, Long>, (1)
        QuerydslPredicateExecutor<Person> { (2)
}
1 标准存储库声明
2 查询 DSL 混合
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.support.CypherdslConditionExecutor;

    interface PersonRepository extends
            Neo4jRepository<Person, Long>, (1)
            CypherdslConditionExecutor<Person> { (2)
    }
1 标准存储库声明
2 Cypher DSL 混合

Cypher DSL 条件执行器显示了示例用法:spring-doc.cadn.net.cn

Node person = Cypher.node("Person").named("person"); (1)
Property firstName = person.property("firstName"); (2)
Property lastName = person.property("lastName");

assertThat(
        repository.findAll(
                firstName.eq(Cypher.anonParameter("Helge"))
                        .or(lastName.eq(Cypher.parameter("someName", "B."))), (3)
                lastName.descending() (4)
        ))
        .extracting(Person::getFirstName)
        .containsExactly("Helge", "Bela");
1 定义一个命名的Node对象,以查询的根为目标
2 从中派生一些属性
3 创建一个or条件。匿名参数用于名字,命名参数用于 姓氏。这是您在这些片段中定义参数的方式,也是相对于 Query-DSL 的优势之一 mixin 不能做到这一点。 文字可以用Cypher.literalOf.
4 定义一个SortItem从其中一个属性

Query-DSL mixin 的代码看起来非常相似。Query-DSL mixin 的原因可能是熟悉 API 和 它也适用于其他商店。反对它的原因是你需要在类路径上有一个额外的库, 它缺少对遍历关系的支持,并且上述事实是它不支持其 谓词(从技术上讲确实如此,但没有 API 方法将它们实际传递给正在执行的查询)。spring-doc.cadn.net.cn

对实体和投影使用(动态)Cypher-DSL 语句

添加相应的 mixin 与使用条件 excecutor 没有什么不同:spring-doc.cadn.net.cn

interface PersonRepository extends
        Neo4jRepository<Person, Long>,
        CypherdslStatementExecutor<Person> {
}

请使用ReactiveCypherdslStatementExecutor当扩展ReactiveNeo4jRepository.spring-doc.cadn.net.cn

CypherdslStatementExecutor带有几个重载findOnefindAll.他们都使用 Cypher-DSL 语句分别是作为第一个参数的持续定义,如果是投影方法,则是一个类型。spring-doc.cadn.net.cn

如果查询需要参数,则必须通过 Cypher-DSL 本身定义它们并由它填充,如以下列表所示:spring-doc.cadn.net.cn

static Statement whoHasFirstNameWithAddress(String name) { (1)
    Node p = Cypher.node("Person").named("p"); (2)
    Node a = Cypher.anyNode("a");
    Relationship r = p.relationshipTo(a, "LIVES_AT");
    return Cypher.match(r)
            .where(p.property("firstName").isEqualTo(Cypher.anonParameter(name))) (3)
            .returning(
                    p.getRequiredSymbolicName(),
                    Cypher.collect(r),
                    Cypher.collect(a)
            )
            .build();
}

@Test
void fineOneShouldWork(@Autowired PersonRepository repository) {

    Optional<Person> result = repository.findOne(whoHasFirstNameWithAddress("Helge"));  (4)

    assertThat(result).hasValueSatisfying(namesOnly -> {
        assertThat(namesOnly.getFirstName()).isEqualTo("Helge");
        assertThat(namesOnly.getLastName()).isEqualTo("Schneider");
        assertThat(namesOnly.getAddress()).extracting(Person.Address::getCity)
                .isEqualTo("Mülheim an der Ruhr");
    });
}

@Test
void fineOneProjectedShouldWork(@Autowired PersonRepository repository) {

    Optional<NamesOnly> result = repository.findOne(
            whoHasFirstNameWithAddress("Helge"),
            NamesOnly.class  (5)
    );

    assertThat(result).hasValueSatisfying(namesOnly -> {
        assertThat(namesOnly.getFirstName()).isEqualTo("Helge");
        assertThat(namesOnly.getLastName()).isEqualTo("Schneider");
        assertThat(namesOnly.getFullName()).isEqualTo("Helge Schneider");
    });
}
1 动态查询是在帮助程序方法中以类型安全的方式构建的
2 我们已经在这里看到了这一点,我们还定义了一些保存模型的变量
3 我们定义了一个匿名参数,由name,该方法被传递给
4 从帮助程序方法返回的语句用于查找实体
5 或者投影。

findAll方法的工作原理类似。 命令式 Cypher-DSL 语句执行器还提供了返回分页结果的重载。spring-doc.cadn.net.cn