-->
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: Newbie Question: Mapping One-To-One for User to Address.
PostPosted: Wed Jul 25, 2007 11:21 pm 
Newbie

Joined: Wed Jul 25, 2007 11:04 pm
Posts: 5
Hi all, I guess this has been asked many times but I couldn't find the answer in the forums.

I have a one-to-one mapping for a user to an address and I was wondering if I need to commit the address to DB before committing the User with the saved user. The reason why I'm asking this is because I want to be able to save User and be able to save the address at the same time so that if anything goes wrong while saving the user, it can rollback everything without an entry in the address table. I hope I'm being clear in what I wanna do here.

By the way, I also want the mapping to behave in such a way that if in any point of time, the reference to addressID has been changed, it deletes away the broken child link

Hibernate version:1.0.2.0 (old version)

Mapping documents:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="Cooee.bizObj.HeavyUser, Cooee" table="CooeeUser" dynamic-update="true">
<id name="UserID" column="UserID" type="Int32" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Login" column="Login" type="String" length="100" />
<property name="LoginRefID" column="LoginRefID" type="Int32" length="4" />
<many-to-one name="UserType" class="Cooee.bizObj.UserType, Cooee" column="UserTypeID"/>
<property name="Title" column="Title" type="String" length="50" />
<property name="FirstName" column="FirstName" type="String" length="100" />
<property name="LastName" column="LastName" type="String" length="100" />
<many-to-one name="Address" class="Cooee.bizObj.Address, Cooee" column="AddressID" unique="true" cascade="all"/>
<property name="Email" column="Email" type="String" length="255" />
<many-to-one name="UserStatus" class="Cooee.bizObj.UserStatus, Cooee" column="UserStatusID"/>
<property name="NotifyOnDraw" column="NotifyOnDraw" type="Boolean" />
<property name="NotifyOnNewRaffle" column="NotifyOnNewRaffle" type="Boolean" />
<property name="CanAccessAllCharities" column="CanAccessAllCharities" type="Boolean" />
<property name="SourceRef" column="SourceRef" type="String" length="255" />
<property name="CreateDate" column="CreateDate" type="DateTime" />
<property name="EditDate" column="EditDate" type="DateTime" />
<property name="EditorID" column="EditorID" type="Int32" length="4" />
<property name="Note" column="Note" type="String" />
</class>

<class name="Cooee.bizObj.Address, Cooee" table="Address" dynamic-update="true">
<id name="AddressID" column="AddressID" type="Int32" unsaved-value="0">
<generator class="identity" />
</id>
<property name="UnitNumber" column="UnitNumber" type="String" length="50" />
<property name="StreetNumber" column="StreetNumber" type="String" length="50" />
<property name="StreetNumberSuffix" column="StreetNumberSuffix" type="String" length="50" />
<property name="StreetAddress" column="StreetAddress" type="String" length="200" />
<property name="AddressLine2" column="AddressLine2" type="String" length="200" />
<property name="Suburb" column="Suburb" type="String" length="200" />
<property name="State" column="State" type="String" length="10" />
<property name="Postcode" column="Postcode" type="String" length="4" />
<property name="HomeAreaCode" column="HomeAreaCode" type="String" length="2" />
<property name="HomePhone" column="HomePhone" type="String" length="8" />
<property name="WorkAreaCode" column="WorkAreaCode" type="String" length="2" />
<property name="WorkPhone" column="WorkPhone" type="String" length="8" />
<property name="MobilePhone" column="MobilePhone" type="String" length="50" />
<property name="PreferredPhone" column="PreferredPhone" type="String" length="10" />
<property name="ContactMorning" column="ContactMorning" type="Boolean" />
<property name="ContactAfternoon" column="ContactAfternoon" type="Boolean" />
<property name="ContactEvening" column="ContactEvening" type="Boolean" />
<property name="CreateDate" column="CreateDate" type="DateTime" />
<property name="EditDate" column="EditDate" type="DateTime" />
<property name="EditorID" column="EditorID" type="Int32" length="4" />
<property name="Note" column="Note" type="String" />
</class>



Code between sessionFactory.openSession() and session.close():

This is the test code i'm using to save a typical user currently... it works but need your opinion on how to make it better.

HeavyUser user = UserManager.GetUserById("32");
UserType usertype = new UserType();
usertype = UserManager.getUserTypeById(Convert.ToString((int)UserTypeValue.super));
UserStatus userstatus = new UserStatus();
userstatus = UserManager.getUserStatusById(Convert.ToString((int)UserStatusValue.active));
HeavyUser heavyuser = new HeavyUser();

heavyuser.UserStatus = userstatus;
heavyuser.UserType = usertype;
heavyuser.FirstName = "Superman";
heavyuser.LastName = "Lastname";
heavyuser.Login = "wee";
heavyuser.LoginRefID = 1;
heavyuser.CreateDate = DateTime.Now;
heavyuser.EditDate = DateTime.Now;
heavyuser.CanAccessAllCharities = true;
heavyuser.NotifyOnDraw = true;
heavyuser.NotifyOnNewRaffle = true;

Address address = new Address();
address.StreetAddress = "lvl 5 William Street";
address.Suburb = "Perth";
address.Postcode = "6100";
address.State = "W.A";
address.CreateDate = DateTime.Now;
address.EditDate = DateTime.Now;
address.ContactMorning = true;
address.ContactAfternoon = true;
address.ContactEvening = true;
//// --> This is the part that saves address first and then user /////
UserManager.Save(address);
heavyuser.Address = address;
UserManager.Save(heavyuser);



Full stack trace of any exception that occurs: None..its working fine.

Name and version of the database you are using: MSSQL2000


Last edited by loba on Wed Jul 25, 2007 11:33 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 25, 2007 11:32 pm 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
Use transactions:

Code:
ITransaction tx;
try {
    tx = session.BeginTransaction();
    // your code
    tx.Commit();
}
catch {
    tx.Rollback();
}

_________________
Karl Chu


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 25, 2007 11:35 pm 
Newbie

Joined: Wed Jul 25, 2007 11:04 pm
Posts: 5
Yes that's what Usermanager.Save(object) does..

it does rollback but my current problem here is that it does commit twice in saving Address obj and then User obj thus defeating the purpose of rolling back if User Obj can't be committed.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 26, 2007 12:31 am 
Hibernate Team
Hibernate Team

Joined: Tue Jun 13, 2006 11:29 pm
Posts: 315
Location: Calgary, Alberta, Canada
NHibernate is no different than any other data access technology: you need to wrap everything that should be in a single transaction... well... in a single transaction.

One easy way around would be to have a Usermanager.SaveUserAndAddress(user, address) method, and have your transaction begun and committed in there. However, before long, you will find the limitations with that too. You will likely find that in time, the only manageable way to manage session lifetime and transaction boundary is to manage them outside of your data access objects or data manager or whatever you want to call it. You can do that quite crudely by having Usermanager.BeginTransaction(), Usermanager.Commit(), and Usermanager.Rollback() and call them appropriately in your code. On the other hand, you can employ something like Spring.NET that affords you declarative transaction management. You have a lot of choices. Good luck.

_________________
Karl Chu


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.