我有两个实体:车辆和武器类。它们分别映射到Vehicle.hbm.xml和Weapon.hbm.xml。两者都有各自的DAO。一切正常。
这是我的想法。我想创建一个类VehicleWeapon,它具有Vehicle和Weapon实体的所有属性。我想声明一个Hibernate映射文件:VehicleWeapon.hbm.xml。我希望映射文件中的属性与武器和车辆实体的属性相匹配。
因此,当我添加,删除或保存VehicleWeapon实体时,相应的更改将反映在后备车辆和武器表中。 (我可能会做一个HQL查询,但我想先知道我问的想法是否可行。)
这可能吗?如果是的话,你能告诉我一个例子吗? (当然,车辆和武器类是假设的类。我确实有一个实际情况,我需要实现这个想法。)
或者有更好的选择?您能提供直接链接或具体示例吗?非常感谢。
答案 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>
table
:已加入表格的名称。schema
(可选):覆盖root指定的模式名称 元件。catalog
(可选):覆盖root指定的目录名称<hibernate-mapping>
元素。fetch
(可选 - 默认为join
):如果设置为加入,则为默认值, Hibernate将使用内部联接 检索由类定义的<join>
或者它的超类。它将使用一个 由...定义的外连接 子类。如果设置为选择则 Hibernate将使用顺序选择 对于在子类上定义的<join>
。 只有在一行时才会发出 代表一个实例 子类。内连接仍将是 用于检索由{定义的<join>
班级及其超类。inverse
(可选 - 默认为false
):如果启用,则Hibernate不会 插入或更新属性 由此联接定义。- 醇>
optional
(可选 - 默认为false
):如果启用,Hibernate会 仅在属性时插入行 此连接定义的值为非null。它 将始终使用外部联接 检索属性。例如,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。