简体   繁体   中英

Hibernate mappings for a single foreign key column to multiple tables

I have three tables similar to these:

vehicles
- id1
- id2
- vehicle_type_id
- vehicle_detail_id
- primary key(id1, id2)
buses
- id
...
cars
- id
...

vehicleTypeId decides the type of the vehicle and also from which table the vehicleDetails are to be fetched. Join is to be taken on vehicleDetailId of vehicle and id of a particular vehicleType. I created classes this way:

class Vehicle{
    VehiclePk pk;
    Long vehicleTypeId;
    Long vehicleDetailId;
}

class Bus extends Vehicle{
    Long id;
}

class Car extends Vehicle{
    Long id;
}

class VehiclePk {
    private Long id1;
    private Long id2;

    @Override
    public boolean equals(Object obj) {
        if(obj != null && obj instanceof VehiclePk) {
            VehiclePk p = (VehiclePk)obj;
            return id1.equals(p.id1) && id2.equals(p.id2);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (id1 + id2).hashCode();
    }
}

I tried combining and elements in the hibernate mapping file, using discriminator:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping schema="test_db">
    <class name="Vehicle" table="vehicles" discriminator-value="0">
    <composite-id name="pk" class="VehiclePK">
        <key-property name="id1" column="id1" type="long"/>
        <key-property name="id2" column="id2" type="long"/>
    </composite-id>
    <discriminator column="vehicle_type_id" type="long"/>
<property name="vehicleDetailId" column="vehicle_detail_id" type="long"/>

    <subclass name="Bus" discriminator-value="1">
        <join table="vehicles" >
            <key column="vehicle_detail_id" />
            ... 
        </join>         
    </subclass>
    <subclass name="Car" discriminator-value="2">
        <join table="vehicles" >
            <key column="vehicle_detail_id" />
            ... 
        </join>         
    </subclass>
</class>

There is something wrong with the mapping file, as the DB is not getting initialized. Please let me know if I have missed something. Thanks.

UPDATE : It gives ArrayIndexOutOfBoundsException: 1
Stacktrace :
...
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1206)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1026)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4421)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4734)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:943)
at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:778)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:504)
at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1385)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:306)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1389)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1653)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1662)
at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1642)
at java.lang.Thread.run(Thread.java:662)

This is a typical error message when the number of columns is not correct. In this case, you have only one primary key column in your join. Joins are primary-key related tables, so they need to have the same primary keys. In your case, the vehicles have two ids, while the buses and cars have only one.

The join element specifies a new table with the key column as both primary key and foreign key.

Consider making it a many-to-one which has a different type per subclass. (Instead of the join).

It would also map to a one-to-any property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM