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.  [ 3 posts ] 
Author Message
 Post subject: How to create 2 <map>'s to the same table
PostPosted: Thu Sep 14, 2006 5:26 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Hi all,
Can someone have a look at the mapping below and see if there anything wrong?

I have the following object model:
Device: base for any type of device
Terminal1, Terminal2: subclasses of Device
Manager: holds 2 maps - map1 for Terminal1s and map2 for Terminal2's, so it's a one-to-many relationship, and you have 2 sets of methods in Manager:
add/remove/getTerminal1(Terminal1 t...)
add/remove/getTerminal2(Terminal2 t...)

The Device hierarchy is all in the single DEVICE table with fields: ID, NAME, ADDRESS, MANAGER_ID
The Manager has its own MANAGER table with fields: ID

I populated the Manager's maps with some devices, and saved it to the DB. It all seems ok in the DBMS GUI. Then I tried to load it. For some reason, the first map I load (doesn't matter if it's map1 or map2) contains both Terminal1's and Terminal2's. The second map I load throws an exception (see below). Also, both access attempts to the maps generate the same SQL query!!! Shouldn't there be some use of the discriminator column in the WHERE clause???

Thanks....


Hibernate version:
3.1

Mapping documents:
Code:
<hibernate-mapping>
    <class name="Manager" table="MANAGER"
    discriminator-value="Manager">
   
        <id name="id" column="MANAGER_ID">
            <generator class="native"/>
        </id>

        <discriminator column="class" type="string"/>
       
        <map name="map1" cascade="all-delete-orphan" inverse="true" access="field">
            <key column="DEVICE_ID" not-null="true"/>
            <map-key formula="ADDRESS" type="string"/>
            <one-to-many class="Terminal1"/>
        </map>
        <map name="map2" cascade="all-delete-orphan" inverse="true" access="field">
            <key column="DEVICE_ID" not-null="true"/>
            <map-key formula="ADDRESS" type="string"/>
            <one-to-many class="Terminal2"/>
        </map>
    </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
session.beginTransaction();
Manager m = (Manager)session.createQuery("from Manager").list().get(0);
// print out the contents of the maps
System.out.println(m.map1);
System.out.println(m.map2);
session.getTransaction().commit();


Full stack trace of any exception that occurs:
org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: Terminal1 (loaded object was of wrong class)
at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:1235)
at org.hibernate.loader.Loader.getRow(Loader.java:1186)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:569)
at org.hibernate.loader.Loader.doQuery(Loader.java:689)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
at org.hibernate.loader.Loader.loadCollection(Loader.java:1919)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:520)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1676)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentMap.toString(PersistentMap.java:215)
at Manager.toString(Manager.java:29)

Name and version of the database you are using:
HSQL DB 1.8

The generated SQL (show_sql=true):
select map10_.MANAGER_ID as MANAGER3_1_, map10_.DEVICE_ID as DEVICE1_1_, map10_.address as formula4_1_, map10_.DEVICE_ID as DEVICE1_5_0_, map10_.MANAGER_ID as MANAGER3_5_0_, map10_.ADDRESS as ADDRESS5_0_, from DEVICE map10_ where map10_.MANAGER_ID=?
select map20_.MANAGER_ID as MANAGER3_1_, map20_.DEVICE_ID as DEVICE1_1_, map20_.address as formula4_1_, map20_.DEVICE_ID as DEVICE1_5_0_, map20_.MANAGER_ID as MANAGER3_5_0_, map20_.ADDRESS as ADDRESS5_0_, from DEVICE map20_ where map20_.MANAGER_ID=?

Debug level Hibernate log excerpt:
Loading of map1:
2006-09-14 12:12:16,006 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - initializing collection [Manager.map1#1]
2006-09-14 12:12:16,006 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - checking second-level cache
2006-09-14 12:12:16,006 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection not cached
2006-09-14 12:12:16,006 DEBUG org.hibernate.loader.Loader - loading collection: [Manager.map1#1]
2006-09-14 12:12:16,006 DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2006-09-14 12:12:16,006 DEBUG org.hibernate.SQL - select map10_.MANAGER_ID as MANAGER3_1_, map10_.DEVICE_ID as DEVICE1_1_, map10_.address as formula4_1_, map10_.DEVICE_ID as DEVICE1_5_0_, map10_.MANAGER_ID as MANAGER3_5_0_, map10_.ADDRESS as ADDRESS5_0_ from DEVICE map10_ where map10_.MANAGER_ID=?
Hibernate: select map10_.MANAGER_ID as MANAGER3_1_, map10_.DEVICE_ID as DEVICE1_1_, map10_.address as formula4_1_, map10_.DEVICE_ID as DEVICE1_5_0_, map10_.MANAGER_ID as MANAGER3_5_0_, map10_.ADDRESS as ADDRESS5_0_ from DEVICE map10_ where map10_.MANAGER_ID=?
2006-09-14 12:12:16,037 DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
2006-09-14 12:12:16,053 DEBUG org.hibernate.type.LongType - binding '1' to parameter: 1
2006-09-14 12:12:16,053 DEBUG org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
2006-09-14 12:12:16,053 DEBUG org.hibernate.loader.Loader - result set contains (possibly empty) collection: [Manager.map1#1]
2006-09-14 12:12:16,053 DEBUG org.hibernate.engine.CollectionLoadContext - uninitialized collection: initializing
2006-09-14 12:12:16,053 DEBUG org.hibernate.loader.Loader - processing result set
2006-09-14 12:12:16,053 DEBUG org.hibernate.loader.Loader - result set row: 0
2006-09-14 12:12:16,053 DEBUG org.hibernate.type.LongType - returning '1' as column: DEVICE1_5_0_
2006-09-14 12:12:16,053 DEBUG org.hibernate.loader.Loader - result row: EntityKey[Terminal2#1]
2006-09-14 12:12:16,053 DEBUG org.hibernate.loader.Loader - Initializing object from ResultSet: [Terminal2#1]
2006-09-14 12:12:16,053 DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [Terminal2#1]
2006-09-14 12:12:16,053 DEBUG org.hibernate.type.LongType - returning '1' as column: MANAGER3_5_0_
2006-09-14 12:12:16,053 DEBUG org.hibernate.type.StringType - returning '[email protected]' as column: ADDRESS5_0_
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.LongType - returning '1' as column: MANAGER3_1_
2006-09-14 12:12:16,069 DEBUG org.hibernate.loader.Loader - found row of collection: [Manager.map1#1]
2006-09-14 12:12:16,069 DEBUG org.hibernate.engine.CollectionLoadContext - reading row
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.LongType - returning '1' as column: DEVICE1_1_
2006-09-14 12:12:16,069 DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading entity: [Terminal2#1]
2006-09-14 12:12:16,069 DEBUG org.hibernate.event.def.DefaultLoadEventListener - attempting to resolve: [Terminal2#1]
2006-09-14 12:12:16,069 DEBUG org.hibernate.event.def.DefaultLoadEventListener - resolved object in session cache: [Terminal2#1]
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.StringType - returning '[email protected]' as column: formula4_1_
2006-09-14 12:12:16,069 DEBUG org.hibernate.loader.Loader - result set row: 1
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.LongType - returning '2' as column: DEVICE1_5_0_
2006-09-14 12:12:16,069 DEBUG org.hibernate.loader.Loader - result row: EntityKey[Terminal2#2]
2006-09-14 12:12:16,069 DEBUG org.hibernate.loader.Loader - Initializing object from ResultSet: [Terminal2#2]
2006-09-14 12:12:16,069 DEBUG org.hibernate.persister.entity.AbstractEntityPersister - Hydrating entity: [Terminal2#2]
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.LongType - returning '1' as column: MANAGER3_5_0_
2006-09-14 12:12:16,069 DEBUG org.hibernate.type.StringType - returning '[email protected]' as column: ADDRESS5_0_
2006-09-14 12:12:16,084 DEBUG org.hibernate.type.LongType - returning '1' as column: MANAGER3_1_
2006-09-14 12:12:16,084 DEBUG org.hibernate.loader.Loader - found row of collection: [Manager.map1#1]
2006-09-14 12:12:16,084 DEBUG org.hibernate.engine.CollectionLoadContext - reading row
2006-09-14 12:12:16,084 DEBUG org.hibernate.type.LongType - returning '2' as column: DEVICE1_1_
2006-09-14 12:12:16,084 DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading entity: [Terminal2#2]
2006-09-14 12:12:16,084 DEBUG org.hibernate.event.def.DefaultLoadEventListener - attempting to resolve: [Terminal2#2]
2006-09-14 12:12:16,084 DEBUG org.hibernate.event.def.DefaultLoadEventListener - resolved object in session cache: [Terminal2#2]
2006-09-14 12:12:16,084 DEBUG org.hibernate.type.StringType - returning '[email protected]' as column: formula4_1_
2006-09-14 12:12:16,084 DEBUG org.hibernate.loader.Loader - done processing result set (2 rows)
2006-09-14 12:12:16,084 DEBUG org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
2006-09-14 12:12:16,084 DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2006-09-14 12:12:16,084 DEBUG org.hibernate.jdbc.AbstractBatcher - closing statement
2006-09-14 12:12:16,084 DEBUG org.hibernate.loader.Loader - total objects hydrated: 2
Notice how both devices were loaded into the first collection:
2006-09-14 12:12:16,084 DEBUG org.hibernate.engine.TwoPhaseLoad - resolving associations for [Terminal2#1]
2006-09-14 12:12:16,100 DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading entity: [Manager#1]
2006-09-14 12:12:16,100 DEBUG org.hibernate.event.def.DefaultLoadEventListener - entity found in session cache
2006-09-14 12:12:16,194 DEBUG org.hibernate.engine.TwoPhaseLoad - done materializing entity [Terminal2#1]
2006-09-14 12:12:16,194 DEBUG org.hibernate.engine.TwoPhaseLoad - resolving associations for [Terminal2#2]
2006-09-14 12:12:16,194 DEBUG org.hibernate.event.def.DefaultLoadEventListener - loading entity: [Manager#1]
2006-09-14 12:12:16,194 DEBUG org.hibernate.event.def.DefaultLoadEventListener - entity found in session cache
2006-09-14 12:12:16,209 DEBUG org.hibernate.engine.TwoPhaseLoad - done materializing entity [Terminal2#2]
2006-09-14 12:12:16,209 DEBUG org.hibernate.engine.CollectionLoadContext - 1 collections were found in result set for role: Manager.map1
2006-09-14 12:12:16,209 DEBUG org.hibernate.engine.CollectionLoadContext - collection fully initialized: [Manager.map1#1]
2006-09-14 12:12:16,209 DEBUG org.hibernate.engine.CollectionLoadContext - 1 collections initialized for role: Manager.map1
2006-09-14 12:12:16,209 DEBUG org.hibernate.engine.StatefulPersistenceContext - initializing non-lazy collections
2006-09-14 12:12:16,209 DEBUG org.hibernate.loader.Loader - done loading collection
2006-09-14 12:12:16,209 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection initialized
Loading of map2:
2006-09-14 12:12:23,350 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - initializing collection [Manager.map2#1]
2006-09-14 12:12:23,350 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - checking second-level cache
2006-09-14 12:12:23,350 DEBUG org.hibernate.event.def.DefaultInitializeCollectionEventListener - collection not cached
2006-09-14 12:12:23,350 DEBUG org.hibernate.loader.Loader - loading collection: [Manager.map2#1]
2006-09-14 12:12:23,350 DEBUG org.hibernate.jdbc.AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2006-09-14 12:12:23,350 DEBUG org.hibernate.SQL - select map20_.MANAGER_ID as MANAGER3_1_, map20_.DEVICE_ID as DEVICE1_1_, map20_.address as formula3_1_, map20_.DEVICE_ID as DEVICE1_5_0_, map20_.MANAGER_ID as MANAGER3_5_0_, map20_.ADDRESS as ADDRESS5_0_ from DEVICE map20_ where map20_.MANAGER_ID=?
Hibernate: select map20_.MANAGER_ID as MANAGER3_1_, map20_.DEVICE_ID as DEVICE1_1_, map20_.address as formula3_1_, map20_.DEVICE_ID as DEVICE1_5_0_, map20_.MANAGER_ID as MANAGER3_5_0_, map20_.ADDRESS as ADDRESS5_0_ from DEVICE map20_ where map20_.MANAGER_ID=?
2006-09-14 12:12:23,365 DEBUG org.hibernate.jdbc.AbstractBatcher - preparing statement
2006-09-14 12:12:23,365 DEBUG org.hibernate.type.LongType - binding '1' to parameter: 1
2006-09-14 12:12:23,365 DEBUG org.hibernate.jdbc.AbstractBatcher - about to open ResultSet (open ResultSets: 0, globally: 0)
2006-09-14 12:12:23,365 DEBUG org.hibernate.loader.Loader - result set contains (possibly empty) collection: [Manager.map2#1]
2006-09-14 12:12:23,365 DEBUG org.hibernate.engine.CollectionLoadContext - uninitialized collection: initializing
2006-09-14 12:12:23,365 DEBUG org.hibernate.loader.Loader - processing result set
2006-09-14 12:12:23,381 DEBUG org.hibernate.loader.Loader - result set row: 0
2006-09-14 12:12:23,381 DEBUG org.hibernate.type.LongType - returning '1' as column: DEVICE1_5_0_
2006-09-14 12:12:23,381 DEBUG org.hibernate.loader.Loader - result row: EntityKey[Terminal1#1]
2006-09-14 12:12:23,381 DEBUG org.hibernate.jdbc.AbstractBatcher - about to close ResultSet (open ResultSets: 1, globally: 1)
2006-09-14 12:12:23,381 DEBUG org.hibernate.jdbc.AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2006-09-14 12:12:23,381 DEBUG org.hibernate.jdbc.AbstractBatcher - closing statement


Top
 Profile  
 
 Post subject: Wrong class
PostPosted: Thu Sep 14, 2006 8:52 am 
Newbie

Joined: Wed Jun 28, 2006 5:29 pm
Posts: 8
There is already a bug repport on this issue
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1846
You should try to get over it by using the where clause in your map tag if you have a discriminator on your devices.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Sep 14, 2006 9:21 am 
Senior
Senior

Joined: Sun Jun 11, 2006 10:41 am
Posts: 164
Yes, that's what I currently did as a workaround, however it's not a polymorphic approach so I can't have a map of objects DERIVED from Terminal1 or DERIVED from Terminal2. Another workaround is to create separate tables for Terminal1 and Terminal2.

Anyway, thanks for the notice.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 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.