[Hibernate]重写eq/hc方法有必要区分POJO一对一、一对多和多对多的情况吗?

07-11-25 javayuan
    

分析了一下,ID作为主键会出问题主要是在用到Set的情况下(也就是一对多或者多对多),比如说某用户保存了两个新建的email。

......   
User user = session.load(User.class,new Integer(1));   
Email e1 = new Email();   
Email e2 = new Email();   
e1.setAddress("xxx@xx.com");   
e2.setAddress("yyy@yy.com");   
user.getEmails().add(e1);//这时候id为null,即使equals方法里逻辑是“id为空则返回false”   
user.getEmails().add(e2);//hashcode值又该如何计算?所以这时候eq/hc方法要用业务关键属性来写   
session.save(user);   
.....   
<p>

但业务键值比对的方法有时候好像又不适用

举个例子吧:

一对一的情况。现在有两个表,用户表和用户联系方式表,用户表作为主表,联系方式表的主键作为外键与用户表关联。联系方式表除了主键其余字段都可为空,这时候如果用“值比对”的方式写eq/hc,很有可能逻辑上应该不相等的两个对象equals的结果是true(比如说两个不同对象的所有属性值都为空),得到的hashcode也是一样的。这时候为了避免这个问题,eq/hc方法可以用id来写。因为是一对一的关系,用不到Set,所以也不会产生上面提到的问题。

总结了一下,就是:

1、不改写eq/hc,在跨session操作时会出现问题;

2、一对多或者多对多关系中,pojo的eq/hc不能用id来写,而应该用业务关键属性来写;

3、一对一关系中,pojo的eq/hc可以用id来写,如果用属性值比对反而有可能出问题。

以上只是个人观点,不知道对不对。

有朋友和我说:

==========================

一对多 一般都是多方设置一方

Email e1 = new Email();     
Email e2 = new Email();     
e1.setAddress("xxx@xx.com");     
e2.setAddress("yyy@yy.com");     
e1.setUser(user);   
e2.setUser(user);   
session.save(e1);    
session.save(e2);    
<p>

这样就不会出现上述问题了

===========================

这样是解决了问题。不过在多对多关系中,这方法就行不通了吧。

我搞不明白的是:Hibernate官方不推荐用id来重写eq/hc,究竟是因为什么呢?仅仅因为对象在自由状态的时候id为null而不推荐使用来重写吗?

如果是这样的话,那只要在多对多关系中避免使用id重写eq/hc就可以了,是这样吗?

    

banq
2007-11-26 09:44

第一种方式需要激活cacade="all",且主键由Hibernate产生,使用merget等方法、

第二种方式则是通常使用方式。

关于你说的那些烦琐POJO重写eq/hc方法,都是画蛇添足,将问题复杂化,违反对象基本原则封装性,而且使用POJO概念不准确,应该是Entity概念,万事万物实体都有一个标识ID,不是外界能够修改的,你是程序员,不是上帝,所以,要用好Hibernate,基础读物就是Evans DDD.

javayuan
2008-12-08 18:11

本来没看懂banq的回复,今天看懂了,感谢!

javayuan
2008-12-08 18:42

同时为了banq推荐的DDD,再次感谢 :)