使用Hibernate的问题:多个产品表使用一个订单表的问题

多个产品表使用一个订单表在Hibernate中的设计问题
由于产品内容的很大差异,使用了多个表保存不同的产品
产品表1:
product_1
--- product_id (pk)
--- product_name
--- other_info
....

产品表2:
product_2
--- product_id (pk)
--- product_name
--- other_info
...

等等其它产品表

使用同一个表来保存所有产品的订单
order
--- order_id (pk)
--- product_table
--- product_id (FK)
--- other_column
...

order.product_id和product_1 , product_2的product_id是多对一的关系
在order.hbm.xml中定义
<many-to-one name="product1" class="test.hibernate.Product1">
<many-to-one name="product2" class="test.hibernate.Product2">
可以实现操作,但使用起来很别扭,必需显式的指定产品类型
newOrder.addProduct1Order(),newOrder.addProduct2Order(),....
读订单时:
aOrder.getProduct1Order(), aOrder.getProduct2Order(),....

请教各位道友:有没有一个优雅的解决方法?

谢谢了!

能实现就可以的啊,就是麻烦点。
不过如果设计一个product接口,让所有的product类实现它,这样就可以直接aOrder.getProductOrder(),aOrder.setProductOrder()去做,但是product的mapping文件我就不太清楚怎么写了

这不是Hibernate的问题,是数据库设计的问题,既然都是产品这种对象,在系统设计看来,就是一个对象。你可以加一个“类型”属性,来区分不同种的产品。

--- product_id (pk)
--- product_name
--- product_type
--- other_info
....

<any>可以做到,要两列,一列保存关联实体的类型,另一列保存标识

谢谢robbin这么快回复
数据库使用的是MySQL,
1. 由于性能和其它方面的考虑,不可以把所有记录放到一个表中,mysql对超过千万记录的表操作很慢
2. 产品类型区别很大,有很多字段不相同,这么多字段放在一个表里也不合理

除了更改数据库设计的方法外,Hibernate可不可以解决这个问题呢?


<any>

可以做到,要两列,一列保存关联实体的类型,另一列保存标识

> 可以做到,要两列,一列保存关联实体的类型,另一列保存标
> ?>

那在Hibernate中如何写hbm呢?


<many-to-one name="写那个表呢?" class="这里那个类呢?">

我也一下子想不出来好办法,其实你的需求是进行动态映射。也就是说Order对象可以根据运行时刻的不同条件,选择映射不同的Product表。本来实现动态映射也不难,自己实现一个ClassPersister接口就行了。但问题是你不同Product表有不同的字段,那就意味着不同的Product肯定是不同的对象,有不同的属性。你写代码的时候是不知道在运行时刻有哪些属性可以存取的,因此连getter/setter方法有没有都不确定,怎么写的来程序呢?

我想不出来好办法,大家开动脑筋吧。

简化一下:
产品类的属性不相同,但在购买时可提供一组基本的getter/setter方法如:set/getProductId, set/getProductName, set/getPrice等

banq老大有没有好办法?

那你可以试试这样来做,自己实现ClassPersister,映射到一个接口上去,就像上面帖子提到的那样,接口里面定义getter/setter方法,然后在ClassPersiter实现类里面根据条件返回不同的接口实现类,也就是不同的Product类对象。

subclass此处是否能够使用?
根据不同的property,映射到不同的表。
(不是很有把握得说)

http://www.hibernate.org/44.html

Hibernate 2.2
introduction of <join> element, for mappings like
<class name="A" table="A" discriminator-value="A">
<id name="id" column="id">
<generator class="uuid.hex"/>
</id>
<discriminator column="discr" type="character"/>
<property name="a"/>
<join table="A1">
<key column="id"/>
<property name="a1"/>
<property name="a2"/>
</join>
<subclass name="B" discriminator-value="B">
<property name="b"/>
<join table="B1">
<key column="id"/>
<property name="b1"/>
</join>
<join table="B2">
<key column="id"/>
<property name="b2"/
</join>
</subclass>
<subclass name="C" discriminator-value="C">
<join table="C">
<key column="id"/>
<property name="c1"/>
<property name="c2"/>
</join>
</subclass>
</class>

faint,贴出来的<和&rt;之间的被吃掉了。....


<class name="A" table="A" discriminator-value="A">
<id name=
"id" column="id">
<generator class=
"uuid.hex"/>
</id>
<discriminator column=
"discr" type="character"/>
<property name=
"a"/>
<join table=
"A1">
<key column=
"id"/>
<property name=
"a1"/>
<property name=
"a2"/>
</join>
<subclass name=
"B" discriminator-value="B">
<property name=
"b"/>
<join table=
"B1">
<key column=
"id"/>
<property name=
"b1"/>
</join>
<join table=
"B2">
<key column=
"id"/>
<property name=
"b2"/
</join>
</subclass>
<subclass name=
"C" discriminator-value="C">
<join table=
"C">
<key column=
"id"/>
<property name=
"c1"/>
<property name=
"c2"/>
</join>
</subclass>
</class>

用ClassPersister实现一个接口对把Product添加到订单的操作确实简化了,可是如何在这些hbm中定义product和order表之间的映射关系呢?尤其是order表中如何设置many-to-one的属性?

根据曹晓钢的建议参考了hibernate_reference.pdf 第26页:


4.1.13. subclass
Finally, polymorphic persistence requires the declaration of each subclass of the root persistent class. For the
(recommended) table-per-class-hierarchy mapping strategy, the <subclass> declaration is used.
<subclass
name="ClassName" (1)
discriminator-value=
"discriminator_value" (2)
proxy=
"ProxyInterface" (3)
dynamic-update=
"true|false"
dynamic-insert=
"true|false">
<property .... />
.....
</subclass>
(1)name: The fully qualified class name of the subclass.
(2)discriminator-value (optional - defaults to the class name): A value that distiguishes individual subclasses.
(3)proxy (optional): Specifies a class or interface to use for lazy initializing proxies.
Each subclass should declare its own persistent properties and subclasses. <version> and <id> properties are
assumed to be inherited from the root class. Each subclass in a heirarchy must define a unique discriminatorvalue.
If none is specified, the fully qualified Java class name is used.

看来subclass应该是正确的方向,还在试验中。