-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: updating referenced subclass not working
PostPosted: Mon Mar 15, 2004 6:38 am 
Newbie

Joined: Thu Oct 09, 2003 4:30 am
Posts: 7
I'm using Hibernate 2.1 and McKoi 1.0.2.

Problem: null values in referenced subclass. Please read the following for a full description.

The following mapping represents a Device that has a one-to-many relationship with BaseItem. BaseItem has two subclasses Item and ArrayItem. The ArrayItem has a one-to-many relationship with its sibbling subclass Item.

Code:
                                            *             1
                                  BaseItem  --------------- Device
                                      ^
                                      |
                       -------------------------------
                       |                              |
                       |   *                   1      |
                     Item  ---------------------  ArrayItem

<hibernate-mapping>
  <class name="dvs.summit.data.items.BaseItem" discriminator-value="base">
    <id name="id" type="long" column="id" unsaved-value="null">
      <generator class="hilo"/>
      </id>
      <many-to-one name="device" column="device_id" class="dvs.summit.devices.DeviceData"/>
      <many-to-one name="itemDefinition" column="itemDef_id" class="dvs.summit.data.ItemDefinition"/>
      <property name="itemIndex" column="itemIndex" type="integer"/>
      <subclass name="dvs.summit.data.items.Item" table="Item" discriminator-value="item">
         <property name="arrayIndex" column="arrayIndex" type="integer"/>
         <property name="valueId"  column="value_id"/>
         <many-to-one name="owningArray" column="arrayItem_id"/>
         <subclass name="dvs.summit.data.items.StringItem" discriminator-value="string"/>
         ...
         <subclass name="dvs.summit.data.items.AlarmItem" discriminator-value="alarm"/>
      </subclass>
      <subclass name="dvs.summit.data.items.ArrayItem" table="ArrayItem" discriminator-value="array">
         <list name="items" inverse="true" cascade="all">
            <key column="arrayItem_id"/>
            <index column="arrayIndex"/>
            <one-to-many class="dvs.summit.data.items.Item"/>
         </list>
         <subclass name="dvs.summit.data.items.StringArrayItem" discriminator-value="string-array"/>
         <subclass name="dvs.summit.data.items.AlarmArrayItem" discriminator-value="alarm-array"/>
      </subclass>
   </class>
</hibernate-mapping>

If I create a new instances of ArrayItem and its referenced Items the data in the database
looks something like this
Code:
id       type         device_id  itemIndex  arrayIndex  arrayItem_id
---------------------------------------------------------------------
3408050  alarm-array  524291     33         null        null
3408051  alarm        524291     33         0           3408050
3408052  alarm        524291     33         1           3408050
3408053  alarm        524291     33         2           3408050

If I update the array items the data in the database suddenly contains null values for
device_id and itemIndex:
Code:
id       type         device_id  itemIndex  arrayIndex  arrayItem_id
---------------------------------------------------------------------
3408050  alarm-array  524291     33         null        null
3408051  alarm        null       null       0           3408050
3408052  alarm        null       null       1           3408050
3408053  alarm        null       null       2           3408050

The reason is that hibernate is doing the following. It first updates the AlarmArrayItem correctly


update Item set device_id=?, itemDef_id=?, itemIndex=? where id=?
Updating entity: [dvs.summit.data.items.AlarmArrayItem#3408050]
Dehydrating entity: [dvs.summit.data.items.AlarmArrayItem#3408050]
binding '524291' to parameter: 1
id unsaved-value strategy NULL
binding '3375176' to parameter: 2
binding '33' to parameter: 3
binding '3408050' to parameter: 4


Then it updates the items collection by first (sort of) deleting the whole collection and then refill all items again.


Deleting collection: [dvs.summit.devices.DeviceData.items#524291]
update Item set device_id=null, itemIndex=null where device_id=?
binding '524290' to parameter: 1
done deleting collection
done closing: 0 open PreparedStatements, 0 open ResultSets
closing statement
Inserting collection: [dvs.summit.devices.DeviceData.items#524291]
about to open: 0 open PreparedStatements, 0 open ResultSets
update Item set device_id=?, itemIndex=? where id=?
preparing statement
binding '524291' to parameter: 1
id unsaved-value strategy NULL
binding '3407873' to parameter: 3
binding '0' to parameter: 2
...


The problem is that it now wiped out device_id and itemIndex for all items refrenced by an arrayItem!

How can I prvent Hibernate from doing the "Deleting collection: [dvs.summit.devices.DeviceData.items#524291]" thing?

I should be able to bypass this by persisting Items and ArrayItems in two seperate tables (table-per-concrete-class since joined-subclass does not allow the subclass element) but will then lose foreign key constraint capability.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Mar 15, 2004 7:09 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
You should show a simple code

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Code
PostPosted: Mon Mar 15, 2004 10:41 am 
Newbie

Joined: Thu Oct 09, 2003 4:30 am
Posts: 7
Here is a simple program that demonstrates the basics - I don't think this will realy help but perhaps it will give you a better picture.
Code:
    DeviceData device = null;
      try {
      // get a hibernate session from my static Persist class
         net.sf.hibernate.Session hSession = Persist.getSession();
         try {
        // get a device from the database
            List resultList = hSession.find("from device in class dvs.summit.devices.DeviceData where device.name='TUT'");
            if (resultList.size() > 0) {
               device = (DeviceData)resultList.get(0);
            }
            hSession.flush();
            hSession.connection().commit();
         }
         catch (Exception e) {
            System.out.println(e);
            hSession.connection().rollback();
         }
         finally {
            hSession.close();
         }
     
         if (device != null) {
        // Ok, we have a device now
        // get an array item from the device
            BaseItem item = device.getItem("SoftVer");
            // SoftVer is an array of two byte values
        // set the array values to 35 and 36
            item.setStringValue("35,36");
        // the values will be stored in another table - not part of the problem domain
            
            // save in another session
            hSession = Persist.getSession();
            try {
               hSession.saveOrUpdate(device); // cascade = "all"
               hSession.flush();
               hSession.connection().commit();
            }
            catch (Exception e) {
               System.out.println(e);
               hSession.connection().rollback();
            }
            finally {
               hSession.close();
            }
         }
      }

This is what happens. Both the device_id and itemIndex values is set correctly when updating the array elements
Code:
- update Item set arrayIndex=?, value_id=?, arrayItem_id=?, itemDef_id=?, device_id=?, itemIndex=? where id=?
- preparing statement
- Dehydrating entity: [dvs.summit.data.items.U8Item#6815751]
- binding '0' to parameter: 1
- binding '6881281' to parameter: 2
- binding '6815750' to parameter: 3
- id unsaved-value strategy NULL
- binding '6848518' to parameter: 4
- binding '5275650' to parameter: 5
- binding '5' to parameter: 6
- binding '6815751' to parameter: 7
- Updating entity: [dvs.summit.data.items.U8Item#6815752]
- Dehydrating entity: [dvs.summit.data.items.U8Item#6815752]
- binding '1' to parameter: 1
- binding '6881282' to parameter: 2
- binding '6815750' to parameter: 3
- id unsaved-value strategy NULL
- binding '6848518' to parameter: 4
- binding '5275650' to parameter: 5
- binding '5' to parameter: 6
- binding '6815752' to parameter: 7

but then hibernate set all device_id and itemIndex values to null before updating all items for the device
Code:
- update Item set device_id=null, itemIndex=null where device_id=?
- preparing statement
- binding '5275650' to parameter: 1
- done deleting collection
- done closing: 0 open PreparedStatements, 0 open ResultSets
- closing statement
- Inserting collection: [dvs.summit.devices.DeviceData.items#5275650]
- about to open: 0 open PreparedStatements, 0 open ResultSets
- update Item set device_id=?, itemIndex=? where id=?
- preparing statement
- binding '5275650' to parameter: 1
- binding '6815745' to parameter: 3
- binding '0' to parameter: 2
...

What hibernate does is correct if the ArrayItems were stored in another table, but in my case the two classes is persisted in the same table and by setting the device_id and itemIndex to null where device_id=? also sets these values to null for items referenced by the ArrayItem.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 05, 2004 9:34 am 
Beginner
Beginner

Joined: Mon Mar 22, 2004 10:01 am
Posts: 22
i experience something similar: a cascade=all collection mapped to a baseclass will always save baseclasses, even if i put sublcasses into the collection.

the problem is not with the deletion, but with hibernate saving the wrong class.

will go dig into the manual, but did you find any solution?

my only workaround is to explicitly save the entity before adding to the collection... and turn off cascade save/update :(


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.