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.  [ 10 posts ] 
Author Message
 Post subject: Domain model using Interfaces - how to map in nHibernate
PostPosted: Fri Apr 30, 2010 6:37 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
Hi,

I have what should be a relatively simple issue but I am struggling to resolve it.

There are 2 tables in my data model: Group and Category. There is a one-to-many relationship....one Group can have many Categories, and a Category can be in one group.

I've got the same 2 classes in my domain model, standard stuff.

Now, I need to write some unit tests for a controller class which uses instances of Group and Category. But the key here is that they are unit tests so I would use a mocking framework (NMock2 in this case) to create mock instances of the domain objects.

So standard practice is to have your domain objects implement an interface, and use the interface to create the mock instances.

So I created an IGroup and ICategory. ICategory has an accessor for it's group. Now I'm working with interfaces the ICategory.Group returns an IGroup rather than a group:

Code:
public interface ICategory
{
    int Id { get; set; }
    string Name { get; set; }
    IGroup Group { get; set; }
}


This is all fine and my unit tests with the mock instances of ICategory and IGroup all work fine.

HOWEVER....now I am unable to do any data access with the Category and Group objects...I get the following NHibernate error:

Code:
NHibernate.MappingException: An association from the table CATEGORY refers to an unmapped class: CLEDOM.Business.Domain.IGroup.


Here's my mapping file for Category:

Code:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="CLEDOM.Business">

   <class name="CLEDOM.Business.Domain.Category" table="CATEGORY">

      <cache usage="read-only"/>

      <id name="Id" type="int" column="CategoryId">
         <generator class="native" />
      </id>

      <property name="Name" type="string" column="Name" length="128" />

      <many-to-one name="Group" column="GroupId" />

   </class>
   
</hibernate-mapping>


I tried to find some info on this but didn't really find a good example of a domain model implemented using standard interfaces. I did find some stuff but it had all sorts of IoC and Castle Windsor in there which was way over the top for what I want. I just want to use simple interfaces!

I did find another sample which included a "proxy" attribute on the class element. So I tried this:

Code:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="CLEDOM.Business">

   <class name="CLEDOM.Business.Domain.Category" proxy="CLEDOM.Business.Domain.ICategory" table="CATEGORY">

  etc...
  etc...


but that made no difference.

Can anybody help? Can my domain model be coded against interfaces?


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Fri Apr 30, 2010 10:08 am 
Beginner
Beginner

Joined: Fri Feb 27, 2009 6:07 am
Posts: 38
Location: Moscow,Russia
Use abstract class instead of interface.

Code:
Code:
public abstract class Group
    {
        private int id;
     
        public int Id
        {
            get { return id;}
            set{id = value;}
        }
    }

public class ProductGroup : Group
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }


Mapping:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Test" assembly="Test">
  <class name="Group" lazy="false">
    <id name="Id">
      <column name="Id"/>
      <generator class="native"/>
    </id>
    <joined-subclass name="ProductGroup" lazy="false">
      <key column="GrouId"/>
      <property name="Name"/>
    </joined-subclass>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Fri Apr 30, 2010 11:09 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
Ah, I NEED the interface in order to generate a dynamic mock!


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Mon May 03, 2010 7:22 am 
Beginner
Beginner

Joined: Fri Feb 27, 2009 6:07 am
Posts: 38
Location: Moscow,Russia
You can use only classes for object mapping.


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Tue May 04, 2010 4:18 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
Surely it's a common scenario to want to use domain objects which are coded against an interface?

What if you have pre-existing domain model coded against an interface? Or a domain model under the control of another team?


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Tue May 04, 2010 5:40 am 
Beginner
Beginner

Joined: Fri Feb 27, 2009 6:07 am
Posts: 38
Location: Moscow,Russia
It is scenario does not approach for NHibernate.
For pre-existing domain model you can use object-wrapper.


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Tue May 04, 2010 5:47 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
I just found out I can use Interfaces for my domain model.

Turns out all I needed was to explicitly name the class on the many-to-one mapping from my Category to Group table:

<many-to-one name="Group" class="CLEDOM.Business.Domain.Group" column="GroupId" />

That's resolved it, and my domain objects are coded against interfaces.

Thanks for the input!


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Wed May 05, 2010 4:38 pm 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
I tried adding the class to the many-to-one mapping as
suggested:


<many-to-one name="Group" class="CLEDOM.Business.Domain.Group"
column="GroupId" />


And YES! That fixed my original problem!


So now it's all happy.


However the story doesn't end there. I have now got a bit further
with my tests. I have a generic broker (implementing IBroker<T> )
which I use to fetch instances from nHibernate. Standard CRUD stuff.


Before I put the interfaces on my domain objects I would create an
instance of the generic broker with something like:


broker = new Broker<Category>();


But now my domain objects are implementing interfaces I need to use
interfaces with my broker.


eg:


broker = new Broker<ICategory>();


So now when doing this and trying to get an instance from the broker I
get the following error:


"there is no persister for ICategory"


Gahhh!!!!


So I'm still a bit lost.


Max you said your domain model was coded against interfaces. Would
you be able to let me have a sample of one of your classes, it's
interface and corresponding hbm mapping?


I'm not mapping the interface in my nHibernate. Here's my mapping for
Category:


Here's my mapping file for Category:


<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-
import="true" assembly="CLEDOM.Business">
<class name="CLEDOM.Business.Domain.Category" table="CATEGORY">
<cache usage="read-only"/>
<id name="Id" type="int" column="CategoryId">
<generator class="native" />
</id>
<property name="Name" type="string" column="Name"
length="128" /
<many-to-one name="Group" class="CLEDOM.Business.Domain.Group"
column="GroupId" />
</class>
</hibernate-mapping>


So as you can see I'm not mapping the interface ICategory. Should I
be? And if so, how!?!?


Very confused.....!


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Thu May 06, 2010 1:46 am 
Beginner
Beginner

Joined: Fri Feb 27, 2009 6:07 am
Posts: 38
Location: Moscow,Russia
Try:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="CLEDOM.Business" assembly="CLEDOM.Business">
  <class name="ICategory" lazy="false">
    <id name="Id">
      <column name="Id"/>
      <generator class="native"/>
    </id>
    <property name="Name" type="string" column="Name" length="128" / >
    <many-to-one name="Group" class="CLEDOM.Business.Domain.Group" column="GroupId" />
    <joined-subclass name="CLEDOM.Business.Domain.Category" lazy="false">
      <key column="CategoryId"/>
      <property name="SomeProperty"/>
    </joined-subclass>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: Domain model using Interfaces - how to map in nHibernate
PostPosted: Thu May 06, 2010 6:45 am 
Newbie

Joined: Fri Apr 30, 2010 6:05 am
Posts: 9
Thanks, that worked!


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