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.  [ 13 posts ] 
Author Message
 Post subject: One Interface, One Class, One Table
PostPosted: Fri Oct 06, 2006 4:47 pm 
Newbie

Joined: Thu Sep 14, 2006 8:52 pm
Posts: 12
I cannot figure out how to write the mapping file for a class that implements an Interface and is mapped to a single table.

Per Gert's recommendation I am using the subclass, but nhibernate insists on a discriminator and since this is an one to one between Interface and the Class there is no discriminator column.

I have included code for my Interface, Class, and the mapping file (incorrect). Please respond with the correction in the mapping file.

btw it is important to reconstitute back IClient from the database. Thx.

public interface IClient
{
Guid Id { get; set;}
string FirstName { get; set;}
string LastName { get; set;}
int Status { get; set;}
DateTime Change { get; set;}
DateTime Create { get; set;}
}

public class Client : IClient
{

public Client() {}

private Guid id;
private string firstName;
private string lastName;
private int status;
private DateTime change;

public DateTime Change
{
get { return change; }
set { change = value; }
}
private DateTime create;

public DateTime Create
{
get { return create; }
set { create = value; }
}

public int Status
{
get { return status; }
set { status = value; }
}

#region IClient Members


public Guid Id
{
get
{
return id;
}
set
{
id = value;
}
}

public string FirstName
{
get
{
return firstName;
}
set
{
firstName = value;
}
}

public string LastName
{
get
{
return lastName;
}
set
{
lastName = value;
}
}

IClient.hbm.xml file -
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0"
namespace="Model.Interfaces"
assembly="Model.Interfaces">
<class name="IClient" table="cus" discriminator-value="Client" >
<id name="Id" column="cusky">
<generator class="guid" />
</id>
<discriminator force="false" insert="false" type="Model.Interfaces.IClient" />
<property name="FirstName" column="cus01frnm" />
<property name="LastName" column="cus01lanm" />
<property name="Status" column="cusstat" />
<property name="Change" column="`change`" />
<property name="Create" column="`create`" />

<subclass name="Model.Client.Client, Model.Client" extends="Model.Interfaces.IClient">

</subclass>
</class>

</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 06, 2006 5:09 pm 
Regular
Regular

Joined: Tue May 31, 2005 3:18 pm
Posts: 117
Location: Houston
You can't really map an interface. In your case you have a single class, so that should be the class in your mapping.

If you create an abstract class that implements your interface, then you can have a mapping / table for that... and any derived classes will need a discriminator column & property so that NHibernate knows which object to instantiate when loading.

_________________
------------------------------
Ben Scheirman
http://www.flux88.com


Top
 Profile  
 
 Post subject: Response to Sundigital's response
PostPosted: Fri Oct 06, 2006 5:24 pm 
Newbie

Joined: Thu Sep 14, 2006 8:52 pm
Posts: 12
I am new to NHibernate and I hate believe you are right. Working with Intefaces is such an important OO design concept. Recall advice from Gang of Four? I'd appreciate if someone else could corroborate Sundigitals' response.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Oct 06, 2006 5:26 pm 
Regular
Regular

Joined: Tue May 31, 2005 3:18 pm
Posts: 117
Location: Houston
I use interfaces all the time. You can't persist an interface directly, you can only persist something concrete (*wink* like a class).

Yes I know the GoF patterns, and I realize the importance of interfaces. There is nothing that hinders you there.

If you need to implement an interface, then implement it. your first classes will be the only ones that are actually persisted anyway.

_________________
------------------------------
Ben Scheirman
http://www.flux88.com


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 07, 2006 12:08 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
subdigital is right, you can't persist an interface. an interface is simply a contract that forces a concrete class to conform to a recognized standard. the problem you are having in your mapping file is that you are trying to persist the interface when you should be persisting the class. The only time you can use interfaces in the mapping file is when you utilize lasy loading and specify an interface as the proxy. your mapping file should be something like:

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

    <class name="Client" table="cus">
    <id name="Id" column="cusky">
      <generator class="guid" />
    </id>
    <property name="FirstName" column="cus01frnm" />
    <property name="LastName" column="cus01lanm" />
    <property name="Status" column="cusstat" />
    <property name="Change" column="`change`" />
    <property name="Create" column="`create`" />
  </class>

</hibernate-mapping>

And the name of the mapping file should mimic your class. So you might have:

    Model.Client.cs
    Model.Client.hbm.xml
    Model.Interfaces.IClient.cs


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 07, 2006 6:49 am 
Expert
Expert

Joined: Thu Jan 19, 2006 4:29 pm
Posts: 348
subdigital wrote:
You can't really map an interface. In your case you have a single class, so that should be the class in your mapping.

If you create an abstract class that implements your interface, then you can have a mapping / table for that...


A quote from docyumentation http://www.hibernate.org/hib_docs/nhibernate/html/mapping.html#mapping-declaration-class

Quote:
It is perfectly acceptable for the named persistent class to be an interface. You would then declare implementing classes of that interface using the <subclass> element.


You can map an interface. But You must also have a mapped class which is persisted.

Gert

_________________
If a reply helps You, rate it!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 07, 2006 4:01 pm 
Regular
Regular

Joined: Tue May 31, 2005 3:18 pm
Posts: 117
Location: Houston
Yes, of course. You can't persist an interface all by itself, but you can persist properties of an interface to a separate table, if you prefer.

_________________
------------------------------
Ben Scheirman
http://www.flux88.com


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 09, 2006 1:03 pm 
Newbie

Joined: Thu Sep 14, 2006 8:52 pm
Posts: 12
so the issue boils down to this question that "Gert" pointed out in another thread
-
can I persist the a single class that implements an interface without a discriminator column/value?

if the answer is "no" then i wonder if this is a desirable feature that's lacking in nhibernate ... couple of situations where you may need this -

1. in a layered application, you may only want to expose the interfaces from the higher layer to the layers below. so if all your nhibernate specific code is in a persistence layer below the domain layer then you don't want the persistence layer to directly depend on a concrete class in a layer that is above itself.

btw i find myself in the above situation because i want to implement the domain driven design "Repository" patten (evans, nilsson, fowler) and locate the Repository in the Persistence layer.

2. if you are practicing tdd, you may start with an interface and a single class that implements that interface. you may or may not ever implement another class that implements the same interface depending on how your design unfolds.

btw thx all for input/comments so far


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 09, 2006 7:33 pm 
Regular
Regular

Joined: Tue May 31, 2005 3:18 pm
Posts: 117
Location: Houston
This is NOT an issue!

We all understand the benefits of using interfaces. The scenario can be easily mapped using NHibernate, but what you are talking about is just a concrete mapping.

If the consumers need to use the interface, so be it.

If I'm not understanding your requirements, then please explain. I haven't found many situations where NHibernate isn't at all suitable, and in the case of "proper" design, NHibernate soars.

_________________
------------------------------
Ben Scheirman
http://www.flux88.com


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 09, 2006 9:10 pm 
Newbie

Joined: Thu Sep 14, 2006 8:52 pm
Posts: 12
1.3.1 Layered architecture
A layered architecture defines interfaces between code that implements the various
concerns, allowing a change to the way one concern is implemented without significant
disruption to code in the other layers. Layering also determines the kinds
of interlayer dependencies that occur. The rules are as follows:
■ Layers communicate top to bottom. A layer is dependent only on the layer directly below it.
■ Each layer is unaware of any other layers except for the layer just below it.

The above is from page 17/Hibernate in Action.

Unless I am misunderstanding something here, in order to create a business object my persistence layer has to depend on the domain layer which violates the Layered Architecture.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 09, 2006 9:24 pm 
Newbie

Joined: Thu Sep 14, 2006 8:52 pm
Posts: 12
softlogger wrote:
1.3.1 Layered architecture
A layered architecture defines interfaces between code that implements the various
concerns, allowing a change to the way one concern is implemented without significant
disruption to code in the other layers. Layering also determines the kinds
of interlayer dependencies that occur. The rules are as follows:
■ Layers communicate top to bottom. A layer is dependent only on the layer directly below it.
■ Each layer is unaware of any other layers except for the layer just below it.

The above is from page 17/Hibernate in Action.

Unless I am misunderstanding something here, in order to create a business object my persistence layer has to depend on the domain layer which violates the Layered Architecture.


btw please don't get me wrong. I have been asked to assess NHibernate, I think Hibernate is a good framework and I hope we use it. But my recommendation to use it on our project must include its limitations/idiosyncracies.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 10, 2006 8:34 am 
Regular
Regular

Joined: Tue May 31, 2005 3:18 pm
Posts: 117
Location: Houston
How can you hope to persist your classes if your persistence layer doesn't know about your domain model?

Some of the more common techniques for layering your application are:

Code:
UI -> Domain Model <- Data Access ->Nhibernate

   UI->Domain Model
     |          ^
     v          |
   DataAccess


The distinction being that you may or may not want to directly use NHibernate from your UI.

I separate this so that the consumer doens'nt know about nhibernate, but rather queries for everything via repositories.

In both cases, the Data Access layer KNOWS about the domain model and thus any concrete objects in it.
[/list]

_________________
------------------------------
Ben Scheirman
http://www.flux88.com


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 29, 2007 1:43 am 
Beginner
Beginner

Joined: Tue Sep 14, 2004 1:03 pm
Posts: 33
Location: Calgary, Alberta Canada
I am recently looking for a solution to this problem. It seems to be an old post but, never seemed to get resolved. With Spring.net and other IoC methods, you should be able to have the one interface, one class, one table.

For instance, I have ClassA that uses a property (or component) of IClassB. When I create my mapping, I want to specfy the IClassB in the mapping, not the concrete class. I can hear the questions now, but why etc.

My interfaces could be in one or more DLLs and concrete classes in another. Also my persistence layer could be busted up into multiple DLLs based on components. I want one of my persistence DLLs to map to the interfaces rather than the concrete classes because if (or when) I change my concrete classes I don't want persistence component B to break because of a namespace or assembly name change.

I've tried a couple of work arounds using joined-subclass but get the error regarding can not map to the same table as the parent, or something to that effect. Can't use subclass because there is no discriminator.

Code:
ClassA{
  IClassB obj;
  public IClassB Obj{
    get{return obj;}
    set{obj = value;}
  }
}

<class name="ClassA">
  ...
  <many-to-one name="Obj"
    class="IClassB" />
</class>


So I want to map to the interface, not the concrete class. So to do this, I need to map the interface, but I want the concrete class mapped to the same table.


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