Hibernate - 如何将新类映射到两个现有表

时间:2010-09-06 14:19:31

标签: hibernate orm hibernate-mapping

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

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

因此,当我添加,删除或保存VehicleWeapon实体时,相应的更改将反映在后备车辆和武器表中。 (我可能会做一个HQL查询,但我想先知道我问的想法是否可行。)

这可能吗?如果是的话,你能告诉我一个例子吗? (当然,车辆和武器类是假设的类。我确实有一个实际情况,我需要实现这个想法。)

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

4 个答案:

答案 0 :(得分:1)

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

我通过Googling 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作为参考。

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

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

答案 1 :(得分:1)

Hibernate支持使用<join>元素(或使用注释时的@SecondaryTable注释)在多个表中持久保存一个实体类。来自文档:

  

5.1.20. Join

     

使用<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.   
  3. schema(可选):覆盖root指定的模式名称    元件。
  4.   
  5. catalog(可选):覆盖root指定的目录名称   <hibernate-mapping>元素。
  6.   
  7. fetch(可选 - 默认为join):如果设置为加入,则为默认值,   Hibernate将使用内部联接   检索由类定义的<join>   或者它的超类。它将使用一个   由...定义的外连接   子类。如果设置为选择则   Hibernate将使用顺序选择   对于在子类上定义的<join>。   只有在一行时才会发出   代表一个实例   子类。内连接仍将是   用于检索由{定义的<join>   班级及其超类。
  8.   
  9. inverse(可选 - 默认为false):如果启用,则Hibernate不会   插入或更新属性   由此联接定义。
  10.   
  11. optional(可选 - 默认为false):如果启用,Hibernate会   仅在属性时插入行   此连接定义的值为非null。它   将始终使用外部联接   检索属性。
  12.         

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

    <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>
        ...
    
         

    此功能通常仅对此有用   遗留数据模型。我们建议更少   表格比类和细粒度   领域模型。但是,它很有用   用于在继承之间切换   映射策略在一个单一的   等级,如后面所述。

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

答案 2 :(得分:0)

不确定这是否是答案,但Hibernate确实允许“复合”关系,从而将一个类嵌入另一个类中,并进行映射。

例如,在这里我们创建“embeddable”类(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;
    }

    ...
}

在您的方案中,这有用吗?

答案 3 :(得分:0)

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