|
该版本仍在开发中,尚未被视为稳定。对于最新稳定版本,请使用Spring Data Neo4j 8.0.0! |
Spring Data Neo4j Extensions
Spring Data Neo4j 仓库的可用扩展
Spring Data Neo4j 提供了几个扩展或“混合”功能,可以添加到仓库中。什么是混合?根据维基百科,混合词是一种允许程序员注入代码的语言概念 进入一个班级。混合编程是一种软件开发风格,在类中创建功能单元 然后又和其他课程混在一起。
Java 在语言层面不支持这个概念,但我们通过几个接口和运行时来模拟它 这为游戏添加了合适的实现和拦截者。
默认添加的混频有QueryByExampleExecutor和ReactiveQueryByExampleExecutor分别。这些接口是
详见《示例查询》。
还提供以下其他混音:
-
QuerydslPredicateExecutor -
CypherdslConditionExecutor -
CypherdslStatementExecutor -
ReactiveQuerydslPredicateExecutor -
ReactiveCypherdslConditionExecutor -
ReactiveCypherdslStatementExecutor
为生成的查询添加动态条件
两者QuerydslPredicateExecutor和CypherdslConditionExecutor提供同样的概念:SDN生成查询,你
提供将被添加的“谓词”(Query DSL)或“条件”(Cypher DSL)。我们推荐Cypher DSL,因为这是
SDN原生使用的是什么。你甚至可以考虑使用生成
为你准备一个静态元模型。
这是怎么运作的?请如上所述声明您的仓库,并添加以下接口之一:
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 混音 |
示例用法是密码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 | 定义一个命名节点对象,针对查询的根节点 |
| 2 | 从中推导一些性质 |
| 3 | 创建一个或条件。第一个名称使用匿名参数,命名参数为
姓氏。这就是你如何定义这些片段中的参数,也是相较于 Query-DSL 的一个优势
Mixin不能做到这一点。
文字可以表示为Cypher.字面的. |
| 4 | 定义一个排序项来自其中一个性质 |
Query-DSL 混音的代码看起来很相似。Query-DSL 混合的原因可能是对 API 的熟悉度和 它也适用于其他商店。反对的理由是你需要在类路径上额外添加一个库, 它缺少对跨越关系的支持,以及前面提到的它不支持参数的事实 谓词(技术上是有的,但没有API方法能将其传递给正在执行的查询)。
使用(动态)密码DSL语句处理实体和投影
添加相应的混合因子与使用条件执行子无异:
interface PersonRepository extends
Neo4jRepository<Person, Long>,
CypherdslStatementExecutor<Person> {
}
请使用ReactiveCypherdslStatementExecutor当扩展ReactiveNeo4j仓库.
这CypherdslStatementExecutor带有多个过载findOne和findAll(查找所有.它们都用Cypher-DSL
分别是对其作为第一个参数的持续定义,对于投影方法,则是一个类型。
如果查询需要参数,必须通过密码DSL本身定义参数,并由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 | 我们定义一个匿名参数,由实际值填充名称,该数据传递给了 |
| 4 | 辅助方法返回的语句用于寻找实体 |
| 5 | 或者说是投射。 |
这findAll(查找所有方法类似。
命令式密码DSL语句执行器也提供过载返回分页结果。