HQL query over sub-classes
I have the following entities defined in my Entity Model:
public class MyContainer
{
public virtual ICollection<Base> Subs { get; set; }
}
public abstract class Base
{
public virtual Guid Id { get; set; }
}
public abstract class Sub1 : Base
{
public virtual int MyValue { get; set; }
}
public abstract class Sub2 : Base
{
public virtual int MyValue { get; set; }
}
and the following FluentNHibernate mappings for the above entities:
public sealed class BaseMap : ClassMap<Base>
{
public BaseMa开发者_运维百科p()
{
Table("BaseTable");
Id(e => e.Id);
}
}
public sealed class Sub1Map : SubClassMap<Sub1>
{
public Sub1Map()
{
Table("Sub1Table");
KeyColumn("BaseId");
Map(e => e.Myvalue);
}
}
public sealed class Sub2Map : SubClassMap<Sub2>
{
public Sub2Map()
{
Table("Sub2Table");
KeyColumn("BaseId");
Map(e => e.Myvalue);
}
}
When I run the following HQL:
select sub
from MyContainer container
join fetch container.Subs sub
where sub.MyValue = :p1
the SQL generated only applies a constraint in the WHERE clause for one of the sub-classes, however, the generated JOINS are correct, i.e., the following skeletal SQL is generated:
SELECT ...
FROM BaseTable bt
INNER JOIN Sub1Table st1 ON ...
INNER JOIN Sub2Table st2 ON ...
WHERE st1.MyValue = @p1
where as I'm expecting an additional OR in the WHERE clause:
SELECT ...
FROM BaseTable bt
INNER JOIN Sub1Table st1 ON ...
INNER JOIN Sub2Table st2 ON ...
WHERE st1.MyValue = @p1
OR st2.MyValue = @p2
Is there something I'm missing, or is there a way to re-write the HQL so that I can reference each sub-class in the WHERE clause and apply the constraint directly (assuming that it would then generate the additional constraint in the generated SQL)?
I'm using NHibernate 3.0.0.
MyValue should be declared and mapped in Base. It is not possible to filter base class by properties that are defined in subclasses without casting to the particular class:
where (b.class = Sub1 and b.MyValue = :p1) or (b.class = Sub2 and b.MyValue = :p1)
EDIT: Or in FNH1.2 union subclassing can be used:
public class BaseMap : ClassMap<Base>
{
public BaseMap()
{
UseUnionSubclassForInheritanceMapping();
Table("BaseTable");
Id(e => e.Id);
}
}
精彩评论