【问题标题】:Unique Id in JPA (multi tenant)JPA 中的唯一 ID(多租户)
【发布时间】:2011-09-20 23:05:52
【问题描述】:

我目前正在开发一个使用 JPA (Hibernate) 的多租户应用程序。对于某些表,我需要一个对每个租户都是唯一的序列号。因此,我不能将@GeneratedValue 用于这些字段。我决定使用一个名为 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 不支持嵌套事务,因此我无法更早地检测到它。我尝试了其他一些方法,但也失败了。

那么,是否有任何其他(便携式)解决方案可以让我在多租户上下文中生成唯一密钥?

【问题讨论】:

    标签: jpa multi-tenant


    【解决方案1】:

    您没有正确使用@Version 注释。这个注解设计了一个数字字段作为版本字段,在做事务锁时被 JPA 内部使用。你不应该真的写,甚至(除了某些情况)读它。您最初的想法是正确的:制作一个音序器,但您不需要为此使用@Version。只要有一个原子整数类,每次需要新的唯一值时都会递增,然后将其持久化到表中的数据库中。

    【讨论】:

    • 我已经尝试过你的建议。这个解决方案的问题是,在我提交整个事务之前我不会检测到事务重叠(这就是我所说的嵌套事务)。
    • 好吧,你不会喜欢我的建议,但如果你真的想要嵌套事务,你可能想放弃 Hibernate/JPA。您可以直接使用 JDBC,或使用 Spring SavePoints(带 JDBC)模拟嵌套事务:static.springsource.org/spring/docs/2.5.5/api/org/…
    猜你喜欢
    • 1970-01-01
    • 2012-03-31
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    相关资源
    最近更新 更多