该版本仍在开发中,尚未被视为稳定。对于最新稳定版本,请使用Spring Data Neo4j 8.0.0spring-doc.cadn.net.cn

Spring Data Neo4j 预测

如上所述,投影有两种类型:接口投影和基于DTO的投影。 在 Spring Data Neo4j 中,这两种类型的投影都直接影响哪些属性和关系被转移 通过电报。 因此,如果你处理的是包含的节点和实体,这两种方法都能减轻数据库负担 有很多属性,可能并非所有应用场景都需要。spring-doc.cadn.net.cn

无论是基于接口还是基于DTO的投影,Spring Data Neo4j都会使用仓库的域类型来构建 查询。所有可能改变查询的属性注释都会被考虑。 域类型是通过仓库声明定义的类型 (给定一个interface TestRepository 扩展了 CrudRepository<TestEntity, Long>域名类型为测试实体).spring-doc.cadn.net.cn

基于接口的投影始终是底层域类型的动态代理。访问器的名称定义 在这样的接口上(如getName)必须解析为性质(此处:名称)存在于投影实体上的元素。 这些属性是否在域类型上有访问者并不重要,只要它们能通过以下方式访问即可 这是Spring Data的通用基础设施。后者已经被确保了,因为域类型不会是 中持久实体 第一位。spring-doc.cadn.net.cn

基于DTO的投影在与自定义查询结合时会更灵活一些。而标准查询则从 原始域类型,因此只能使用其中定义的属性和关系,自定义查询 可以添加额外的属性。spring-doc.cadn.net.cn

规则如下:首先,利用域类型的属性来填充DTO内容。如果DTO声明 通过访问器或字段获取额外属性——Spring Data Neo4j 会在结果记录中查找匹配的属性。 属性必须在名称上完全匹配,并且可以是简单类型(定义如下org.springframework.data.neo4j.core.convert.Neo4jSimpleTypes) 或已知的持续存在实体。这些合集是支持的,但地图不支持。spring-doc.cadn.net.cn

Spring Data Neo4j 中还内置了一个额外机制,允许在实体定义层面定义加载和持久边界。 更多内容请参见“总计边界”部分。spring-doc.cadn.net.cn

多层次投影

Spring Data Neo4j 还支持多层次投影。spring-doc.cadn.net.cn

多层投影示例
interface ProjectionWithNestedProjection {

    String getName();

    List<Subprojection1> getLevel1();

    interface Subprojection1 {
        String getName();
        List<Subprojection2> getLevel2();
    }

    interface Subprojection2 {
        String getName();
    }
}

尽管可以建模循环投影或指向将形成循环的实体, 投影逻辑不会遵循这些循环,只会创建无循环的查询。spring-doc.cadn.net.cn

多层投影受限于它们应投影的实体。关系属性在这种情况下,属于实体类别,如果应用投影,就需要得到尊重。spring-doc.cadn.net.cn

投影的数据作

如果你已经将投影作为DTO获取,可以修改其值。 但如果你使用基于接口的投影,你不能仅仅更新界面。 一个典型的模式是在你的域实体类中提供一个方法,消耗接口并创建一个包含从接口复制的值的域实体。 这样,你可以更新实体,并像下一节描述的投影蓝图/遮罩一样再次持久化。spring-doc.cadn.net.cn

投影的持久性

类似于通过投影检索数据,它们也可以作为持久化的蓝图。 这Neo4j模板提供流畅的 API,将这些投影应用到保存作中。spring-doc.cadn.net.cn

你可以为某个域类保存投影spring-doc.cadn.net.cn

给定域类的保存投影
Projection projection = neo4jTemplate.save(DomainClass.class).one(projectionValue);

或者你可以保存一个域对象,但只尊重投影中定义的字段。spring-doc.cadn.net.cn

保存域对象并使用给定的投影蓝图
Projection projection = neo4jTemplate.saveAs(domainObject, Projection.class);

在这两种情况下,这些作也可用于基于集合的作,只有字段和关系预测中定义的字段和关系会被更新。spring-doc.cadn.net.cn

为了防止数据被删除(例如删除关系),你应该始终加载至少所有之后需要持久化的数据。

完整示例

给定以下实体、投影及相应的存储库:spring-doc.cadn.net.cn

一个简单的实体
@Node
class TestEntity {
    @Id @GeneratedValue private Long id;

    private String name;

    @Property("a_property") (1)
    private String aProperty;
}
1 该性质在图中有不同的名称
衍生实体,继承于测试实体
@Node
class ExtendedTestEntity extends TestEntity {

    private String otherAttribute;
}
界面投影测试实体
interface TestEntityInterfaceProjection {

    String getName();
}
DTO 投影测试实体,包括一个额外的属性
class TestEntityDTOProjection {

    private String name;

    private Long numberOfRelations; (1)

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Long getNumberOfRelations() {
        return numberOfRelations;
    }

    public void setNumberOfRelations(Long numberOfRelations) {
        this.numberOfRelations = numberOfRelations;
    }
}
1 该属性不存在于投影实体中

一个测试实体如下所示,且其行为将如同商品列表所述。spring-doc.cadn.net.cn

一个用于测试实体
interface TestRepository extends CrudRepository<TestEntity, Long> { (1)

    List<TestEntity> findAll(); (2)

    List<ExtendedTestEntity> findAllExtendedEntities(); (3)

    List<TestEntityInterfaceProjection> findAllInterfaceProjectionsBy(); (4)

    List<TestEntityDTOProjection> findAllDTOProjectionsBy(); (5)

    @Query("MATCH (t:TestEntity) - [r:RELATED_TO] -> () RETURN t, COUNT(r) AS numberOfRelations") (6)
    List<TestEntityDTOProjection> findAllDTOProjectionsWithCustomQuery();
}
1 仓库的域类型为测试实体
2 返回一个或多个的方法测试实体只返回实例,因为它与域类型相符
3 返回一个或多个扩展域类型的类实例的方法,只会返回扩展类的实例。该方法的域类型将是扩展类,且仍然满足仓库本身的域类型
4 该方法返回接口投影,因此方法的返回类型不同与仓库的域类型不同。接口只能访问域类型中定义的属性。后缀是让 SDN 不去寻找接口投影测试实体
5 该方法返回一个DTO投影。执行该方法会使SDN发出警告,正如DTO定义的关系数量作为附加属性,但该属性不包含在域类型的契约中。注释属性aProperty测试实体将正确翻译为a_property在查询中。如上所述,返回类型与仓库的域类型不同。后缀是让 SDN 不去寻找DTOProjections测试实体
6 该方法还返回一个DTO投影。但不会发出警告,因为查询包含投影中定义的附加属性的拟合值值
虽然上述列表中的仓库使用了具体的返回类型来定义投影,另一种变体是动态投影的使用,如Spring Data Neo4j 与其他 Spring Data 项目共享的文档部分。动态投影可以应用于封闭和开放接口投影,以及基于类的 DTO 投影:

动态投影的关键是将期望的投影类型指定为查询方法的最后一个参数在这样的仓库中:
<T> Collection<T> findByName(字符串名,类<T>类型). 这是一个声明可以添加到测试仓库在上述,允许通过同一方法检索不同的投影,但不包含以重复可能的@Query对多种方法的注释。

总边界

通过引入多重投影来反映多层关系可能会很繁琐。为了在实体层面简化这一点,可以添加一个额外的参数总边界并提供1.n类。在这种情况下,参数化实体只会报告其@Idfield back 和 SDN 无法跟踪其关系,也无法获取其他属性。spring-doc.cadn.net.cn

仍然可以使用基于接口的投影来描述这些实体。这些投影可以更广泛,比如声明的聚合边界,比如包含属性或关系。spring-doc.cadn.net.cn