-->
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.  [ 6 posts ] 
Author Message
 Post subject: One-to-one mapping
PostPosted: Tue Mar 07, 2006 4:17 pm 
Beginner
Beginner

Joined: Tue May 17, 2005 2:48 pm
Posts: 47
Hi,

I have a problem with a one-to-one mapping. I have 3 classes: Customer, Person and Address. I also have 3 tables for those classes in the database, also 3 separate mapping files. Person is a subclass of Customer. When I save an instance of Person, I get the error that the column Address_id is null. This column has a foreign key to the Address table. The instance of Address is created in the constructor of Person. Therefore, the instance of Address should first be saved, then the instance of Person can be saved.
Is my mapping wrong? I don't want a relation from Address to Person, only from Person to Address, because the Address-class is also used in other classes, Employee for example.

The application is built in ASP.NET 2.0. I have a separate class library Domain for the domain classes and the hbm.xml files.

Hibernate version: NHibernate 1.1

Mapping documents:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyApp.Domain">
   <class name="Customer" table="Customer">

      <cache usage="read-write" />

      <id name="Id" type="Int32" column="id" unsaved-value="0">
         <generator class="identity"/>
      </id>

      <property name="CustNr" column="CustNr" type="String" length="10" />
   </class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyApp.Domain">
   <joined-subclass name="Person" table="Person" extends="Customer">
      <key column="id" />
      <one-to-one name="Address" class="Address" constrained="true" cascade="all"/>
      <property name="FirstName" column="FirstName" type="String" length="50"/>
                <property name="LastName" column="LastName" type="String" length="50"/>
   </joined-subclass>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="MyApp.Domain">
   <class name="Address" table="Address">

      <cache usage="read-write" />

      <id name="Id" type="Int32" column="id" unsaved-value="0">
         <generator class="identity"/>
      </id>

      <property name="Street" column="Street" type="String" length="50" />
      <property name="Number" column="Number" type="String" length="50" />
   </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():
Code:
person = new Person();
person.FirstName = 'John';
person.LastName = 'Doe';
person.Address.Street = 'Bakerstreet'; //The Address-instance is created in the constructor of Person
person.Address.Number = 10;
Db.Save(person);

// This is the Save-method from Simon Green's Db-class (comes with NHibernateHelper).
public static void Save(object item)
    {
        ITransaction transaction = Db.Session.BeginTransaction();

        try
        {
            Db.Session.Save(item);
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
    }


Full stack trace of any exception that occurs:
Code:
[SqlException (0x80131904): Cannot insert the value NULL into column 'address_id', table 'MyDatabase.dbo.Person'; column does not allow nulls. INSERT fails.
The statement has been terminated.]
   System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +95
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +82
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +346
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +3244
   System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +186
   System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +1121
   System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +334
   System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) +407
   System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +149
   NHibernate.Impl.BatcherImpl.ExecuteNonQuery(IDbCommand cmd) +58
   NHibernate.Persister.NormalizedEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlString[] sql, Object obj, ISessionImplementor session) +892

[ADOException: could not insert: [Person]]
   NHibernate.Persister.NormalizedEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlString[] sql, Object obj, ISessionImplementor session) +1056
   NHibernate.Persister.NormalizedEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session) +192
   NHibernate.Impl.ScheduledIdentityInsertion.Execute() +97
   NHibernate.Impl.SessionImpl.Execute(IExecutable executable) +128
   NHibernate.Impl.SessionImpl.DoSave(Object theObj, Key key, IClassPersister persister, Boolean replicate, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything) +787
   NHibernate.Impl.SessionImpl.DoSave(Object obj, Object id, IClassPersister persister, Boolean useIdentityColumn, CascadingAction cascadeAction, Object anything) +443
   NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything) +257

[ADOException: Could not save object]
   NHibernate.Impl.SessionImpl.SaveWithGeneratedIdentifier(Object obj, CascadingAction action, Object anything) +394
   NHibernate.Impl.SessionImpl.Save(Object obj) +237
   Db.Save(Object item) in c:\NET\MyApp\App_Code\NHibernate\Db.cs:157
   EditPerson.butSave_Click(Object sender, EventArgs e) in c:\NET\MyApp\User Controls\EditPerson.ascx.cs:52
   System.Web.UI.WebControls.Button.OnClick(EventArgs e) +96
   System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +117
   System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +31
   System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +32
   System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +72
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3840


Name and version of the database you are using:
SQL Server 2005


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 07, 2006 5:15 pm 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
I don't see address_id column in the mappings, are these really the correct mapping files?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 07, 2006 5:39 pm 
Beginner
Beginner

Joined: Tue May 17, 2005 2:48 pm
Posts: 47
Sergey, I solved it. You mentioned that address_id was missing. I didn't map address_id since column is not an attribute of the one-to-one mapping.
I got rid of the one-to-one mapping in Person and mapped Address via a many-to-one relation to Address.
Code:
<many-to-one name="Address" class="Address" column="address_id" unique="true" cascade="all" />

I already tried this once, but then I forgot to set the cascade attribute.
It works fine now.


Top
 Profile  
 
 Post subject: Re: One-to-one mapping
PostPosted: Wed Mar 08, 2006 4:48 am 
Newbie

Joined: Wed Dec 21, 2005 6:17 am
Posts: 10
JackBigMac wrote:
Hibernate version: NHibernate 1.1


Are you sure? ;)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 08, 2006 2:37 pm 
Beginner
Beginner

Joined: Tue May 17, 2005 2:48 pm
Posts: 47
The name of the Visual Studio solution is NHibernate 1.1, so I figured that 1.1 would be the version number. It is not?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 08, 2006 3:14 pm 
Regular
Regular

Joined: Fri Jan 27, 2006 2:32 pm
Posts: 102
Location: California, USA
JackBigMac wrote:
The name of the Visual Studio solution is NHibernate 1.1, so I figured that 1.1 would be the version number. It is not?


No. It means that it is the solution file for the .Net Framework version 1.1.

AFAIK, the last stable version of NHibernate is 1.0.2


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