Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Hibernate映射中覆盖键的等于?_Hibernate_Orm_Map_Overriding_Equals - Fatal编程技术网

如何在Hibernate映射中覆盖键的等于?

如何在Hibernate映射中覆盖键的等于?,hibernate,orm,map,overriding,equals,Hibernate,Orm,Map,Overriding,Equals,我希望重写基于业务密钥而不是对象标识的equals,但我无法使它与hibernate一起工作 我知道有人问过类似的问题,阅读答案(如)有助于理解不破坏等价关系,使用instanceof代替getClass,使用Getter代替field refs。等等,但我的equals/hashCode实现仍然打破了映射的休眠状态 我没有得到一个错误,hibernate将映射中的所有3个实体正确地保存在数据库中,但当我再次读取带有映射的实体时,它只读取1而不是所有3个实体。hibernate记录的sql在my

我希望重写基于业务密钥而不是对象标识的equals,但我无法使它与hibernate一起工作

我知道有人问过类似的问题,阅读答案(如)有助于理解不破坏等价关系,使用instanceof代替getClass,使用Getter代替field refs。等等,但我的equals/hashCode实现仍然打破了映射的休眠状态

我没有得到一个错误,hibernate将映射中的所有3个实体正确地保存在数据库中,但当我再次读取带有映射的实体时,它只读取1而不是所有3个实体。hibernate记录的sql在mysql中执行时会选择所有3个正确的实体

该项目基于Spring3.2.1、Hibernate4.1.5和JPA注释

更新 调试hibernate时,它似乎为3个映射实体中的每个实体调用hashCode,但除hibernate生成的id外,所有值都为null。因此,由重写方法计算的hashCode始终相同。我想这就是为什么地图上只添加了一个实体。但我不明白为什么hibernate在从数据库加载数据之前会计算哈希代码

例子 在下面的示例中,我在一个包含3个简单实体的项目中重现了错误(所有实体都带有hibernate生成的ID):

  • 项目
  • 语言
  • 语言细节
项具有语言详细信息的映射,其中语言是关键:

@OneToMany(mappedBy="item", orphanRemoval=true, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@MapKey(name="language")
private Map<Language, LanguageDetails> languageDetails = new TreeMap<Language, LanguageDetails>();
以下集成测试使用上述equals/hashCode失败,而不使用以下代码则成功:

Item item = new Item();
Language english = languageService.getByCode("en");
Language german = languageService.getByCode("de");
Language spanish = languageService.getByCode("es");

item.getLanguageDetails().put(english, new LanguageDetails(item, english, "ice cream"););
item.getLanguageDetails().put(spanish, new LanguageDetails(item, spanish, "helado"););
item.getLanguageDetails().put(german, new LanguageDetails(item, german, "eis"););

//save - stores all 3 languageDetails correct in mysql
int id = itemService.create(item); 

//read - loads only 1 languageDetails (de)
Item readItem = itemService.getById(id); 

//java.lang.AssertionError: expected:<3> but was:<1>
Assert.assertEquals(item.getLanguageDetails().size(), readItem.getLanguageDetails().size());
Item项=新项();
Language english=languageService.getByCode(“en”);
语言德语=languageService.getByCode(“de”);
西班牙语=languageService.getByCode(“es”);
item.getLanguageDetails().put(英语,新语言详细信息(item,英语,“冰淇淋”);
item.getLanguageDetails();
item.getLanguageDetails().put(德语,新语言详细信息(item,德语,“eis”););
//保存-在mysql中正确存储所有3种语言的详细信息
int id=itemService.create(item);
//读取-仅加载1种语言详细信息(de)
Item readItem=itemService.getById(id);
//java.lang.AssertionError:应为:但为:
Assert.assertEquals(item.getLanguageDetails().size(),readItem.getLanguageDetails().size());

我做错了什么?

我花了将近一周的时间调试、编写解决方案,并试图理解这个问题,在我越来越绝望的反复尝试中,我找到了解决方案:

我将我的hibernate版本从4.1.5改为4.1.8,所有的痛苦都消失了。这是hibernate中的一个bug,在版本中已修复

我一定会在下次早些时候查看错误报告

Item item = new Item();
Language english = languageService.getByCode("en");
Language german = languageService.getByCode("de");
Language spanish = languageService.getByCode("es");

item.getLanguageDetails().put(english, new LanguageDetails(item, english, "ice cream"););
item.getLanguageDetails().put(spanish, new LanguageDetails(item, spanish, "helado"););
item.getLanguageDetails().put(german, new LanguageDetails(item, german, "eis"););

//save - stores all 3 languageDetails correct in mysql
int id = itemService.create(item); 

//read - loads only 1 languageDetails (de)
Item readItem = itemService.getById(id); 

//java.lang.AssertionError: expected:<3> but was:<1>
Assert.assertEquals(item.getLanguageDetails().size(), readItem.getLanguageDetails().size());