JPA 中的唯一 ID(多租户)
我目前正在开发一个使用 JPA(Hibernate)的多租户应用程序。对于某些表,我需要每个租户唯一的序列号。因此,我无法对这些字段使用 @GenerateValue
。我决定使用一个名为 Sequence 的额外实体,其中包含一个用 @Version
注释的 long
字段。当请求新的 id 时,我会执行以下操作:
Sequence seq = em.find(Sequence.class, pk, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
long nextId = seq.id;
只要我不运行该应用程序两次,此操作就有效。然后我得到以下异常:
线程“主”javax.persistence.OptimisticLockException 中出现异常: org.hibernate.StaleObjectStateException:行已更新或删除 另一笔交易(或未保存值映射不正确)
序列未“正确”锁定,并且在提交后立即出现异常。由于 JPA 不支持嵌套事务,我无法提前检测到它。我尝试了其他一些方法,但也都失败了。
那么,是否有任何其他(便携式)解决方案允许我在多租户上下文中生成唯一密钥?
I'm currently working on a multi tenant applcation which is using JPA (Hibernate). For some tables I need a sequential number thats unique for each tenant. Because of this I cannot use @GeneratedValue
for these fields. I decided to use an extra entity called Sequence with a long
field annotated with @Version
. When requesting a new id I do the following:
Sequence seq = em.find(Sequence.class, pk, LockModeType.PESSIMISTIC_FORCE_INCREMENT);
long nextId = seq.id;
This works as long as I don't run the application twice. Then I get the following exception:
Exception in thread "main" javax.persistence.OptimisticLockException:
org.hibernate.StaleObjectStateException: Row was updated or deleted by
another transaction (or unsaved-value mapping was incorrect)
Sequence doesn't get locked "properly" and I get an exception as soon as I commit. I can't detect it earlier since JPA doesn't support nested transactions. I tried a few other things but they failed, too.
So, are there any other (portable) solutions that allow me to generate an unique key in a multi tenant context?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您没有正确使用 @Version 注释。该注解设计了一个数字字段作为版本字段,供JPA内部在做事务锁时使用。您不应该真正编写甚至(某些情况除外)阅读它。您最初的想法是正确的:制作一个音序器,但您不需要为此使用 @Version 。只需有一个具有原子整数的类,每次需要新的唯一值时该整数都会递增,然后持久保存到表中的数据库中。
You're not using the @Version annottion properly. This annotation designs a numeric field as the version field and is used internally by JPA when doing transaction locks. You shouldn't really write or even (except some situations) read it. Your inital idea was right: make a sequencer, but you don't need to use @Version for that. Just have a class with an atomic integer that is incremented each time you need a new unique value, and then persisted to the db in a table.