将两个类映射到同一张表

时间:2019-01-17 16:18:03

标签: nhibernate nhibernate-mapping

在旧式数据库中有一个NODES表,其中包含数十个“小”列和一个LOB列。 NodeEntity类被映射到NODES表。

出于性能目的,我不想每次访问数据库时都加载LOB列。我知道两种方法可以做到这一点:

  • 延迟加载的属性
  • 单独的实体类(该概念取自here

仅从数据库加载数据时,延迟加载的属性很好。但是,如果您必须保存实体,那么如果您忘记事先获取延迟加载的属性,则可能会丢失数据。

所以我选择了第二种方法。

我创建了单独的小型NodeEntityLite类,其属性映射到NODES表的非LOB列。我修改了NodeEntity类,使其继承自NodeEntityLite类。我更改了类的映射,并使用union-subclass进行继承。

public class NodeEntityLite {
  public virtual long Id { get; set; }
  public virtual string Code { get; set; }
}
public class NodeEntity : NodeEntityLite {
  public virtual string NOTE { get; set; } // type:clob
}

NodeEntityLite类的FluentNHibernate映射为

public void Override(AutoMapping<NodeEntityLite> mapping) {
    mapping.Table("NODES");
    mapping.UseUnionSubclassForInheritanceMapping();
}

NodeEntity类的FluentNHibernate映射为

public void Override(AutoMapping<NodeEntity> mapping) {
    mapping.Table("NODES");
    mapping.Map(e => e.NOTE).CustomType("StringClob").CustomSqlType("NCLOB");
}

我希望当我执行select n from NodeEntityLite n where n.Id = :p0 HQL时,NHibernate会生成没有NOTE列的SQL命令:

select nodeentity0_.ID as id1_87_, 
       nodeentity0_.CODE as code2_87_
    from from NODES nodeentity0_ 
    where nodeentity0_.ID=:p0;

但是NHibernate生成完全不同的SQL命令(没有按我期望的那样跳过NOTE列):

select nodeentity0_.ID as id1_87_, 
       nodeentity0_.CODE as code2_87_, 
       nodeentity0_.NOTE as note14_87_, 
       nodeentity0_.clazz_ as clazz_ 
    from ( select ID, CODE, NOTE, 1 as clazz_ from NODES ) nodeentity0_ 
    where nodeentity0_.ID=:p0;

我试图更改继承并使用其他映射,但没有成功。

问题是:我可以将几个类映射到NHibernate中的同一表以访问不同的列吗?

如果是,请举个例子。


解决方案(基于David Osborne和mxmissile的建议)是不使用继承。我使用通用接口实现而不是类继承。工作代码如下:

public interface INodeLite {
  long Id { get; set; }
  string Code { get; set; }
}

public class NodeEntityLite : INodeLite {
  public virtual long Id { get; set; }
  public virtual string Code { get; set; }
}

public class NodeEntity : INodeLite {
  public virtual long Id { get; set; }
  public virtual string Code { get; set; }
  public virtual string NOTE { get; set; } // type:clob
}
...
public void Override(AutoMapping<NodeEntityLite> mapping) {
    mapping.Table("NODES");
}
...
public void Override(AutoMapping<NodeEntity> mapping) {
    mapping.Table("NODES");
    mapping.Map(e => e.NOTE).CustomType("StringClob").CustomSqlType("NCLOB");
}

1 个答案:

答案 0 :(得分:0)

无论继承如何,NH都可以将不同类型映射到同一张表。我已经做到了,尽管没有继承。

您应该能够从NodeEntityLite替代中删除这一行并实现它:

mapping.UseUnionSubclassForInheritanceMapping();

如果证明不成功,则可能需要进一步调整自动映射。绝对有可能。