1

我有以下类图,我想将其映射到数据库(请注意,Person 有一个包含 Vehicle 类对象的列表)。 在此处输入图像描述

我的数据库也看起来像: 在此处输入图像描述
数据库中表示 Vehicle 类的子类的所有表都具有超类 Vehicle 的所有字段。此外,所有关系都显示了从人到车辆、汽车和摩托车的一对多关系。

我的休眠映射文件如下: 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>

车辆.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)。但是,情况并非如此,插入 Cars 似乎被跳过了。person.getOwnedVehicles().add(vehicle);我通过尝试而不是 person.getOwnedVehicles().add(car);上面给出的代码来理解 Hibernate 在这里的工作原理 。
正如您可能理解的那样,我试图查看 Hibernate 是否真正了解记录应该放在哪个“子类”表中,具体取决于 Person 类的ownedVehicle 列表中包含的对象的类。例如,如果 ownVehicles 有一个 Car 类对象和一个 Motorcycle 类对象,那么这些对象中的每一个都应该分别转到 Cars 和 Motorcycle 表。

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

我将不胜感激。
谢谢。

4

2 回答 2

1

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

您实际上是在调用“managePerson.store”而不是“manageCar.store”,我必须查看 .store(...) 方法中的代码才能确定,但​​我希望它不会进行迭代的车辆,并且没有为任何发现的车辆进行插入(除非您明确构建它来执行此操作,否则为什么要插入?)。

于 2013-06-27T01:26:32.400 回答
1

我认为这只是对 Hibernate 的隐式多态性的错误使用的问题。您的案例的隐式多态性只能通过将您的列表更改为具有 inverse="true" 来工作。如果您的 Vehicle 类也“知道”与 Person 类的关系(例如,通过添加“Owner”属性和相应的映射),这当然可以完成。

(看看这个表和“每个具体类(联合子类)的表”和一对多关联的情况。

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

因此,通过让 Vehicle 类知道它的 Owner 并使用 inverse="true" 您应该能够成功地完成您想做的事情。无论是这个还是尝试其他继承映射策略之一(再次查看文档)。

于 2013-06-28T13:50:42.597 回答