休眠等于方法

Posted

技术标签:

【中文标题】休眠等于方法【英文标题】:Hibernate equals method 【发布时间】:2013-08-15 11:49:28 【问题描述】:

有很多问题与如何实现由 Hibernate 管理的实体的良好 equals 和 hashcode 函数有关。 但是,我没有为我的问题找到任何解决方案:

我有一个没有业务密钥的实体类。它具有生成的主键、一些不能用于标识的属性以及与其他实体类的多个关联。我总是尝试坚持 Hibernate 的建议(业务密钥的平等),所以我不想检查生成的 Id。 这导致检查 2 个唯一标识我的实体类的关联。 但这会导致这两个关联必须定义为 FetchType.EAGER。

对于我的 equals 函数,我可以考虑其他替代方法吗?

更新:

您如何看待 Hibernate 中“通用”equals 方法的以下解决方案?

public boolean equals(Object object) 
    if (this == object) return true;
    if (! (object instanceof AbstractEntity)) return false;

    AbstractEntity other = (AbstractEntity) object;

    if (getId() == null && other.getId() != null) return false;
    if (getId() != null && other.getId() == null) return false;
    if (getId() == null && other.getId() == null) return uuid == other.uuid;
    return getId().longValue() == other.getId().longValue();

这样,实体可以安全地在集合中使用。当实体被分离时,它通过 ID 进行比较。当实体是瞬态的时,它会通过生成的 UUID 进行比较。所以我看到的唯一缺点是瞬态实体是通过 UUID 而不是业务密钥进行比较的。

非常欢迎任何建议!

【问题讨论】:

为什么不能使用生成的主键? 实体为瞬态时,id仍为null。想象一下,实体被添加到 java.util.Set 并且会话将状态刷新到数据库。然后 id 将被分配一个值,这会导致哈希码发生变化。这违反了合同。 @user2054927:这实际上是一个好问题。除了根本不定义 equals 之外,我从来没有找到一个像样的方法。如果它不是不可变的,使用业务密钥也会破坏合同。如果你绝对需要 equals(),你可以使用 ID 来实现它,但如果 ID 尚未设置,则阻止任何添加到 Set。 【参考方案1】:

Liferay 执行类似于以下解决方案的操作。希望对你有帮助。

此解决方案需要在您的表中添加一个列,并在您的实体中添加一个包含唯一“计数器”的字段。这是使您的实体独一无二的计数器。

会有一个新表,比如“ENTITY_COUNTER”表,它有两列 - 1. 您的实体名称和 2. 给出的最高“可能”计数器。

您需要创建一个单例,以便在创建实体时将这些唯一计数器(认为令牌)分发给您的实体。每次实体获取令牌时,计数器都会增加 1。

您的单身人士不会每次都去数据库更新最高令牌。每次发出 1000 个唯一令牌时,它都会更新数据库。单例将获得一批 1000 个令牌来分发,一旦用完这些令牌,它将使用其持有的最高令牌编号更新 ENTITY_COUNTER 表。

例如ENTITY_COUNTER 中的第一个更新将是 EntityName 1000,每次创建 1000 个实体时,该数字将增加 1000。

这样您就可以在实体被持久化之前拥有一个唯一标识符。

【讨论】:

以上是关于休眠等于方法的主要内容,如果未能解决你的问题,请参考以下文章

java多线程--线程休眠

JAVA for循环执行500个休眠一段时间

初学线程休眠和礼让

QT不让windows休眠的方法

线程操作之线程休眠

win2012系统如何关闭休眠