views:

461

answers:

1

I'm doing some per table inheritance and all is working great- but I'm noticing that when I want the base entity (base table data) NHProf is showing a left outter join on the child entity / (related table)

How can I set the default behavior to only query the needed data - for example: When I want a list of parent elements (and only that data) the query only returns me that element.

right now my mapping is similar to the below:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="FormBase, ClassLibrary1" table="tbl_FormBase">
    <id name="BaseID" column="ID" type="Int32" unsaved-value="0">
      <generator class="native" />
    </id>
    <property name="ImportDate" column="ImportDate" type="datetime" not-null="false" />
    <joined-subclass table="tbl_Form" name="Form, ClassLibrary1">
      <key column="ID"/>
      <property name="gendate" column="gendate" type="string" not-null="false" />
    </joined-subclass>
  </class>
</hibernate-mapping>

And the example where I want all the data back vs ONLY the parent entity is shown below:

    Dim r As New FormRepository()
    Dim forms As List(Of Form) = r.GetFormCollection().ToList()



    Dim fbr As New FormBaseRepository()
    Dim fb As List(Of FormBase) = fbr.GetFormBaseCollection().ToList()
+2  A: 

You can't. It's called "implicit polymorphism" and it's a rather nice (albeit unwanted in your case :-) ) feature provided by Hibernate. When you query a list of base objects, the actual instances returned are of the actual concrete implementations. Hence the left join is needed for Hibernate to find out whether particular entity is a FormBase or a Form.

Update (too big to fit in comment): The general issue here is that if you were to trick Hibernate into loading only the base entity you may end up with inconsistent session state. Consider the following:

  1. Form instance (that is persisted to both form_base and form tables) was somehow loaded as FormBase.
  2. You've deleted it.
  3. During flush Hibernate (which thinks we're dealing with FormBase and thus is blissfully unaware that there are 2 tables involved) issues a DELETE FROM form statement which throws an exception as FK is violated.

Implicit polymorphism exists to prevent that from happening - Form is always a Form, never a FormBase. You could, of course, use "table-per-hierarchy" mapping where everything is in the same table and thus no joins are needed but you'll end up with (potentially) a lot of NULL columns and - ergo - inability to specify not-null on children's properties.

All that said, if this is REALLY a huge performance issue for you (which it normally shouldn't be - presumably it's an indexed join), you could try using a native query to just return FormBase instances.

ChssPly76
Ahh ... - is there another approach to this inheritance problem that will keep my base table separate if I query for that entity and not the child? (right now each child element has its own table)
Toran Billups
I've updated my answer above - too much stuff to fit in comment
ChssPly76
Well i don't think it's a huge issue in my POC currently but this base class is inherited by almost 12 other classes in my production application ... so i'm a little worried (maybe I shouldn't be as you mentioned -- each would be an indexed join)
Toran Billups
12, huh? :-) 12 left joins might be a bit concerning on large tables; you should actually measure the performance before taking any drastic steps, though. One possible approach (which may or may not work depending on your needs) is to mix the table-per-concrete-class and table-per-subclass strategies: https://www.hibernate.org/hib_docs/nhibernate/1.2/reference/en/html/inheritance.html This will only make sense if your hierarchy has multiple levels; won't work for 12 horizontal subclasses.
ChssPly76