-->
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: Insert problems with many-to-many association.
PostPosted: Tue May 08, 2007 11:04 am 
Newbie

Joined: Mon Apr 23, 2007 3:55 pm
Posts: 10
Hibernate version: 1.2.0 GA
Database: Microsoft SQL Server 2000

Description:
I have two classes, File and Category simple as that. The File can have several categories and the category several files. Here's the deal. When I save a file to the database a want to assign it a category/categories as well. If I add a file manually to the database and assigning its categories I can perfectly get what categories a file has, and vice versa. Nothing wrong with that. My problem is that when I try to upload a file whit NHibernate and try to assign that file to a category it does not work, it only adds the file and that's it!
It will become more clear once the mapping is displayed.
Note! It's only small portions of the classes.

File class:
Code:
public class File
{
    private string _fileName;
    //etc...
    private IList<Category> _fileCategorys = new List<Category>();

    //and then the get, set for all the members.
}


File mapping:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Acme" namespace="Acme.Core.Domain">
<class name="File" table="Files" lazy="true">
        <id name="ID" column="pkFileGuid">
            <generator class="guid.comb" />
        </id>
       <property name="Name" column="FileName" type="String(50)" unique="true" />
       etc...
       <bag name="Categories" table="FileCategories" inverse="true" lazy="true">
            <key column="fkFileGuid" />
            <many-to-many class="Category" column="fkCategoryID" />
        </bag>
</class>


Category class:
Code:
public class Category
{
    private string _fileName;
    //etc...
    private IList<Category> _fileCategories = new List<Category>();

    //and then the get, set for all the members.
}


Category mapping:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Acme" namespace="Acme.Core.Domain">
<class name="Category" table="Categories" lazy="true">
        <id name="ID" column="pkCategoryID" type="Int32">
            <generator class="native" />
        </id>
        <property name="Name" column="CategoryName" type="String(50)" unique="true" />
        <bag name="Files" table="FileCategories" inverse="true" lazy="true">
            <key column="fkCategoryID" />
            <many-to-many class="File" column="fkFileGuid" />
        </bag>
    </class>


"Database Diagrams"

Files:

Name: Type:
-------------------------------
pkFileGuid uniqueidentifier
FileName nvarchar(50)

FileCategories:

Name: Type:
-------------------------------
fkFileGuid uniqueidentifier
fkCategoryID int


Categories:

Name: Type:
-------------------------------
pkCategoryID int
CategoryName

Example
Code:
File file = new File();
file.Name = "Test";

// Trying with the categories ID.
Category category = new Category(1);
// Even tried with the name of the category.
file.Categories.Add("Foo");

// Finally, save it.
FileDao.SaveOrUpdate(file);


I don't really know if this is the correct way but I thought that if NHibernate can get all the categories that a file has and vice versa it mind as well insert them automatically. And again, this does not generate any errors, but it does not insert the category assigned to the file in the database. I know that NHibernate can do this, I'm sure that there something with my mapping, or?

Oh yeah, one more thing... :) Anyone have a good idea on how to handle file duplicates, I do not want users to be able to upload the same file does this have to be handled manually by a stored procedure or such?


Top
 Profile  
 
 Post subject: Re: Insert problems with many-to-many association.
PostPosted: Tue May 08, 2007 12:17 pm 
Senior
Senior

Joined: Thu Feb 09, 2006 1:30 pm
Posts: 172
c3nturion wrote:
File mapping:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Acme" namespace="Acme.Core.Domain">
<class name="File" table="Files" lazy="true">
        <id name="ID" column="pkFileGuid">
            <generator class="guid.comb" />
        </id>
       <property name="Name" column="FileName" type="String(50)" unique="true" />
       etc...
       <bag name="Categories" table="FileCategories" inverse="true" lazy="true">
            <key column="fkFileGuid" />
            <many-to-many class="Category" column="fkCategoryID" />
        </bag>
</class>


Example
Code:
File file = new File();
file.Name = "Test";

// Trying with the categories ID.
Category category = new Category(1);
// Even tried with the name of the category.
file.Categories.Add("Foo");

// Finally, save it.
FileDao.SaveOrUpdate(file);



I see one clear issue, which is that you never saved your category. I'm going to assume this is why you are seeing the behavior you are describing. You really have two choices here, one you could call Save(category); (or SaveOrUpdate() if you wish) or you could change the cascade rule on the Categories collection of the Files mapping file. Note you would need to change the cascade property for the Files collection of Category if you wanted it to work both ways. Set the cascade to "save-update" then re-run the code you provided. You should see your desired result.


Top
 Profile  
 
 Post subject: Re: Insert problems with many-to-many association.
PostPosted: Tue May 08, 2007 1:08 pm 
Newbie

Joined: Mon Apr 23, 2007 3:55 pm
Posts: 10
jchapman wrote:
I see one clear issue, which is that you never saved your category. I'm going to assume this is why you are seeing the behavior you are describing. You really have two choices here, one you could call Save(category); (or SaveOrUpdate() if you wish) or you could change the cascade rule on the Categories collection of the Files mapping file. Note you would need to change the cascade property for the Files collection of Category if you wanted it to work both ways. Set the cascade to "save-update" then re-run the code you provided. You should see your desired result.


Thanks for your response but I thought since NHibernate automatically gets the categories for a file, it mind as well add it when I save a file right? About the cascade, that does not solve this problem because it only adds more categories to the Categories table, which I do not want.

For instance, if I have the two categories Official and Themes it would be:

Code:
pkCategoryID   CategoryName
-----------------------------
1              Official
2              Themes


Suppose I then do as I mentioned before, file.Categories.Add("Official"); it would add another Official category to the Categories table with the ID 3, which is wrong. I want it to add the file guid and the categories id to the FileCategories table. I hope it didn't get too confusing.


Top
 Profile  
 
 Post subject: Re: Insert problems with many-to-many association.
PostPosted: Tue May 08, 2007 2:32 pm 
Senior
Senior

Joined: Thu Feb 09, 2006 1:30 pm
Posts: 172
c3nturion wrote:
jchapman wrote:
Suppose I then do as I mentioned before, file.Categories.Add("Official"); it would add another Official category to the Categories table with the ID 3, which is wrong. I want it to add the file guid and the categories id to the FileCategories table. I hope it didn't get too confusing.


You just showed your problem right there. That's not the code you would write.

You really want to write file.Categories.Add(category). Why are you passing in a string. Really I suspect you are doing the following:

Code:
Category c = new Category("Official");
file.Categories.Add(c);


This is wrong, you are now telling NHibernate that there is a new category, when there really isn't. Based on this usage I'm going to guess what you are using it for. Potentially you are using a web based interface where you store the category value in the drop down list? In that case do something like this:

Code:
Category c = Session.Load(typeof(Category), ddl.SelectedValue);
file.Categories.Add(c);
Session.Save(file);


Now you no longer create new categories, but rather add the category to the file's categories collection. Ideally in that code you would add the item to both sides of the relationship. Meaning that after you load the category you will call c.Files.Add(file) as well as file.Categories.Add(c).


Top
 Profile  
 
 Post subject: Still not working...
PostPosted: Wed May 09, 2007 4:24 am 
Newbie

Joined: Mon Apr 23, 2007 3:55 pm
Posts: 10
Thanks again for your respoonse! Oh I see, but still it does not add the information to the FileCategories-table...

1. Make sure that the cascade="save-update" is present on each collection in the hbm.xml-files.
2. Create a file with all it's necessary properties.
3. Load a category/categories and add the file to it/them.
4. Add the category/categories to the file.
5. Save the file.
6. Save the category/categories.

I don't know what I'm doing wrong here...? I've done as you've said and still...

Edit
The funny thing is that after step 6. If I then do:
Code:
List<File> files = FileDao.GetAll();

foreach(File file in files)
{
    Console.WriteLine(file.Name);
    foreach(Category category in file.Categories)
    {
        Console.WriteLine("--{0}", category.Name);
    }
}


It would result in:
Code:
Test
-- Foo
Foo-file
-- Foo
-- Bar


And Test is the file I've just added with the category Foo. The Foo-file is the one I've added manually in Enterprise Manager. If I then go the database, the categories is not added, I guess this has to do with the NHibernate cache right?


Top
 Profile  
 
 Post subject: Solved!
PostPosted: Wed May 09, 2007 10:10 am 
Newbie

Joined: Mon Apr 23, 2007 3:55 pm
Posts: 10
Solved!
The problem lied in the mapping (as I thought). The problem was that I specified the inverse="true" in both Files.hbm.xml and Category.hbm.xml. I've now removed the attribute from the Category.hbm.xml and it works.

I made my homework and read the manual a bit more closely!


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.