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.  [ 25 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: null foreign key values when using inhertance
PostPosted: Mon Oct 02, 2006 1:04 pm 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Does anyone outt here have any experiance of implementing inheritance using the Table Per Subclass approach? If so i'd really appreciate some help with the following problem. I'm sure its something simple....but I can't get it to work and i've been at it for ages!

I have the following model (Sorry I can't draw it, don't know how to insert drawings here)

Company has many Communications.
Comunications is an abstract class, from which the class Meetings inherits.

The problem i'm having is that when I create a new Meeting for an existing Company my meetings table is populated with the foreign key to the communications table however the communications table has a null value in its FK column to the company table. Any help would be greatly appreciated....

Mapping File
========
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="sampleApp.Communication, sampleApp" table="rme_communications">
<id name="Id" column="comm_id" unsaved-value="" type="int">
<generator class="assigned" />
</id>
<property name="Title" column="comm_title"/>
<property name="Date" column="comm_date" type="date"/>
<joined-subclass name="sampleApp.Meeting, sampleApp" table="rme_meetings">
<key column="mtn_com_id"></key>
<property
name="Location" column="mtn_location"/>
<property
name="Type" column="mtn_type"/>
<property
name="Rating" column="mtn_rtng"/>
</joined-subclass>
<joined-subclass name="sampleApp.Report, sampleApp" table="rme_reports">
<key column="rpt_com_id"></key>
<property
name="Type" column="rpt_type"/>
</joined-subclass>
</class>
<class name="sampleApp.Instrument, sampleApp" table="rme_instruments">
<id name="Code" column="inst_code" unsaved-value="" type="String" length="100">
<generator class="assigned" />
</id>
<property name="Sedol" column="inst_sedol"/>
<property name="Description" column="inst_desc"/>
<property name="DateFirstHeld" column="inst_first_held"/>
<property name="DateLastHeld" column="inst_last_held" />
</class>
<class name="sampleApp.Company, sampleApp" table="rme_companies">
<id name="Id" column="coy_code" unsaved-value="" type="int" >
<generator class="assigned" />
</id>
<property name="Name" column="coy_name"/>
<property name="Address" column="coy_address"/>
<bag name="Instruments">
<key column="inst_coy_code" />
<one-to-many
class="sampleApp.Instrument, sampleApp" />
</bag>
<bag name="Communications" lazy="true" cascade="save-update" inverse="true">
<key column="comm_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>
<!--<map name="instruments">
<key column="inst_coy_code"/>
<index column="inst_code" type="String" length ="100"/>
<one-to-many class="sampleApp.Instrument, sampleApp" />
</map>-->
</class>
</hibernate-mapping>

Company Class
===========
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace sampleApp
{
public class Company
{
private int _id;

public virtual int Id
{
get { return _id; }
set { _id = value; }
}

private string _name;

public virtual string Name
{
get { return _name; }
set { _name = value; }
}

private string _address;

public virtual string Address
{
get { return _address; }
set { _address = value; }
}

private IList _instruments;

public virtual IList Instruments
{
get { return _instruments; }
set { _instruments = value; }
}

private IList _communications;

public virtual IList Communications
{
get { return _communications; }
set { _communications = value; }
}
public Company()
{
Instruments = new ArrayList();
Communications = new ArrayList();
}

public Company(IList p_communications, IList p_instruments)
{
Instruments = p_instruments;
Communications = p_communications;
}

public Company(int p_id, string p_name, string p_address, IList p_instruments)
{
Id = p_id;
Name = p_name;
Address = p_address;
Instruments = p_instruments;
}

}
}

Communication Class
==============
using System;
using System.Collections.Generic;
using System.Text;

namespace sampleApp
{
public abstract class Communication
{
private int _id;

public virtual int Id
{
get { return _id; }
set { _id = value; }
}

private string _title;

public virtual string Title
{
get { return _title; }
set { _title = value; }
}

private DateTime _date;

public virtual DateTime Date
{
get { return _date; }
set { _date = value; }
}

}
}

Meetings Class
==========
using System;
using System.Collections.Generic;
using System.Text;

namespace sampleApp
{
public class Meeting : Communication
{
private string _location;

public virtual string Location
{
get { return _location; }
set { _location = value; }
}

private string _type;

public virtual string Type
{
get { return _type; }
set { _type = value; }
}

private string _rating;

public virtual string Rating
{
get { return _rating; }
set { _rating = value; }
}

public Meeting()
{
}
public Meeting(int p_id, string p_title, DateTime p_date, String p_location)
{
Id = p_id;
Title = p_title;
Date = p_date;
Location = p_location;
}
}
}


Top
 Profile  
 
 Post subject: Re: null foreign key values when using inhertance
PostPosted: Mon Oct 02, 2006 2:08 pm 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
<bag name="Communications" lazy="true" cascade="save-update" inverse="true">


inverse relation implies that the association is bi-directional. It basically tells that the peropty is read-only and all updates are done trougth the other association end.

See http://www.hibernate.org/hib_docs/nhibernate/html/collections.html#collections-bidirectional

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 4:53 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Hi unfortuately this didn't work, any other ideas? Do you know of any simple examples of this sort of thing that I can copy.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 6:48 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
Hi unfortuately this didn't work, any other ideas? Do you know of any simple examples of this sort of thing that I can copy.

What didn't work?

Other solution: Remove the "inverse="true"" from relation. You will have a separate table for storing relation data.

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 7:06 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Removing the "inverse=true" didn't work. I also tried "inverse=false" which didn't work. I'm wondering if I might have something basic wrong. In my xml file I have a one-to-many clause from Company to Communication but I do not have a many-to-one clause from Communication to Company. I leave out the many-to-one as this works fine for the same sort of relationships elsewhere. Have you any advice? By the way my relational model is:

company-<communications-<meetings

I think you might be thiking I have an association table like:

company-<company_communications>-communications-<meetings

Thanks....


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 7:34 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
Removing the "inverse=true" didn't work. I also tried "inverse=false" which didn't work. I'm wondering if I might have something basic wrong. In my xml file I have a one-to-many clause from Company to Communication but I do not have a many-to-one clause from Communication to Company. I leave out the many-to-one as this works fine for the same sort of relationships elsewhere. Have you any advice? By the way my relational model is:

company-<communications-<meetings

I think you might be thiking I have an association table like:

company-<company_communications>-communications-<meetings


AFAIK, if You do not use inverse="true", You will need the association table.

If You use inverse="true", You must have a many-to-one from Communication to Company. And, saving "Communication" changes the elements of the Company.Communications collection. Saving Company has no effect on the collection.

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 8:37 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
So how do you describe an assoication table in the mapping file? In my mapping file I tell class Company that its data comes from the company table and I tell class Communication that its data comes from the communication table and I say a Company has many Communications like this:

<bag name="Communications" lazy="true" cascade="save-update" >
<key column="comm_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>

which implies (as far as I know) that there is a foreign key from the communications table column comm_coy_code to the company table's primary key. How would I do this with an association table? Thanks.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 10:06 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
So how do you describe an assoication table in the mapping file? In my mapping file I tell class Company that its data comes from the company table and I tell class Communication that its data comes from the communication table and I say a Company has many Communications like this:

<bag name="Communications" lazy="true" cascade="save-update" >
<key column="comm_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>

which implies (as far as I know) that there is a foreign key from the communications table column comm_coy_code to the company table's primary key. How would I do this with an association table?


<bag name="Communications" lazy="true" cascade="save-update" table="Company_Comm_Assoc">
<key column="comm_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 11:45 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
When I do this I don't seem to be populating a Companies Communications collection. I've got the following in my xml file:

<bag name="Communications" lazy="true" cascade="save-update" table="rme_company_communications">
<key column="cc_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>

cc_coy_code is the foreign key from rme_company_communications to the primary key on companies table. Does it matter that I don't have a property in my Communication class that identifies the Company that it belongs to? I presum I only need to do this I want to model many-to-one from Communivation to Company and I don't have to do this if I use an association table? Thanks for your on going help - very much appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 03, 2006 1:18 pm 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
So how do you describe an assoication table in the mapping file? In my mapping file I tell class Company that its data comes from the company table and I tell class Communication that its data comes from the communication table and I say a Company has many Communications like this:

<bag name="Communications" lazy="true" cascade="save-update" >
<key column="comm_coy_code" />
<one-to-many
class="sampleApp.Communication, sampleApp" />
</bag>

which implies (as far as I know) that there is a foreign key from the communications table column comm_coy_code to the company table's primary key. How would I do this with an association table? Thanks.


I must step back here. This mapping should work just fine, and association table should not be needed (according to docs). (I have never used non-inverse one-to-many relations :()

So I must ask my first question again: what did not work? Any errors generated? Data not saved? Data not retrived?

BTW, did You notice:
Quote:
Very Important Note: If the <key> column of a <one-to-many> association is declared NOT NULL, NHibernate may cause constraint violations when it creates or updates the association. To prevent this problem, you must use a bidirectional association with the many valued end (the set or bag) marked as inverse="true". See the discussion of bidirectional associations later in this chapter.


Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 4:45 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Sorry if i'm being confusing......Ultimately the problem i'm having is that when I create a new Meeting for an existing Company my meetings table is populated with the foreign key to the communications table so the 'is a' relation exists between sub class and super class, however the communications table has a null value in its FK column to the company table.

I would like to use the table per subclass approach to inplmement inheritacnce which is why I have a communication table for the abstract Communication class and a meetings table for the Meetings class that inherits from Communication. However in depseration i've tried using the 'table per class hierarchy' approach so that all data goes into the Communications table and I have a descriminator column but even with this approach I get the same problem - a null value in the FK column to the Company table...any ideas? Thanks again for your ongoing help.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 5:04 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
Sorry if i'm being confusing......Ultimately the problem i'm having is that when I create a new Meeting for an existing Company my meetings table is populated with the foreign key to the communications table so the 'is a' relation exists between sub class and super class, however the communications table has a null value in its FK column to the company table.


So, the sequence like
Code:
Company comp = new Company();
session.Save(comp);

Meeting met = new Meeting();
session.Save(met);

com.Communications.Add(met);

session.Flush();


has following results:
1. It executes successfully.
2. the Communcations table has NULL in the foreign key column to Company table.

Or not?

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 6:20 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
Not exactly... I should point out that i'm new to OO and .NET (i'm an oracle developer). My exact code is listed below what i'm trying to achieve is :
- Get a list of Companies from the database
- add a new meeting to Company with Id 1.
- Save all this back to the database

I think the code below should do this, but it doesn't it does what you say :

1. It executes successfully.
2. the Communcations table has NULL in the foreign key column to Company table.

Code
===

NHibernate.ICriteria compCriteria = session.CreateCriteria(typeof(Company));

foreach (Company c in compCriteria.List())
{
if (c.Id == 1)
{
newMeeting = new Meeting(4, "com 4", aDate, "com 4");
c.Communications.Add(newMeeting);
transaction = session.BeginTransaction();
if (c.Communications.Count != 0)
{
//save each instruments changed/new communications
foreach (Communication Cm in c.Communications)
{
session.Save(Cm);
}
}
session.Save(c);
transaction.Commit();
}
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 6:55 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
roye wrote:
Not exactly... I should point out that i'm new to OO and .NET (i'm an oracle developer). My exact code is listed below what i'm trying to achieve is :
- Get a list of Companies from the database
- add a new meeting to Company with Id 1.
- Save all this back to the database

I think the code below should do this, but it doesn't it does what you say :

1. It executes successfully.
2. the Communcations table has NULL in the foreign key column to Company table.

Code
===

NHibernate.ICriteria compCriteria = session.CreateCriteria(typeof(Company));

foreach (Company c in compCriteria.List())
{
if (c.Id == 1)
{
newMeeting = new Meeting(4, "com 4", aDate, "com 4");
c.Communications.Add(newMeeting);
transaction = session.BeginTransaction();
if (c.Communications.Count != 0)
{
//save each instruments changed/new communications
foreach (Communication Cm in c.Communications)
{
session.Save(Cm);
}
}
session.Save(c);
transaction.Commit();
}
}


First of all: the session.Save(); means "INSERT" in SQL language (Save new instance). session.Update would save modified instance, but it is not needed if object is read trought the same session.

The only thing I do not understand - the database should have thrown Primary Key Violation in case of that code :O

EDIT: To get specific object from database, use session.Get(typeof(Company), 1);
or
session.Get<Company>(1);

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 04, 2006 7:30 am 
Beginner
Beginner

Joined: Wed Jul 26, 2006 11:52 am
Posts: 23
Location: Edinburgh, Scotland
I don' think you were suggesting that session.update would solve the problem but I changed the code anyway to see it it did, so I know have :

"session.Update(c)"; instead of "session.Save(c);"

I still get the same problem. So you have any ideas what's going on? I've added a many-to-one clause in the mapping file from Communication to Company and put back the inverse="true" into the one-to-many relation between Company and Communication but i'm still getting the same problem. Would it have anything to do with how I've configured Id generation. I'm using <generator class="assigned" /> but i'm not sure it that's correct?? I suppose what i'm doing is trying to implement polymorphic bi-directional associations to collections which I wold have thought is pretty common. Do you know of documented worked examples?


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