Question

Say I have two persistent classes Cat and Hat. Let's imagine that the relationship between the two is bidirectionally one-to-many, as in a Cat can have many different Hats, and we can traverse the mapping in both directions. In order to create an association between an instance of each class, I should be able to, and correct me if I'm wrong, do the following:

Cat whiskers = new Cat();
Hat redHat = new Hat();
redHat.Id = 1; // normally assigned by generator but this makes example more explicit
whiskers.Hats.Add(redHat);
catService.Save(whiskers);
hatService.Save(redHat);

With that in mind, should I not be able to retrieve the Cat which is associated with redHat by doing the following?

Hat hat = hatService.FindById(1); // redHat has Id 1
Cat cat = hat.Cat; // cat should be whiskers

Unfortunately, when I try to use this technique, cat results as a null object in that last line. I'm guessing I am missing something in my one-to-many mapping in Cat.hbm.xml, or at least I hope it's something that simple. Here's what it currently looks like:

<set name="Hats" inverse="true">
  <key column="Id"/>
  <one-to-many class="Hat"/>
</set>

I have no mapping in Hat.hbm.xml since adding one resulted in a "duplicate mapping" error. I read the Hibernate documentation on association mappings, but still can't get this working. What am I doing wrong?

Complete mapping files below:

Cat.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="Domain"
               namespace="Domain">

  <class name="Cat" table="cats" lazy="true">

    <id name="Id">
      <generator class="increment" />
    </id>

    <property name="Name" />

    <set name="Hats" inverse="true">
      <key column="Id"/>
      <one-to-many class="Hat"/>
    </set>

  </class>

</hibernate-mapping>

Hat.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
               assembly="Domain"
               namespace="Domain">

  <class name="Hat" table="hats" lazy="true">

    <id name="Id">
      <generator class="increment" />
    </id>

  </class>

</hibernate-mapping>

Edit

I believe the problem was that I was not initializing the ISet<Hat> value in the Cat class. However, I've run into a new problem. When I try to access the associations, I get this error:

Could not initialize proxy - no Session.

I figured this would be easily avoided if I created a method in my DAO where I could wrap it in a session like this:

public Cat GetRelatedCat(Hat hat)
{
    Cat cat;
    using (ISession session = HibernateUtil.GetSessionFactory().OpenSession())
    {
        cat = hat.Cat;
    }
    return cat;
}

This yields the same "no session" error. I'm stumped.

Was it helpful?

Solution 2

I solved the problem by creating a SessionManager which allows me to open a Session, perform any transactions and access any collection proxies within the Session singleton, and then close the Session.

OTHER TIPS

  1. You need to add a many-to-one entry in your hat.hbm. I think should work.

  2. Then you have to set both sides of the association

    whiskers.Hats.Add(redHat);

    redHat.Cat=whiskers;

I think this should make your sample work.

THe reason for your "no session" problem is, that the collection proxy only works with the session it was created with. So in your example it works only with the session that created your Hat instance. It is possible to connect a proxy with another session but that is generally not recommeded, because it has complex implications on transaction boundaries and data consistency.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top