Hibernate映射具有一对多的多态关系

时间:2013-06-26 16:36:33

标签: java hibernate data-binding one-to-many hibernate-mapping

我有以下类图,我想将它映射到数据库(请注意,Person有一个包含Vehicle类对象的列表)。 enter image description here

我的数据库看起来像: enter image description here
数据库中表示Vehicle类的子类的所有表都包含超类Vehicle的所有字段。此外,所有关系都显示了从人到车,汽车和摩托车的一对多关系。

我的 hibernate映射文件如下: 的 Person.hbm.xml

<hibernate-mapping package="...."> 
    <class name="Person" table="Persons"> 
        <id name="key" column="Person_ID"> 
            <generator class="native"/> 
        </id> 
        <list name="ownedVehicles" inverse="false" cascade="all">
            <key column="Person_ID" not-null="true" />
            <list-index column="idx"/>
            <one-to-many class="Vehicle"/>
        </list>
    </class> 
</hibernate-mapping>

Vehicle.hbm.xml

<hibernate-mapping package="..."> 
    <class name="Vehicle" table="Vehicles"  polymorphism="implicit"> 
        <id name="id" type="int" column="Vehicle_ID"> 
            <generator class="increment"/>
        </id> 
        <property name="numOfSeats"/>
        <union-subclass name="Car" table="Cars"></union-subclass>
        <union-subclass name="Motorcycle" table="Motorcycles"></union-subclass>
    </class> 
</hibernate-mapping>

问题(我得到的错误)如下:

Hibernate: insert into Persons (Person_ID) values (default)
2013-06-26 15:41:52 WARN  JdbcCoordinatorImpl:424 - HHH000386: ResultSet had no statement associated with it, but was not yet registered
Hibernate: update Car set numOfSeats=? where Vehicle_ID=?
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

运行时出现此错误:

Car car = new Car();
car.setNumOfSeats(5);
Person person = new Person();
person.getOwnedVehicles().add(car);
ManagePerson managePerson = new ManagePerson();
Integer personID = managePerson.store(person);

ManagePerson的 store()功能实际上创建了一个会话和一个事务,然后使用Hibernate提供的 save()方法将对象持久保存到数据库中。

据我所知,Hibernate通常会插入到Persons中,然后插入Cars并最终更新Cars(更新完成后将外键保存在Cars表中,该表将引用拥有汽车的Person)。但是,这不是这种情况,并且插入汽车似乎被忽略了。通过在上面给出的代码上尝试person.getOwnedVehicles().add(vehicle);而不是person.getOwnedVehicles().add(car);,我了解了Hibernate的工作原理 正如您可能理解的那样,我试图看看Hibernate是否真正了解记录应该在哪个“子类”表中,这取决于Person类的ownedVehicle列表中包含的对象的类。例如,如果ownedVehicles有一个类Car的对象和一个类Motorcycle,那么每个都应该分别转到Cars和Motorcycle表。

注意:我使用的是Hibernate 4.2.2和HSQLDB 2.2.9。

我将不胜感激任何帮助 感谢。

2 个答案:

答案 0 :(得分:1)

如果managePerson.store(...)方法没有对“getOwnedVehicles()”中的对象进行递归调用,那么它可以调用它们的“store”方法,那么你不应该期望创建它“car”对象将被插入表中。

你实际上是在调用“managePerson.store”而不是“manageCar.store”,我必须看到.store(...)方法中的代码才能确定,但​​我希望它不是对车辆进行迭代并且不对任何已发现的车辆进行插入(为什么它除非你明确地将它构建成这样做?)。

答案 1 :(得分:1)

我认为这只是不正确使用Hibernate的隐式多态的问题。 您的案例的隐式多态性只能通过更改您的列表来实现 逆=“真”。当然,如果您的Vehicle类也“知道”与Person类的关系(例如,通过添加'Owner'属性和相应的映射),则可以这样做。

(看看this表和“每个具体类(union-subclass)表”和一对多关联的情况。

如果启用日志记录并将日志级别提升为DEBUG,您会看到当前Hibernate尝试使用Person_ID而不是Car表来更新Vehicles表,就像您想要的那样。这是因为inverse =“true”以及Table-per-concrete-class映射策略和隐式多态的组合的局限性(请参阅文档)。

因此,通过让Vehicle类了解其所有者并使用inverse =“true”,您应该能够成功完成您想要做的事情。要么是这个,要么尝试其他继承映射策略之一(再次查看文档)。