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.  [ 16 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Hibernate mapping (table per subclass) problem
PostPosted: Tue Feb 07, 2006 5:58 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
<hibernate-mapping>
<class name="Header" table="MENU_HEADER_DEFINITION">
<composite-id
name="DefKey"
class="BaseOID"
unsaved-value="none">
<key-property name="ID" type="int" >
<column name="MENU_HEADER_DEFINITION_ID" sql-type="int" not-null="true" />
</key-property>
<key-property name="OrigID" type="int" >
<column name="MENU_HEADER_DEFINITION_ORIG_ID" sql-type="int" not-null="true" />
</key-property>
</composite-id>
<version
column="INSTANCE_VERSION_NUMBER"
name="instanceVersionNumber"
/>
<property name="labelIdentifier">
<column name="MENU_LABEL_MESSAGE_IDENTIFIER" sql-type="string" not-null="true" />
</property>
<property name="DisplaySeqNum">
<column name="DISPLAY_ORDER_SEQUENCE_NUMBER" sql-type="int" not-null="true" />
</property>
<property name="ExpandsByDefault">
<column name="EXPANDS_BY_DEFAULT_FLAG" sql-type="string" not-null="true" />
</property>
<property name="lastModifiedTS">
<column name="LAST_MODIFIED_TS" sql-type="date" not-null="true" />
</property>

<joined-subclass name="AssignedHeader"table="CONNECT_OWNER.MENU_HEADER_ASSIGNMENT">
<key>
<column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
<column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true"/>
</key>

<component name="AssignmentKey" class="BaseOID">
<property name="ID" type="int" >
<column name="MENU_HEADER_ASSIGNMENT_ID" sql-type="int" not-null="true" />
</property>
<property name="OrigID" type="int">
<column name="MENU_HEADER_ASSIGNMENT_ORIG_ID" sql-type="int" not-null="true" />
</property>
</component>
<property name="clientOrgUnitId" >
<column name="CLIENT_ORG_UNIT_ASGN_ID" sql-type="int" not-null="true" />
</property>
<property name="clientOrgUnitOrigId" >
<column name="CLIENT_ORG_UNIT_ASGN_ORIG_ID" sql-type="int" not-null="true" />
</property>
<property name="displaySeqNum" >
<column name="DISPLAY_ORDER_SEQUENCE_NUMBER" sql-type="int" not-null="false" />
</property>
<property name="displayForAllSubunits" >
<column name="DISPLAY_FOR_ALL_SUB_UNITS_FLAG" sql-type="string" not-null="true" />
</property>
<property name="lastModifiedTS" >
<column name="LAST_MODIFIED_TS" sql-type="date" not-null="true" />
</property>
<property name="defaultLocale">
<column name="DEFAULT_LOCALE_CODE" sql-type="string" not-null="false"/>
</property>

</joined-subclass>
</class>

</hibernate-mapping>


Header(super class) and Assigned Header(subclass) have two colums(MENU_HEADER_DEFINITION_ID and MENU_HEADER_DEFINITION_ORIG_ID) in common which is a key to join both classes.

Question 1:-
Is using component tag to refer to subclass table composite key from subclass right ?.
IT's working though


Question 2:- My biggest problem is to query only super class(Header).When i query super class , i am getting sub class objects.
When i am querying subclass, i am getting both super and sub class objects(which is supposed to and this is working fine).How to get only super objects when i query only super class, how can i do it using hibernate mapping.I dont' have descriminator value to use <subclass fetch="select"> which can do the job. when i Query only super class, i need to have only the objects from super class table not from subclass.

Can u some one help me?Thanks in advance


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 6:22 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Answer 1: Yes, but that's not giving you a bi-directoinal relationship. If you don't want one, then what you've got is good.

Answer 2: If you want to find Headers that aren't joined to AssignedHeaders, you'll have to do that in your own code (load all Headers, drop results that implement AssignedHeader). It can be done using subclass instead of joined-subclass; in HQL there's a special .class member which provides access to the discriminator. There is no discriminator for joined-subclass though.


Top
 Profile  
 
 Post subject: mapping help
PostPosted: Tue Feb 07, 2006 6:43 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
i have only 5 entries in Definition table . So if I query like

Map criteria = new HashMap();

printCollection(HibernateUtil.find(criteria,Header.class));

I am not getting the header object, i am getting AssignedHeader Object instead.I don't want AssignedHeader if i am querying for super class.
I just need only super class object.Is it possible from <joined-sublcass>.I don't have descriminators defined in tables. For <subclass> Can i use Descriminators even if i don't have them in tables?.




HibernateUtil{
public static Collection find(Map criteria,Class persistent){
Collection items;
Criteria sessionCriteria= HibernateUtil.getSession().createCriteria(persistent);
sessionCriteria.add(Expression.allEq(criteria));
items=sessionCriteria.list();
return items;
}

}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 7:11 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
No, you can't use discriminators unless they're "real".

Is there anything wrong with getting AssignedHeaders when querying for Headers? This is how polymorphism works, and if Hibernate did it any other way, people would complain so much that <insert reference to Danish cartoons here> would look like a minor quibble. Headers that are AssignedHeaders will never be returned as just Headers: that would be very un-object-oriented. They can, however, be downcast to Headers. And Headers that are not AssignedHeaders will still be returned as Headers.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 8:10 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
tenwit wrote:
No, you can't use discriminators unless they're "real".

Is there anything wrong with getting AssignedHeaders when querying for Headers? This is how polymorphism works, and if Hibernate did it any other way, people would complain so much that <insert reference to Danish cartoons here> would look like a minor quibble. Headers that are AssignedHeaders will never be returned as just Headers: that would be very un-object-oriented. They can, however, be downcast to Headers. And Headers that are not AssignedHeaders will still be returned as Headers.


Menu header def table stores generic menu headers definitions(they are not assigned to any client)

Menuheader asignemnts table stores the assignments when a assignment is made to a client.

The problem is like this , if a client is assigned a menu header then it would go to menu header assignment table(AssignedHeader class) .If a new client comes in, there will be no headers assigned in assignments table , so we want all headers from menu headers definition table in that case.In this scenario i want to go to menu headers def table(Header) to get all the headers since there are no headers found for new client.So i want only super class objects.it is still returning all the clients assignments(which i don't want)even though i do criteria on header object.Any idea?.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 8:58 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Either:
move the client references into the base Header class, and query "where <clientref> is null"; or
abandon polymorphism, and instead give a client a collection of AssignedHeaders and a collection of GlobalHeaders.

This doesn't sound like a case for polymorphism: there is no "kind-of" relationship. To my way of thinking, an AssignedHeader isn't a kind-of Header: it is an Header, that just happens to have an association with a client. But I don't have all the requirements, so maybe your solution is better. In that case, you'll need to put a discriminator in the Header table so that hibernate can figure out which Headers are not AssignedHeaders.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 9:42 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
tenwit wrote:
Either:
move the client references into the base Header class, and query "where <clientref> is null"; or
abandon polymorphism, and instead give a client a collection of AssignedHeaders and a collection of GlobalHeaders.

This doesn't sound like a case for polymorphism: there is no "kind-of" relationship. To my way of thinking, an AssignedHeader isn't a kind-of Header: it is an Header, that just happens to have an association with a client. But I don't have all the requirements, so maybe your solution is better. In that case, you'll need to put a discriminator in the Header table so that hibernate can figure out which Headers are not AssignedHeaders.

Thanks for your answers, but i am still stuck.

I ran the query, it is still pointing to subclass.If there are no assignments it is giving me null.
Actually there is a relationship between Menu header assignment table and menu header definition table.It is many to one relationship.
Each menu header corresponds to many assignments(clients).Client references comes from different table.There will be no entrees for new client in assignments table . If it is a new client , the client references from client tables and associated with all the headers(from definitions table) in the assignment table.In this scenarion if a client is new client
i should only go to definitions table and get the definitions. i should n't go to assignments table since there will be no rows there.[/url]


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 10:05 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Well, there's no way around it: querying for all Headers will give you all matching Headers, no matter what class. You'll have to redesign something. I suggest putting links from clients to both Headers and AssignedHeaders. You don't have to do this in the schema, it sounds like you have all the necessary columns already. You just have to add some bidirectional mappings.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 10:36 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
tenwit wrote:
Well, there's no way around it: querying for all Headers will give you all matching Headers, no matter what class. You'll have to redesign something. I suggest putting links from clients to both Headers and AssignedHeaders. You don't have to do this in the schema, it sounds like you have all the necessary columns already. You just have to add some bidirectional mappings.


Can show me how to add bi-directional mapping from super to sub class and subclass to super for my mapping .At least an example will do.
Do i have to define many to one relationship from the subclass?. i did that
and it did not make a difference.Can please correct my mapping?.

<hibernate-mapping>
<class name="Header" table="MENU_HEADER_DEFINITION">
<composite-id
name="DefKey"
class="BaseOID"
unsaved-value="none">
<key-property name="ID" type="int" >
<column name="MENU_HEADER_DEFINITION_ID" sql-type="int" not-null="true" />
</key-property>
<key-property name="OrigID" type="int" >
<column name="MENU_HEADER_DEFINITION_ORIG_ID" sql-type="int" not-null="true" />
</key-property>
</composite-id>
<version
column="INSTANCE_VERSION_NUMBER"
name="instanceVersionNumber"
/>
<property name="labelIdentifier">
<column name="MENU_LABEL_MESSAGE_IDENTIFIER" sql-type="string" not-null="true" />
</property>
<property name="DisplaySeqNum">
<column name="DISPLAY_ORDER_SEQUENCE_NUMBER" sql-type="int" not-null="true" />
</property>
<property name="ExpandsByDefault">
<column name="EXPANDS_BY_DEFAULT_FLAG" sql-type="string" not-null="true" />
</property>
<property name="lastModifiedTS">
<column name="LAST_MODIFIED_TS" sql-type="date" not-null="true" />
</property>

<joined-subclass name="AssignedHeader"table="CONNECT_OWNER.MENU_HEADER_ASSIGNMENT">
<key>
<column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
<column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true"/>
</key>
....
...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 11:25 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
My bidirectional relationship suggestion wasn't to relate Headers and AssignedHeaders. My point is that you should not have two classes for this: you should just have one, Headers. Then add a bidirectional many-to-many mapping between clients and headers: I'm assuming that the MENU_HEADER_ASSIGNMENT table is a join table containing nothing more than columns describing foreign keys to MENU_HEADER_DEFINITION and whatever your client table is.

To implement this, have a look in the ref docs, section 7.5, "Bidirectional associations with join tables". Here's the example from section 7.5.3, roughly converted for your schema:
Code:
<class name="Client">
  ...

  <set name="Headers" table="MENU_HEADER_ASSIGNMENT">
    <key>
      (your client id here)
    </key>
    <many-to-many class="Header">
      <column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
      <column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true"/>
    </many-to-many>
  </set>

  <set name="UnassignedHeaders" table="MENU_HEADER_ASSIGNMENT">
    <key formula="null"/> <!-- This will have to be composite if client ids are composite -->
    <many-to-many class="Header">
      <column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
      <column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true"/>
    </many-to-many>
  </set>
</class>

<class name="Header">
  ...
  <set name="Clients" inverse="true" table="MENU_HEADER_ASSIGNMENT">
    <key>
      <column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
      <column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true" />
    </key>

    <many-to-many class="Client">
      (your client id here)
    </many-to-many>
  </set>
</class>
Note that I have put the unassigned headers inside the client mapping. I don't believe that this is the correct solution: you should have global headers available from some factory. However, this should work, and you can refactor at your leisure.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 12:48 am 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
Thanks for your answers...

Thanks, but i have a question on this.Since Header will have only definitions in your mapping , how can i include assignments properties from assignments if any?.What i meant is how to include properties in <class> below for assigned headers from assignments table.
Can i map properties in one class to 2 different tables.

<class name="Header">
...
<set name="Clients" inverse="true" table="MENU_HEADER_ASSIGNMENT">
<key>
<column name="MENU_HEADER_DEFINITION_ID" not-null="true" />
<column name="MENU_HEADER_DEFINITION_ORIG_ID" not-null="true" />
</key>

<many-to-many class="Client">
(your client id here)
</many-to-many>
</set>
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 12:56 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Use the <join> element instead of the <joined-subclass> element. It's described in ref docs, section 5.1.18. I think the tag line there sums it up for you: "Using the <join> element, it is possible to map properties of one class to several tables.".


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 1:07 am 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
tenwit wrote:
Use the <join> element instead of the <joined-subclass> element. It's described in ref docs, section 5.1.18. I think the tag line there sums it up for you: "Using the <join> element, it is possible to map properties of one class to several tables.".



Thanks

Each table has it's own composite keys Defition has
MENU_HEADER_DEFINITION_ID
and MENU_HEADER_DEFINITION_ORIG_ID
and ASsignment has it's own composite keys mapped to it's table.If i go by Header , i should have total 2 differnt keys from 2 tables. Is that possible if i map one class having 2 sets of keys from 2 tables with out subclassing in join ?.

The relationship is only between client table and assignements table, assignments table and definition table


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 1:19 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Just map the definition table in the normal way, with its composite key. Then join to its assignments, in the normal way, with a two-column key.

I still believe that you should have separate classes for Assignments and Headers. You've described a classic "many-to-many with join table" scenario: the only weirdness is that you have a special kind of Header, one with no assignments. No amount of hibernate jiggery-pokery is going to help you fix a poor design, and neither are the ref docs.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 08, 2006 6:16 pm 
Newbie

Joined: Tue Feb 07, 2006 3:32 pm
Posts: 8
tenwit wrote:
Just map the definition table in the normal way, with its composite key. Then join to its assignments, in the normal way, with a two-column key.

I still believe that you should have separate classes for Assignments and Headers. You've described a classic "many-to-many with join table" scenario: the only weirdness is that you have a special kind of Header, one with no assignments. No amount of hibernate jiggery-pokery is going to help you fix a poor design, and neither are the ref docs.


Thanks,

I used another strategy to do that.I have the Definition class mapping to the table once and have the same class mapping to the same table with subclass mapped to it's table. I could able to solve this way.I used entity names to differentiate between class names.

There is a small problem with my earlier mapping with subclassing ,probably you can help me with this..I was trying to save menuheader assignment and but it is also saving definition to definition table which i don't want.I just want to save only subclass , how can do i that.I tried setting properties to insert and update =false for super class,but the query is looking at composite keys of super class MENU_HEADER_DEFINITION_ID and MENU_HEADER_DEFINITION_ORIG_ID which should n't happen while updating or inserting for subclass table.Hibernate generated Query looks like this ...

update CONNECT_OWNER.MENU_HEADER_ASSIGNMENT set CLIENT_ORG_UNIT_ASGN_ID=?, CLIENT_ORG_UNIT_ASGN_ORIG_ID=?, DISPLAY_ORDER_SEQUENCE_NUMBER=?, DISPLAY_FOR_ALL_SUB_UNITS_FLAG=?, LAST_MODIFIED_TS=?, DEFAULT_LOCALE_CODE=? where MENU_HEADER_DEFINITION_ID=? and MENU_HEADER_DEFINITION_ORIG_ID=?

Error is org.hibernate.HibernateException: Duplicate identifier in table for: [HeaderAssignment#component[ID,OrigID]{OrigID=15, ID=1}]


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 16 posts ]  Go to page 1, 2  Next

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.