|
该版本仍在开发中,尚未被视为稳定。对于最新稳定版本,请使用Spring Data Neo4j 8.0.0! |
唯一ID的处理与配置
使用内部的Neo4j id
给你的域类赋予唯一标识符最简单的方法是组合以下方式:@Id和@GeneratedValue在 的类型域上字符串或长(最好是对象,而不是标量长,字面意思零是判断实例是否全新的最佳指标):
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private Long id;
private String name;
public MovieEntity(String name) {
this.name = name;
}
}
你不需要为场地提供二传手,SDN会用反射来分配场地,但如果有二传手,也要用。 如果你想创建一个带有内部生成id的不可变实体,你必须提供一个凋零。
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private final Long id; (1)
private String name;
public MovieEntity(String name) { (2)
this(null, name);
}
private MovieEntity(Long id, String name) { (3)
this.id = id;
this.name = name;
}
public MovieEntity withId(Long id) { (4)
if (this.id.equals(id)) {
return this;
} else {
return new MovieEntity(id, this.title);
}
}
}
| 1 | 表示生成值的不可变最终id字段 |
| 2 | 公共构造器,应用于应用程序和 Spring Data |
| 3 | 内部使用的构建器 |
| 4 | 这就是所谓的枯萎身份证-属性。
它创建一个新实体并相应设置字段,而不修改原实体,从而使其不可变。 |
你要么提供ID属性的设定器,要么像wither这样的东西,如果你想要的话
-
优点:很明显,id 属性是代理业务密钥,使用它无需额外努力或配置。
-
缺点:它与 Neo4js 内部数据库 ID 绑定,而该 ID 仅在数据库生命周期内对我们的应用实体独有。
-
缺点:创建一个不可篡改的实体需要更多努力
使用外部提供的代理密钥
这@GeneratedValue注释可以取一个实现的类org.springframework.data.neo4j.core.schema.IdGenerator作为参数。
SDN提供内部生成器(默认值)和UUIDStringGenerator直接开箱。
后者为每个实体生成新的UUID,并返回为java.lang.字符串.
使用该应用实体的应用实体会是这样的:
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue(UUIDStringGenerator.class)
private String id;
private String name;
}
我们必须讨论两个关于优点和缺点的两个问题。 任务本身和UUID策略。 通用唯一标识符旨在实现实际目的的唯一。 引用维基百科的话: “因此,任何人都可以创建UUID,并用它来识别某个标识符,几乎可以确定该标识符不会重复已经被创建或将被创建以识别其他事物的标识符。”我们的策略采用Java内部UUID机制,采用密码学上强的伪随机数生成器。 大多数情况下这应该没问题,但情况可能因人而异。
剩下的任务本身是:
-
优势:应用程序完全控制,可以生成一个恰到好处于应用目的的唯一密钥。 生成的价值会是稳定的,之后也不需要更改。
-
缺点:生成的策略被应用于应用端。 在那个时代,大多数应用都会在多个实例中部署,以便更好地扩展。 如果你的策略容易产生重复,插入会失败,因为主键的唯一性属性会被破坏。 因此,虽然在这种情况下你不必考虑独特的业务密钥,但你必须更多地考虑生成什么。
你有多种选择来推出自己的ID生成器。 一个是实现生成器的POJO:
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.data.neo4j.core.schema.IdGenerator;
import org.springframework.util.StringUtils;
public class TestSequenceGenerator implements IdGenerator<String> {
private final AtomicInteger sequence = new AtomicInteger(0);
@Override
public String generateId(String primaryLabel, Object entity) {
return StringUtils.uncapitalize(primaryLabel) +
"-" + sequence.incrementAndGet();
}
}
另一种选择是提供额外的春豆,比如这样:
@Component
class MyIdGenerator implements IdGenerator<String> {
private final Neo4jClient neo4jClient;
public MyIdGenerator(Neo4jClient neo4jClient) {
this.neo4jClient = neo4jClient;
}
@Override
public String generateId(String primaryLabel, Object entity) {
return neo4jClient.query("YOUR CYPHER QUERY FOR THE NEXT ID") (1)
.fetchAs(String.class).one().get();
}
}
| 1 | 使用你所需的查询或逻辑。 |
上面的生成器可以配置为豆子参考,如下:
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue(generatorRef = "myIdGenerator")
private String id;
private String name;
}
使用商业密钥
我们在完整示例中使用了商业密钥电影实体和PersonEntity.
该人的名字是在施工时分配的,既是你的应用程序,也是通过Spring Data加载时。
这只有在你找到稳定、唯一的业务密钥时才可能,但它们能很好地生成不可变域对象。
-
优点:使用商业密钥或自然密钥作为主密钥是自然的。 所涉及的实体被明确识别,在进一步建模你的领域时,大多数时候感觉恰到好处。
-
缺点:一旦你发现你找到的密钥不像想象中稳定,商业密钥作为主键就很难更新。 事实往往是可以改变的,即使承诺了相反的承诺。 除此之外,找到真正独特的标识符很难。
请记住,在Spring Data Neo4j处理业务密钥之前,域名实体上始终设置了业务密钥。
这意味着它无法确定该实体是否全新(它总是假设该实体是新的),
除非还有一个@Version田提供。