作者:再见看淡_266 | 来源:互联网 | 2023-01-13 19:10
最近,在hibernate中使用JPA注解方式配置bean遇到联合主键时采用@EmbeddedIdprivateBeanPKid;再顶一个BeanPK对象@Embedd
最近,在hibernate中使用JPA注解方式配置bean
遇到联合主键时采用
@EmbeddedId
private BeanPK id;
再顶一个 BeanPK 对象
@Embeddable
public class BeanPK implements Serializable{}
看文档中,要求@Embeddable的BeanPK需要重写hashCode、equals方法;
equals好说;
但hashCode问题就来了
就我所知 java中的hashCode是根据对象的内存地址计算得到的;
String特殊一些,根据字符串内容计算得到的;而String常出现在常量池中。
这样java可以保证每个对象的hashCode是一个固定值。
而我重写BeanPK中的hashCode方法,只能根据BeanPK中的属性的hashCode计算而出。
这样一旦BeanPK中的某个属性改变(例如:调用BeanPK.setXXXX()方法)后 hashCode的值就会改变。
这样就会带来几个问题:
1.当BeanPK放入到集合中
由于对象存放到集合中的位置依赖对象的hashCode值。
那么,当对象放入集合后,再改变hashCode的值,集合就找不到该对象了。
Set中也就无法过滤重复对象。
例子:
BeanPK pk = new BeanPK("id","name");
Bean b = new Bean(pk,"age");
Map
map = new HashMap();
map.put(pk,b);
pk.setName("newName");//BeanPK 的hashCode会根据id和name计算,setName后hashCode改变
map.get(pk);//由于hashCode改变,Map已经找不到匹配的key了,这里返回null
2.由于@Embeddable要求实现Serializable
那么当反序列后,hashCode不一致会不会带来同样的问题?
希望高手指定一下,
另外:在使用@Embeddable时,需不需要重写hashCode方法?
8 个解决方案
我刚刚大二 我说说我对于hashcode的比较浅显的理解。我前段时间也有同样的疑问。后来我查了查。
set是要求无序不重复的 而要保证添加进去的每个对象都是不重复的那么只能重写该对象的equals和hashcode方法。在添加的时候就已经改变了hashcode。
也许文不对题 但我就是这样去记住使用的 期待大神的解答。
大二就这么厉害了。。。。。
hashCode不一定是根据内存得到的。string对象的hashCode,就是每个字符乘以31的次方作为分别的权重计算得到的。你可以看下源码。实际上hash函数的设计本来就很复杂。像你这种情况要避免变动的成员用来计算hashCode。
不过内容变了对象本来就不是同一个了吧。。比如你这个对象,性别变成女了。。还是你自己么。。
Map的key要求是一个不可变的值对象。可变的不应该作为key。