JPA 实体的 UUID 主键:在多个实例上使用唯一值的安全方法

Saf*_*ari 12 java hibernate jpa spring-boot

我正在使用 SpringBoot、JPA 和 Hibernate。

我有个疑问。

对于我的实体,我需要有一个 UUID 作为主键(并且我想以“清除模式”(字符串)而不是二进制保存此 id)

我正在使用这段代码:

@Id
@Column(name = "id")
@Type(type = "uuid-char")
private UUID uuid = UUID.randomUUID();
Run Code Online (Sandbox Code Playgroud)

我的疑问是:这种方法安全吗?我可以确定 id 始终是唯一的吗?

据我了解,使用此代码,将在代码端生成 UUID,因此,如果我的服务有多个实例,并且所有实例都使用相同的数据库服务,会发生什么情况?

是否有可能更多实例会生成相同的 UUID?

Bas*_*que 10

UUID uuid = UUID.randomUUID()

我的疑问是:这种方法安全吗?我可以确定 id 始终是唯一的吗?

是的,非常安全。

UUID版本 4具有 122 位随机生成的数据。这是一个很大的数字范围。假设您的 UUID 是使用加密强度强的随机数生成器生成的,那么您对使用随机生成的 UUID 没有任何实际顾虑。

有关详细信息,请参阅维基百科上的碰撞部分。

如果你想担心,那就把你的担心转移到更有可能发生的事情。我最关心的是:宇宙射线 翻转EEC 内存中的位。(参见Linus Torvalds关于这个问题的有效咆哮。)

就我个人而言,我认为诸如版本 1 之类的时空点版本更不用担心碰撞。但其他人对此存在争议。无论哪种方式,版本 1 或版本 4,我都会睡得很好。

尽管如上所述,您仍然应该确保编写的代码在面对冲突时具有鲁棒性。不是因为随机生成的重复项造成的冲突,而是因为人为可能性造成的冲突,例如代码中将记录重复发布到数据库的错误,或者 DBA 错误地加载备份数据两次,等等。


Mar*_*nik 7

我不是休眠专家,但是,如果你这样做,一般来说,应该没问题,这意味着碰撞的可能性很低,但是“如果”发生碰撞怎么办?换句话说,你不能 100% 确定你“保证避免碰撞”。如果您的系统可以处理冲突(例如,重新创建 UUID,假设性能损失可以忽略不计,因为这种情况在极少数情况下会发生),那么当然没有问题。

\n

现在真正的问题是这里是否还可以做其他事情?\n嗯,Hibernate 能够UUID以一种也使用机器的 IP 作为生成参数的方式生成:

\n
@Entity\npublic class SampleEntity {\n \n    @Id\n    @GeneratedValue(generator = "UUID")\n    @GenericGenerator(\n        name = "UUID",\n        strategy = "org.hibernate.id.UUIDGenerator",\n        parameters = {\n            @Parameter(\n                name = "uuid_gen_strategy_class",\n                value = "org.hibernate.id.uuid.CustomVersionOneStrategy"\n            )\n        }\n    )\n    @Column(name = "id", updatable = false, nullable = false)\n    private UUID id;\n     \n    \xe2\x80\xa6\n}\n
Run Code Online (Sandbox Code Playgroud)\n

欲了解更多信息,请阅读此处,例如

\n

当然,最好的方法是让 DB 来处理 ID 生成。您尚未指定使用哪个数据库。例如,Postgresql 允许在扩展的帮助下生成 UUID 键:

\n

例如,请阅读此处。

\n

一般来说,使用 UUID 并不总是一个好主意 - 在日常生活中很难处理它们,而且一般来说,如果表中有很多行,它们会带来很大的开销。因此,您可能会考虑对主键使用自动增量序列或其他东西 - DB 将能够做到这一点,而您无需费心。

\n