1

我有两个实体:车辆和武器类。它们分别映射到 Vehicle.hbm.xml 和 Weapon.hbm.xml。两者都有各自的 DAO。一切正常。

这是我的想法。我想创建一个类 VehicleWeapon,它具有 Vehicle 和 Weapon 实体的所有属性。我要声明一个 Hibernate 映射文件:VehicleWeapon.hbm.xml。我希望映射文件中的属性与武器和车辆实体的属性相匹配。

因此,当我添加、删除或保存 VehicleWeapon 实体时,相应的更改将反映在支持的 Vehicle 和 Weapon 表上。(我可能会做一个 HQL 查询,但我想先知道我要问的想法是否可行)。

这可能吗?如果是,你能给我举个例子吗?(当然,Vehicle 和 Weapon 类是假设的类。我确实有一个需要实现这个想法的实际场景)。

或者有什么更好的选择?您能否提供直接链接或具体示例?非常感谢。

4

4 回答 4

1

Hibernate 支持使用<join>元素(或使用@SecondaryTable注解时的注解)跨多个表持久化一个实体类。从文档中:

5.1.20。加入

使用该<join>元素,可以将一个类的属性映射到具有一对一关系的多个表。例如:

<join
        table="tablename"                        (1)
        schema="owner"                           (2)
        catalog="catalog"                        (3)
        fetch="join|select"                      (4)
        inverse="true|false"                     (5)
        optional="true|false">                   (6)

        <key ... />

        <property ... />
        ...
</join>
  1. table: 连接表的名称。
  2. schema(可选):覆盖根元素指定的模式名称。
  3. catalog(可选):覆盖根 <hibernate-mapping>元素指定的目录名称。
  4. fetch(可选 - 默认为join):如果设置为 join,默认情况下,Hibernate 将使用内部连接来检索<join>由类或其超类定义的。它将为子类定义的 a 使用外连接。如果设置为选择,那么 Hibernate 将使用顺序选择来<join>定义子类。仅当行表示子类的实例时才会发出此消息。内部连接仍将用于检索<join>由类及其超类定义的。
  5. inverse(可选 - 默认为false):如果启用,Hibernate 将不会插入或更新此连接定义的属性。
  6. optional(可选 - 默认为false):如果启用,Hibernate 将仅在此连接定义的属性为非空时插入一行。它将始终使用外部连接来检索属性。

例如,一个人的地址信息可以映射到一个单独的表,同时保留所有属性的值类型语义:

<class name="Person"
    table="PERSON">

    <id name="id" column="PERSON_ID">...</id>

    <join table="ADDRESS">
        <key column="ADDRESS_ID"/>
        <property name="address"/>
        <property name="zip"/>
        <property name="country"/>
    </join>
    ...

此功能通常仅对遗留数据模型有用。我们建议使用比类更少的表和细粒度的域模型。但是,它对于在单个层次结构中的继承映射策略之间切换很有用,如下所述。

像您一样使用组合是另一种选择,但它显然会引入另一个表(用于“聚合”实体)。

于 2010-09-06T21:54:28.497 回答
1

我找到了一个可行的解决方案。正如我之前提到的,我不允许修改 Vehicle 和 Weapon 实体以及相应的映射文件。甚至不允许使用单个注释。

我通过谷歌搜索 Ben 的建议找到了这个答案,这让我找到了这些文章: http ://www.mkyong.com/hibernate/hibernate-one-to-one-relationship-example/ 和http://www.vaannila.com /hibernate/hibernate-example/hibernate-mapping-one-to-one-1.html

mkyong 的建议很好,但我不喜欢同时保留和分配主键的想法,因为我无法编辑 Vehicle 和 Weapon 类的映射文件。请参阅评论“一对一关系的主要困难是确保两者都分配了相同的主键”

vaannila 的建议在某种程度上很有趣。它具有一对一的关系,但不需要对其他映射文件进行任何编辑。

首先,我声明了我的 VehicleWeapon.hbm.xml 如下:

<hibernate-mapping package="com.armory">

    <id name="id" type="long" >
        <column name="id"  />
        <generator class="native" />
    </id>

    <many-to-one name="vehicle" class="Vehicle" 
            column="vehicle_column"  cascade="all" unique="true" />

    <many-to-one name="weapon" class="Weapon" 
            column="weapon_column"  cascade="all" unique="true" />

然后我声明了我的标准 VehicleWeapon POJO 类。以及相应的DAO实现。

我运行了几个 Junit/Spring 测试。我能够毫无问题地保存、删除、检索。所有动作级联到相应的武器和车辆表。

此方法的唯一缺点是 Hibernate 将创建第三个表 vehicle_weapon ,其中分别包含车辆和武器表的 id 作为参考。

好消息是我没有编辑任何现有实体或映射文件。我创建了一个新对象并从两个表中组合了一个新对象。

我仍然希望能够直接映射到武器和载具的属性,而不是直接映射到武器和载具实体。但就目前而言,我认为这是可以接受的。

于 2010-09-06T17:19:12.677 回答
0

使用 joincolumn 和 inverseJoincolumn 注释连接两个表(Vehicle 和 Weapon)并将它们放入事务表(VehicleWeapon)。使用任何映射(onetoone、onetomany 等)通过 ondeletecascade 和 fetch 映射车辆 amd waepon 表。

于 2011-12-15T19:11:55.283 回答
0

不确定这是否是答案,但 Hibernate 确实允许“复合”关系,即您将一个类嵌入到另一个类中,然后映射。

例如,这里我们创建“可嵌入”类(Vehicle),然后将其“嵌入”到 VehicleWeapon 中:

import javax.persistence.Embeddable;

@Embeddable
public class Vehicle
{
    ...
}

嵌入这里:

@Entity
public class VehicleWeapon
{
  private long id;  
  private String name;
  private Vehicle vehicle;

  ...

    @Embedded
    public Vehicle getVehicle()
    {
      return vehicle;
    }

    public void setVehicle(Vehicle vehicle)
    {
        this.vehicle = vehicle;
    }

    ...
}

这对你的场景有帮助吗?

于 2010-09-06T15:14:21.000 回答