I was hoping that I could use the abstract base class in my inheritance hierarchy for a polymorphic query if I know the ID (but, instead, I get a generated query that's incorrect). I wanted to just treat the object(s) returned as the abstract class (for this particular scenario, I don't need to have the code know the subclasses).
I have the following inheritance hierarchy for PhysicalNetworkDevices (many more devices aren't shown):
* PhysicalNetworkDevice (abstract)
* * Router
* * AUI
Note: Almost all of the subclasses of PhysicalNetworkDevice don't add any of their own Properties. A few (such as Router) add additional Properties.
I pass down the deviceID (an integer field that matches the ID field for the object identity). I'd like to be able to do the following:
Code between sessionFactory.openSession() and session.close():
ICriteria c = session.CreateCriteria(typeof(PhysicalNetworkDevice));
c.Add(Expression.Eq("ID", deviceID));
IList<PhysicalNetworkDevice> physicalNetworkDevices = (IList<PhysicalNetworkDevice>)c.List();
...
but I get an error with the generated query (the query thinks it needs to join fields from tblRouter - tier1 and loopback fields - [which it shouldn't if it's just dealing w/ the abstract class, right?] and then includes these fields but not the join to tblRouter):
Debug level Hibernate log excerpt:
The multi-part identifier "this_1_.Tier" could not be bound.
The multi-part identifier "this_1_.LoopBackIP" could not be bound.
The multi-part identifier "this_2_.Tier" could not be bound."
The generated SQL (show_sql=true):
SELECT this_.ID as ID0_0_, this_.Manufacturer as Manufact3_0_0_, this_.Version as Version0_0_, this_1_.Tier as Tier1_0_, this_1_.LoopBackIP as LoopBackIP1_0_, this_2_.Tier as Tier2_0_, this_.TypeName as TypeName0_
FROM dbo.tblDevice this_
WHERE this_.ID = ?
Persistence strategy for the inheritance:
Almost all PhysicalNetworkDevice objects can be represented in one table, tblDevice. Some (e.g. Router) add some additional fields of their own and, therefore, have an additional table. Therefore, we use table-per-class-hierarchy mixed with table-per-subclass (separate additional table) for objects like Router.
tables:
- tblDevice: identity=ID, (common properties)
- tblRouter: identity=ID; FK_pDeviceID is a foreign key to tblDevice, properties specific to Router: Tier, Loopback
Hibernate version: Custom-built 1.2.0.GA merged with the NH-466 patch
Mapping documents:
mapping for <PhysicalNetworkDevice>:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="false">
<class name="PhysicalNetworkDevice, Domain" table="dbo.tblDevice">
<id type="Int32" column="ID" name="ID" unsaved-value="null">
<generator class="identity"></generator>
</id>
<discriminator column="TypeName"/>
<property name="Manufacturer" column="Manufacturer"/>
<property name="Version" column="Version"/>
<subclass name="AUI, Domain" discriminator-value="AUI">
</subclass>
<subclass name="Router, Domain" discriminator-value="Router">
<join table="dbo.tblRouter">
<key column="FK_pDeviceID"/>
<property name="Tier" column="Tier"/>
<property name="LoopBackIP" column="LoopBackIP"/>
</join>
</subclass>
</hibernate-mapping>
Name and version of the database you are using: Microsoft SQL Server 2005; Version: 9.00.1406.00; Product Level: RTM; Edition: Developer Edition
_________________ metazone
|