我在#hibernate
IRC上,有人与我分享了以下(部分)模式
@Entity
public MyEntity() {
... primary key, object properties, getters/setters go here ...
@Column(nullable=false)
private int hashCode;
public MyEntity() {
hashCode += id;
}
private final Set<String> tags = Sets.newHashSet();
public void addTag(String tag) {
if(tags.add(tag)) {
hashCode += tag.hashCode();
}
}
public void removeTag(String tag) {
if(tags.remove(tag) {
hashCode -= tag.hashCode();
}
}
public void hashCode() {
return hashCode;
}
... http://www.artima.com/lejava/articles/equality.html style equals ...
}
人们可以称之为“分段更新的缓存hashCode”。(这绝对不是一些评论者认为的“业务密钥”模式。“业务密钥”模式需要一个带有唯一性约束的列,比如用于相等性测试的用户名)。
当在 JPA/Hibernate 中使用时,这意味着@Entity
可以具有与 JBoss Equals 和 HashCode 文章中的“eq/hC with buisness [sic] key”类似的优势,但行为方式与开发人员期望的任何普通 Javabean 对象的行为方式(即不必像数据库行一样考虑对象):在持久化到数据库之前;在 EAGER
获取模式下的交易
之后;以及随时在事务
内或扩展
模式下使用LAZY
获取。
但是,确保hashCode
始终正确更新可能是一个真正的挑战。
这里有人对这种模式有任何经验吗,你能分享你关于它的发现(正面和负面)吗?我对陷阱非常感兴趣,但我对那些声称某事是“坏的”而没有关于为什么它是坏的坚实论据的评论一点也不感兴趣。
请注意,我知道JPA hashCode()/equals()的困境,但我不相信这一模式实际上已经在讨论中讨论过了。
这种模式最初是为了避免在 @Entity
s 中加载嵌套集合
时出现问题而提出的,例如在使用 EAGER @ElementCollection 的 find() 上遇到 Hibernate LazyInitializationException。
更新:一些评论者对现有方法非常感兴趣。为了避免疑问,我只是对这个新模式的优点感兴趣。供您参考,也请您不要再说您认为等于/hashCode应该如何实现,请注意,我已经在我的@Entity
s中使用了以下模式好几年了:
@Id
private UUID id = UUID.randomUUID();
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof MY_CLASS) || id == null)
return false;
MY_CLASS other = (MY_CLASS) obj;
return id.equals(other.id);
}
@Override
public int hashCode() {
Preconditions.checkNotNull(id, "id must be set before @Entity.hashCode can be called");
return id.hashCode();
}
我最近才尝试了一些新的东西,看看我是否真的需要一个像这样的独立方法
public boolean hasSameProperties(Note other) {
Preconditions.checkNotNull(other);
if (this == other)
return true;
return Objects.equal(source, other.source)
&& Objects.equal(title, other.title)
&& Objects.equal(tags, other.tags)
&& Objects.equal(contents, other.contents);
}
我写了,重写了,删除了两三个长答案,解释了为什么我认为这是一个坏主意,但最终,所有这些都是对什么是对象同一性的基本解释,我相信你明白这一点。
我对这种模式的回应是,它不能解决任何需要解决的问题。
所谓的“hashCode/equals问题”的解决方案非常简单。在创建实体时给它们一个标识符。坚持下去。基于等于
和hashCode
。不要依赖数据库或持久性层在插入时创建的标识符。这是一个非常古老的原则。
顺便说一句,对于实体来说,将等于
或hashCode
基于可变字段从来都是不对的。实体的平等不是这样工作的。实体不仅仅是一个状态包,它们是一个身份,某个状态碰巧附加到这个身份上。平等和hashcode必须基于身份,而不是状态。
这个业务密钥不是唯一的,因此它似乎是equals()的一个糟糕的选择。
业务密钥 1002 添加了标记 500 和标记 -502,业务密钥 995 添加了标记 3 和标记 2?这些对象真的是平等的吗?
无论您的特定实体服务于什么目的,32位数相对较低的冲突风险都是可以忍受的,但是将某个东西称为“模式”时,我们希望它实际上是正确的,而不仅仅是对于给定的数据大小不太可能失败。
这个函数我传入一个数组提示arr.map不是函数?
我试图做一个代码,将打印所有元素的内容与从一些链接,但它不起作用,我不知道为什么,这是代码: 当我粘贴“someurl”而不是
嗨,我想知道如果你有你要寻找的对象的Hashcode,是否可以直接访问HashSet的内容,有点像在HashMap中使用Hashcode作为键。 我想它可能会像这样工作: 谢谢 编辑:谢谢你的回答。好的,我知道我可能会稍微推动HashSet的契约,但是对于这个特定的项目,等式完全由hashcode决定,我确信每个hashcode/hashbucket只有一个对象。我非常不愿意使用HashMap的原
提示:Extra content at the end of the document这样的错误
从原理到应用分析什么是哈希? 一、什么是哈希? 哈希(hash):将任意长度的输入(关键字),通过Hash算法变成固定长度的输出。这个映射的规则就是对应的Hash算法,而原始数据映射后的二进制串就是哈希值,通常哈希值代表了关键字的存储位置。 但是为什么要这样做呢?或者说,哈希是怎样来的呢? 哈希的出现解决了两个问题:存储和搜索。 1. 存储(数据结构):如果在容器中保存对象及其关联的键,并且不用键
问题内容: 我了解到,哈希码是一个唯一标识参考号,它是一个十六进制数。 我的疑问是,参考数字代表对象的内存地址吗? 例如: 这段代码会返回我对象的内存地址吗? 问题答案: 哈希码不是唯一的标识。它只是一个数字,可以帮助您区分对象。两个不同的对象可能具有相同的哈希码,这很好。 HashCode特征: 如果obj1和obj2相等,则它们必须具有相同的哈希码。 如果obj1和obj2具有相同的哈希码,则