<union-subclass> + mapping multiple classes into one table

1,089 views
Skip to first unread message

Piotr Jakóbczyk

unread,
Feb 20, 2009, 7:10:18 AM2/20/09
to nhusers
Hi,
I need to map multiple clesses into one database table.The common
table (TABLE1) is shared by class ClassB and SubclassA (subclass of
ClassA) mapped by <union-subcless>. Mapping file looks like in the
following example:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" >
<class name="NhMappingTest.ClassB, NhMappingTest" table="TABLE1" >
<id name="Id" >
<column name="id" sql-type="Int32"/>
<generator class="identity" />
</id>
<property name="Name" type="String" column="name" />
</class>
<class name="NhMappingTest.ClassA, NhMappingTest" abstract="true" >
<id name="Id" >
<column name="id" sql-type="Int32"/>
<generator class="identity" />
</id>
<property name="Name" type="String" column="name" />
<union-subclass name="NhMappingTest.SubclassA, NhMappingTest"
table="TABLE1" />
</class>
</hibernate-mapping>

When NH try to create mappings, its raise the following exception:
NHibernate.MappingException {"Could not compile the mapping document:
NhMappingTest.Mappings.hbm.xml"} - inner exception:
NHibernate.DuplicateMappingException {"Duplicate table mapping
TABLE1"}.

But when we change order of mapping definitions in file, like this:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" >
<class name="NhMappingTest.ClassA, NhMappingTest" abstract="true" >
<id name="Id" >
<column name="id" sql-type="Int32"/>
<generator class="identity" />
</id>
<property name="Name" type="String" column="name" />
<union-subclass name="NhMappingTest.SubclassA, NhMappingTest"
table="TABLE1" />
</class>
<class name="NhMappingTest.ClassB, NhMappingTest" table="TABLE1" >
<id name="Id" >
<column name="id" sql-type="Int32"/>
<generator class="identity" />
</id>
<property name="Name" type="String" column="name" />
</class>
</hibernate-mapping>

everything is ok and mappings are build correctly.
My question is about the presented behaviour of NH, it's correct ("by
desing") or it's a bug?

--
Piotr Jakóbczyk

Fabio Maulo

unread,
Feb 20, 2009, 7:45:17 AM2/20/09
to nhu...@googlegroups.com
union-subclass is an advanced way provided by NH to implement the mapping pattern : table-per-concrete-class

What you are looking for is the implementation of the pattern : table-per-class-hierarchy
The tag for that is <subclass>; reference available here


2009/2/20 Piotr Jakóbczyk <piotr.j...@gmail.com>



--
Fabio Maulo

Fabio Maulo

unread,
Feb 20, 2009, 7:50:21 AM2/20/09
to nhu...@googlegroups.com
A good white paper to read before continue using NH is here

2009/2/20 Fabio Maulo <fabio...@gmail.com>



--
Fabio Maulo

Piotr Jakóbczyk

unread,
Feb 20, 2009, 8:04:10 AM2/20/09
to nhusers
I know what union-subclass is and I read references about all
inheritance strategy implemented by NH.
In my example I used <union-subclass> (look at SubclassA entity
mapping).
But why, in my example, the changing of the order of mapping
definitions provide different behevoiur of NH. The first order raises
exception, but the second not.

On 20 Lut, 13:45, Fabio Maulo <fabioma...@gmail.com> wrote:
> union-subclass is an advanced way provided by NH to implement the mapping
> pattern : table-per-concrete-class
> What you are looking for is the implementation of the pattern :
> table-per-class-hierarchy
> The tag for that is <subclass>; reference available herehttp://nhforge.org/doc/nh/en/index.html#mapping-declaration-subclass
>
> --
> Fabio Maulo

--
Piotr Jakóbczyk

Fabio Maulo

unread,
Feb 20, 2009, 8:55:14 AM2/20/09
to nhu...@googlegroups.com
You CAN'T use <union-subclass> mapping more than one class to the same table.

If you want use only one table you must use <subclass> or a trick like this



--
Fabio Maulo

Fabio Maulo

unread,
Feb 20, 2009, 9:04:18 AM2/20/09
to nhu...@googlegroups.com
Your mapping is wrong...
You should define the ClassB inside the <union-subclass> node and no out-side as an independent class.
one example from our tests (for simplicity)
<class name="Being" abstract="true">

<id name="id">
<generator class="hilo"/>
</id>

<union-subclass name="Human" table="humans">
<property name="sex" not-null="true" update="false"/>
<union-subclass name="Employee" table="employees">
<property name="salary"/>
</union-subclass>
</union-subclass>

<union-subclass name="Alien" table="aliens">
<property name="species" not-null="true" update="false"/>
<many-to-one name="hive" not-null="true"/>
</union-subclass>

</class>



2009/2/20 Piotr Jakóbczyk <piotr.j...@gmail.com>



--
Fabio Maulo

Piotr Jakóbczyk

unread,
Feb 20, 2009, 9:28:39 AM2/20/09
to nhusers
Thanks for quick response.
Let my explain in details what kind of mappings I need.

We have composed hierarchy of objects with common base abstract class
- BusinessObject. Until now we have whole hierarchy mapped by <joined-
subclass>. But becouse of performance reasons and specificity of
realized queries we want to horizontally divide base table of our
hierarchy into a few distinct tables: TABLE1, TABLE2, TABLE3.

The idea is following:
For every new distinct tables should be prepared new classes:
Class1Marker, Class2Marker, Class3Marker derivated from BusinessObject
class.
Class1Marker, Class2Marker and Class3Marker classes are mapped by
<union-subcless>.

In this way, we will have SHALLOW hierarchy of object derivated from
BusinessObject class (stored in several tables: TABLE1, TABLE2,
TABLE3).
This hierarchy is sufficient for most of required and frequently
executed queries and will be used for read only.

But any of Class1Marker, Class2Marker, Class3Marker classes does not
represent concrete object.
So we want to prepare additional distinct hierarhies beased of a
tables TABLE1, TABLE2, TABLE3. For each table separated hierarchy may
used different inheritance strategy (mixing table per class hierarchy
with table per subclass). To do this we need to prepare another
mappings for tables TABLE1, TABLE2, TABLE3 and classes Class1, Class2,
Class3 (not marker).

Everything works fine untill mappings of BusinessObject and
Class1Marker, Class2Marker, Class3Marker classes are placed before
other mapping for tables TABLE1, TABLE2, TABLE3.


On 20 Lut, 14:55, Fabio Maulo <fabioma...@gmail.com> wrote:
> You CAN'T use <union-subclass> mapping more than one class to the same
> table.
> If you want use only one table you must use <subclass> or a trick like thishttp://fabiomaulo.blogspot.com/2008/10/power-of-orm.html
>
> 2009/2/20 Piotr Jakóbczyk <piotr.jakobc...@gmail.com>
>
>
>
>
>
> > I know what union-subclass is and I read references about all
> > inheritance strategy implemented by NH.
> > In my example I used <union-subclass> (look at SubclassA entity
> > mapping).
> > But why, in my example, the changing of the order of mapping
> > definitions provide different behevoiur of NH. The first order raises
> > exception, but the second not.
>
> > On 20 Lut, 13:45, Fabio Maulo <fabioma...@gmail.com> wrote:
> > > union-subclass is an advanced way provided by NH to implement the mapping
> > > pattern : table-per-concrete-class
> > > What you are looking for is the implementation of the pattern :
> > > table-per-class-hierarchy
> > > The tag for that is <subclass>; reference available herehttp://
> > nhforge.org/doc/nh/en/index.html#mapping-declaration-subclass
>
> > > --
> > > Fabio Maulo
>
> > --
> > Piotr Jakóbczyk
>
> --
> Fabio Maulo

--
Piotr Jakóbczyk

Fabio Maulo

unread,
Feb 20, 2009, 9:57:00 AM2/20/09
to nhu...@googlegroups.com
The strategy "mixing table per class hierarchy with table per subclass" is a special and specific feature of Hibernate and NHibernate.
The implementation is 
<class>
  <discriminator ..../>  
  <subclass>
    <join>
    </join>
  </subclass>
  <subclass>
    <join>
    </join>
  </subclass>
</class>

Reference here:


2009/2/20 Piotr Jakóbczyk <piotr.j...@gmail.com>



--
Fabio Maulo

Piotr Jakóbczyk

unread,
Feb 20, 2009, 10:02:03 AM2/20/09
to nhusers
Yes, I know syntax of "mixing table per class hierarchy with table per
subclass".
But I require one SHALLOW (used as read-onlu) hierarchy used <union-
subclass> and several distinct hierarchy used "mixing table per class
hierarchy with table per subclass" with base db tables from first one
hierarchy.

On 20 Lut, 15:57, Fabio Maulo <fabioma...@gmail.com> wrote:
> The strategy "mixing table per class hierarchy with table per subclass" is a
> special and specific feature of Hibernate and NHibernate.The implementation
> is
> <class>
>   <discriminator ..../>
>   <subclass>
>     <join>
>     </join>
>   </subclass>
>   <subclass>
>     <join>
>     </join>
>   </subclass>
> </class>
>
> Reference here:http://nhforge.org/doc/nh/en/index.html#inheritance-tablepersubclass-...
>
> 2009/2/20 Piotr Jakóbczyk <piotr.jakobc...@gmail.com>
--
Piotr Jakóbczyk

Fabio Maulo

unread,
Feb 20, 2009, 10:26:16 AM2/20/09
to nhu...@googlegroups.com
Ok.
Please send classes and tables, then we can talk about mappings.

2009/2/20 Piotr Jakóbczyk <piotr.j...@gmail.com>



--
Fabio Maulo
Message has been deleted

Fabio Maulo

unread,
Feb 20, 2009, 11:05:02 AM2/20/09
to nhu...@googlegroups.com
Sorry but to create a mapping i must know, at least, 2 things: the class and how you want represent its persistent state.
As you know, given a class graph you can represent its persistent state in various ways.


2009/2/20 Piotr Jakóbczyk <piotr.j...@gmail.com>

I can't send a actual classes and tables, but try to consider simple
example:

abstract class BusinessObject
{

}

class ConcreteObject1 : BusinessObject
{
}

class ConcreteObject2 : BusinessObject
{
}


On 20 Lut, 16:26, Fabio Maulo <fabioma...@gmail.com> wrote:
> Ok.Please send classes and tables, then we can talk about mappings.
>
> 2009/2/20 Piotr Jakóbczyk <piotr.jakobc...@gmail.com>



--
Fabio Maulo

Piotr Jakóbczyk

unread,
Feb 20, 2009, 11:13:39 AM2/20/09
to nhusers
I can't send actual classes and tables, but let's try simple example:

abstract class BusinessObject
{
}

class ConcreteObject1 : BusinessObject
{
}

class ConcreteObject2 : BusinessObject
{
}

Additionaly thera are many ohter classes inherited from
ConcreteObject1 as well as ConcretObject2. Except of base class -
BusinessObject - both of concrete class have different specific
characters.
For some reason objects of both concrete classes MUST be stored in
distinct tables: TABLE1, TABLE2.

Sa we have following mappings:

<class name="ConcreteObject1" table="TABLE1" polymorphism="explicite"
>
<subclass>
</subclass>
<subclass>
</subclass>
</class>

<class name="ConcreteObject2" table="TABLE2" polymorphism="explicite"
>
<subclass>
</subclass>
<subclass>
</subclass>
</class>

Mapping strategy of subclasses is not importat at this moment.
Important fact is that mapping strategy for subclasses of
ConcreteObject1 can be different from mappng strategy for subclasses
of ConcreteObject2.

But in some cases we need to query about list of BusinessObject's
(ConcreteObject1 and ConcreteObject2 together) base properties. So we
introduced some special marker classes:

class ConcreteObject1Marker : BusinessObject
{
}

class ConcreteObject2Marker : BusinessObject
{
}

There are no classes inherited from ConcreteObject1Marker or
ConcreteObject2Marker.

And we want to prepare following mapping of BusinessObject class:

<class name="BusinessObject" abstract="true" mutable="false"
polymorphism="explicite" >
<union-subclass name="ConcreteObject1Marker" table="TABLE1">
</union-subclass>
<union-subclass name="ConcreteObject2Marker" table="TABLE2">
</union-subclass>
</class>

And now we should can quering about BusinessObject's instances
although they are stored in distinct tables (TABLE1 and TABLE2).


--
Piotr Jakóbczyk

Piotr Jakóbczyk

unread,
Feb 23, 2009, 2:22:07 AM2/23/09
to nhusers
I would like to point that above mapping pattern works, but only when
the second mapping (of class BusinessObject) was added to NH
configuration BEFORE the first one mapping (of ConcreteObject1 and
ConcreteObject2).
--
Piotr Jakóbczyk

Donghong Wu

unread,
May 13, 2014, 2:29:41 AM5/13/14
to nhu...@googlegroups.com
Hey Piotr,

     I also met this problem. Did you find out any solution? Thanks !

在 2009年2月23日星期一UTC+8下午3时22分07秒,Piotr Jakóbczyk写道:
Reply all
Reply to author
Forward
0 new messages