Question

I am facing difficulty in writing hibernate mapping for below table structure

Throttle                SAMPLEDATA
-------------          --------------------------------
OBJID  INT(PK)      OBJID | NUM_WHEELS |    NUM_BRAKES
NUM_WHEELS INT         --------------------------------
NUM_BRAKES INT      1234  | 2   |  2
                    1235  | 2   |  2
                    1236  | 2   |  2

NOTCH                   SAMPLEDATA
-------------           ---------------------------------------
THROTTLE_OBJID(PK+FK)INT    THROTTLE_OBJID |POSITION |  SECONDS
POSITION INT(PK)        ---------------------------------------
SECONDS INT         1234  | 1       |  2
                    1234  | 2           |  2
                    1234  | 3       |  2


DYNBRAKE                SAMPLEDATA
-------------           ---------------------------------------
THROTTLE_OBJID(PK+FK)INT    THROTTLE_OBJID |POSITION |  SECONDS
POSITION INT(PK)        ---------------------------------------
SECONDS INT         1235  | 0       |  2
                    1235  | 2       |  2
                    1235  | 4       |  2

NOTCH & DYNBRAKE tables has a composite primary key as combination of THROTTLE_OBJID & POSITION. My requirement is, whenever i delete a record from Throttle table, the corresponding references in Notch and DynBrake tables should be deleted.

for this DB structure i have my hibernate mapping as below.

THROTTLE mapping file
=========================

<hibernate-mapping> 
    <class name="Throttle" table="THROTTLE">

        <id name="objId">
            <generator class="sequence">
                <param name="sequence">throttle-seq</param>
            </generator>
        </id>

        <property name="numWheels" type="int" column="NUM_WHEELS" />
        <property name="numBrakes" type="int" column="NUM_BRAKES" />

        <map name="notch" cascade="all" inverse="true">
            <key column="THROTTLE_OBJID"/>
            <index column="POSITION" type="int"/>
            <one-to-many class="Notch"/>
        </map>  

        <map name="dynbrake" cascade="all" inverse="true">
            <key column="THROTTLE_OBJID"/>
            <index column="POSITION" type="int"/>
            <one-to-many class="DynBrake"/>
        </map>  
    </class>
</hibernate-mapping>

NOTCH mapping file
=========================    

<hibernate-mapping>
    <class name="Notch" table="NOTCH">
        <composite-id name="id" 
            class="Order$Id">
        <key-property name="position" column="POSITION" type="int"/>
        <key-one-to-many name="throttleObjId"/>
        </composite-id>
        <many-to-one name="throttleObjId" class="Throttle" column="THROTTLE_OBJID"/>
        <property name="seconds" type="int" column="SECONDS" />                    

    </class>
</hibernate-mapping>

DYNBRAKE mapping file
=========================
<hibernate-mapping>
    <class name="DynBrake" table="DYNBRAKE">
        <composite-id name="id" 
            class="Order$Id">
        <key-property name="position" column="POSITION" type="int"/>
        <key-one-to-many name="throttleObjId"/>
        </composite-id>
        <many-to-one name="throttleObjId" class="Throttle" column="THROTTLE_OBJID"/>
        <property name="seconds" type="int" column="SECONDS" />                    
    </class>
</hibernate-mapping>

With this mapping configuration, i am getting "Collection can not be initialized for #Notch" exception. I have to maintain the in Throttle.hbm.xml as there is good amount of code dependant on this map in some other part of application. so i dont want to change the collection mapping to SET or BAG here.

Can anybody help me out in this regard.

Was it helpful?

Solution

From the description of the Notch & DynBrake objects/tables, I would suggest to change the mapping. We do not need these objects/entities to be represented as separated objects. Because there is only composite-id ... it brings lot of troubles.

For these purposes Hibernate has composite-elements. So let's change the Throttle.hbm.xml <map> mapping (and throw the other files):

 <map name="notch" cascade="all-delete-orphan" inverse="true">
    <key column="THROTTLE_OBJID"/>
    <index column="POSITION" type="int"/>
    //<!--<one-to-many class="Notch"/>-->
    <composite-element class="Notch">
        <parent name="throttleObjId" />
        <property name="seconds" type="int" column="SECONDS" />
    </composite-element>
</map>  

<map name="dynbrake" cascade="all-delete-orphan" inverse="true">
   <key column="THROTTLE_OBJID"/>
   <index column="POSITION" type="int"/>
   //<!--<one-to-many class="DynBrake"/>-->
   <composite-element class="DynBrake">
       <parent name="throttleObjId" />
       <property name="seconds" type="int" column="SECONDS" />
   </composite-element>
</map> 

The model will remain the same, but because of the nature of the Notch and DynBrake - mapping is simplified. Querying would be working, insert/update/delete as well. Also the cascading is changed to all-delete-orphan, which fits more into this scenario

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top