Spring Data Neo4j 存储库的可用扩展
Spring Data Neo4j 提供了一些可以添加到存储库中的扩展或“mixins”。什么是混合?根据维基百科,mixins是一种语言概念,允许程序员注入一些代码 进入一个类。Mixin 编程是一种软件开发风格,其中在类中创建功能单元 然后与其他班级混在一起。
Java 在语言层面上不支持这个概念,但我们确实通过几个接口和一个运行时来模拟它 这为添加了适当的实现和拦截器。
默认添加的 mixin 分别是 和 。这些接口是
在示例查询中进行了详细解释。QueryByExampleExecutor
ReactiveQueryByExampleExecutor
提供的其他混合物包括:
-
QuerydslPredicateExecutor
-
CypherdslConditionExecutor
-
CypherdslStatementExecutor
-
ReactiveQuerydslPredicateExecutor
-
ReactiveCypherdslConditionExecutor
-
ReactiveCypherdslStatementExecutor
向生成的查询添加动态条件
和 提供相同的概念:SDN 生成查询,你
提供将要添加的“谓词”(查询 DSL)或“条件”(Cypher DSL)。我们推荐 Cypher DSL,因为这是
SDN 本机使用的内容。您甚至可能要考虑使用生成
一个静态的元模型。QuerydslPredicateExecutor
CypherdslConditionExecutor
这是如何工作的?如上所述声明存储库,并添加以下接口之一:
interface QueryDSLPersonRepository extends
Neo4jRepository<Person, Long>, (1)
QuerydslPredicateExecutor<Person> { (2)
}
1 | 标准存储库声明 |
2 | 查询 DSL mixin |
或
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 条件执行器显示了示例用法:
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 | 创建条件。匿名参数用于名字,命名参数用于
姓氏。这就是在这些片段中定义参数的方式,也是与 Query-DSL 相比的优点之一
mixin不能这样做。
文字可以用 表示。or Cypher.literalOf |
4 | 从其中一个属性中定义一个SortItem |
查询-DSL 混合的代码看起来非常相似。查询-DSL 混合的原因可能是对 API 的熟悉程度和 它也适用于其他商店。反对它的原因是您需要在类路径上添加一个额外的库, 它缺少对遍历关系的支持,以及上述事实,即它不支持其 谓词(从技术上讲确实如此,但没有 API 方法可以将它们实际传递给正在执行的查询)。
对实体和投影使用(动态)Cypher-DSL 语句
添加相应的 mixin 与使用条件执行器没有什么不同:
interface PersonRepository extends
Neo4jRepository<Person, Long>,
CypherdslStatementExecutor<Person> {
}
扩展 .ReactiveCypherdslStatementExecutor
ReactiveNeo4jRepository
带有多个重载 和 .他们都采用 Cypher-DSL
语句分别将其定义为第一个参数,如果是投影方法,则为类型。CypherdslStatementExecutor
findOne
findAll
如果查询需要参数,则必须通过 Cypher-DSL 本身定义这些参数,并由其填充,如以下列表所示:
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 | 或者投影。 |
这些方法的工作原理类似。
命令式 Cypher-DSL 语句执行器还提供返回分页结果的重载。findAll
1 | 标准存储库声明 |
2 | 查询 DSL mixin |
1 | 标准存储库声明 |
2 | Cypher DSL 混合 |
1 | 定义一个命名对象,以查询的根为目标Node |
2 | 从中派生一些属性 |
3 | 创建条件。匿名参数用于名字,命名参数用于
姓氏。这就是在这些片段中定义参数的方式,也是与 Query-DSL 相比的优点之一
mixin不能这样做。
文字可以用 表示。or Cypher.literalOf |
4 | 从其中一个属性中定义一个SortItem |
1 | 动态查询是在帮助程序方法中以类型安全的方式生成的 |
2 | 我们已经在这里看到了这一点,我们还定义了一些保存模型的变量 |
3 | 我们定义一个匿名参数,由传递给方法的实际值 的 填充name |
4 | 从帮助程序方法返回的语句用于查找实体 |
5 | 或者投影。 |