Hibernate建模的一些疑问

目前正基于Hibernate来开发一些项目。
建模中,碰到一些问题,不知该如何解决,请教各位。
问题是这样的:假设我需要存储三个类,A,B,C,其中A是B和C的父类。
那么,按照Hibernate的建议,我应该在xml中定义A的存储,并将B,C作为A的subclass来声明。但是这样会遇到一些问题。比如B,C各自的属性中,有not-null的字段,比如B,C的各自属性中,有外键关联等等...。当然,可以用join-subclass来解决这两个问题,但我不清楚对hibernate,这两种方式有什么区别,为什么文档中推荐subclass而非join-subclass。
另外,两种方式都无法解决一个问题:假设A有一个属性name,name应该在B和C中各自为unique的,但是B和C的对象应该可以拥有相同的name。这个问题该如何建模?

我觉得将多个子类放在同一张表中会带来不少问题,所以目前我的方式是将B和C拆开。由于我的系统中,没有类型为A的对象,只有类型为B,C的对象。所以我在hbm.xml中,没有声明A,直接将B,C声明为顶级的class。把A的属性放到B,C中,将B,C彻底拆分为两个单独的表。这样能解决上述的问题。

但是这样做毕竟是一种比较不符合面向对象的方式,也并不好。
希望大家一起来讨论一下,在Hibernate中,如果需要实现比较复杂的类层次结构,该如何建模比较好,各种建模的方式有何优劣,特点是什么,有什么地方需要注意的。

joined-subclass会带来很多连接操作,这可能会影响性能。

>另外,两种方式都无法解决一个问题:假设A有一个属性name,name应该在B和C中各自为unique的,但是B和C的对象应该可以拥有相同的name。<
这没办法,关系模型和对象模型毕竟有很大的差异。除非按照你说的做法。

我也觉得是对象持久化程序无法避免的一些问题。毕竟要将oo模型映射到一个关系模型中,确实有牵强的地方。
开这个帖子,希望大家能发表一些用Hibernate建模的Best practice,把自己的经验共享一下,避免大家走弯路。我现在建模中,经常由于对Hibernate不够了解,经验不足,做出一些OO上正确,但是在Hibernate上有这样,那样的问题的设计。
在此抛砖引玉,望不吝赐教。
(现在时间不够,明天把我的一些经验贴出来)

试试看用一张表来存储A,B和C,我觉得不会有什么问题。

A.name存储在一个字段中 parent_name
B.name和C.name存储在另一个字段中 sub_name

A <-> table的时候,取parent_name映射name属性,sub_name字段不取

B,C <-> table的时候, 取sub_name映射name属性,取parent_name字段回溯父类。

Robbin的方法应该是可行的。只是看上去稍有些不太perfect而已。
其实,我觉得这些问题的产生原因是:在OO中,一个类继承另一个类,其含义更多的是行为的继承和重载,运用继承的目的也主要在于此。而在Hibernate中,其实,继承的语义更像是实体-关系模型中的isa关系。虽然从意义上来说,两者都是表示了A is a B,但是前者注重于行为,后者注重于属性的存储。
很多时候,如果是从OO->DB的设计过程,对于一个类层次,其实并不一定需要他们持久化时有固定的关系,比如存放在同一个表中,而Hibernate强调的却是实体的isa关系,这就强调了必须在表这个层次上用一张表存放父类的属性。这带来的副作用就是设计OO的时候,有点束手束脚。
我觉得我提到的不少问题就是由于这个产生的。不知大家看法如何。

我不清楚你说的束手束脚体现在什么地方?

一个系统,笼统的来说分为Business Layer和Persistent Layer,在Persistent Layer都是PO,而对PO的控制类都在Business Layer。而你说的OO的类继承强调行为的继承和重载其实都出现在控制类中,也就是Business Layer层。而Persistent Layer里面的PO其实就是getter/setter方法,不应该有和业务逻辑相关的行为,这些行为应该从PO,也就是说应该从Persistent Layer剥离出来放到Business Layer,由控制类来完成。因此所有的PO,它的继承行为只体现为属性的继承,最多就是getter/setter方法的覆盖和重载。

因此:

Business Layer:控制类,业务逻辑实现,强调行为的继承和重载,业务流程的控制

Persistent Layer:持久类,存储实现,注重于属性的存储和PO状态的管理