gpt4 book ai didi

java - Hibernate代理作为HashMap中的键

转载 作者:行者123 更新时间:2023-11-30 06:52:44 25 4
gpt4 key购买 nike

今天我花了一些时间调试 hibernate 的一个问题,简化的示例如下:

Map<Cat, Owner> catsMap = new HashMap();
List<Owner> owners = ownerRepo.getOwners();
for (Owner owner : owners) {
// cat is Lazy, according to its nature :)
catsMap.put(owner.getCat(), owner);
}

Cat cat = catRepo.findOne("meow");
Owner meowOwner = catsMap.get(cat);

此时 meowOwner 为 null,因为在 catsMap 键集中找不到它。我花了一些时间才弄清楚原因,因为在调试窗口中,我看到名为“meow”的 Cat 存在于 catsMap 的键集中,而且,如果我编写一个表达式

catsMap.keySet().iterator().next().equals(cat)

它返回true,但哈希码是相同的,相同的值

catsMap.get(cat)

在同一表达式窗口中仍然返回 null。最后我打电话了

catsMap.keySet().iterator().next().getClass()

最后发现它是long.path.to.package.Cat_$$_jvstaea_41,所以它是一个代理,并且equals在检查类相等性时失败。解决方案当然是显而易见的,但问题是为什么我有

catsMap.keySet().iterator().next().equals(cat)

返回true?我也尝试过颠倒大小写

cat.equals(catsMap.keySet().iterator().next())

并且这个返回 false,这打破了 equals() 传递性约定。

PS:在所有示例中,我假设当前数据库中只有一只猫和一个主人

最佳答案

Cat cat = catRepo.findOne("meow") 应返回相同的实例,除非您的 Map 位于初始事务之外。如果您想在事务之外存储实体,请确保在存储之前取消代理。

public T unproxy(T proxied)
{
T entity = proxied;
if (entity instanceof HibernateProxy) {
Hibernate.initialize(entity);
entity = (T) ((HibernateProxy) entity)
.getHibernateLazyInitializer()
.getImplementation();
}
return entity;
}
<小时/>

您必须确保对 equalshashCode 覆盖使用正确的语法。这是一个实现示例:

@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof MyEntityClass))
return false;

MyEntityClass other = (MyEntityClass) obj;
return Objects.equals(getId(), other.getId());
}

@Override
public int hashCode() {
return Objects.hash(getId());
}

注意:不要直接使用字段 this.id,最好使用 getter 来允许 Hibernate 的代理在必要时解析实体。另外,优先选择 instanceof 而不是 getClass() != obj.getClass(),第一个将正确处理实现和扩展,而不是第二个。

关于java - Hibernate代理作为HashMap中的键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42422397/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com