将两个 类 映射到相同的 table
Map two classes to the same table
遗留数据库中有一个 NODES table,其中包含许多 'small' 列和一个 LOB 列。 NodeEntity class 映射到 NODES table.
出于性能目的,我不想在每次访问数据库时都加载 LOB 列。我知道实现此目的的两种方法:
- 延迟加载的属性
- 独立实体class(思路取自here)
仅从数据库加载数据时,延迟加载属性非常有用。但是,如果您必须保存实体,那么如果您忘记事先获取延迟加载的属性,则存在丢失数据的风险。
所以我选择了第二种方式
我创建了单独的小型 NodeEntityLite class,其属性映射到 NODES table 的非 LOB 列。我修改了 NodeEntity class,因此它继承自 NodeEntityLite class。我更改了 classes 的映射并使用 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 class 的 FluentNHibernate 映射是
public void Override(AutoMapping<NodeEntityLite> mapping) {
mapping.Table("NODES");
mapping.UseUnionSubclassForInheritanceMapping();
}
NodeEntity class 的 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 会生成 SQL 没有 NOTE 列的命令:
select nodeentity0_.ID as id1_87_,
nodeentity0_.CODE as code2_87_
from from NODES nodeentity0_
where nodeentity0_.ID=:p0;
但是 NHibernate 生成完全不同的 SQL 命令(注意列没有像我预期的那样被跳过):
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;
我尝试更改继承并使用其他映射但没有成功。
问题是:我可以将多个 class 映射到 NHibernate 中的相同 table 以访问不同的列吗?
如果是,请举例说明。
解决方案(基于 David Osborne 和 mxmissile 的建议)是不使用继承。我使用通用接口实现而不是 class 继承。工作代码如下:
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");
}
不考虑继承,NH 可以将不同的类型映射到相同的table。我做到了,虽然没有继承。
您应该能够从 NodeEntityLite
覆盖中删除这一行并实现它:
mapping.UseUnionSubclassForInheritanceMapping();
如果证明不成功,您可能需要进一步调整自动映射。不过绝对有可能。
遗留数据库中有一个 NODES table,其中包含许多 'small' 列和一个 LOB 列。 NodeEntity class 映射到 NODES table.
出于性能目的,我不想在每次访问数据库时都加载 LOB 列。我知道实现此目的的两种方法:
- 延迟加载的属性
- 独立实体class(思路取自here)
仅从数据库加载数据时,延迟加载属性非常有用。但是,如果您必须保存实体,那么如果您忘记事先获取延迟加载的属性,则存在丢失数据的风险。
所以我选择了第二种方式
我创建了单独的小型 NodeEntityLite class,其属性映射到 NODES table 的非 LOB 列。我修改了 NodeEntity class,因此它继承自 NodeEntityLite class。我更改了 classes 的映射并使用 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 class 的 FluentNHibernate 映射是
public void Override(AutoMapping<NodeEntityLite> mapping) {
mapping.Table("NODES");
mapping.UseUnionSubclassForInheritanceMapping();
}
NodeEntity class 的 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 会生成 SQL 没有 NOTE 列的命令:
select nodeentity0_.ID as id1_87_,
nodeentity0_.CODE as code2_87_
from from NODES nodeentity0_
where nodeentity0_.ID=:p0;
但是 NHibernate 生成完全不同的 SQL 命令(注意列没有像我预期的那样被跳过):
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;
我尝试更改继承并使用其他映射但没有成功。
问题是:我可以将多个 class 映射到 NHibernate 中的相同 table 以访问不同的列吗?
如果是,请举例说明。
解决方案(基于 David Osborne 和 mxmissile 的建议)是不使用继承。我使用通用接口实现而不是 class 继承。工作代码如下:
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");
}
不考虑继承,NH 可以将不同的类型映射到相同的table。我做到了,虽然没有继承。
您应该能够从 NodeEntityLite
覆盖中删除这一行并实现它:
mapping.UseUnionSubclassForInheritanceMapping();
如果证明不成功,您可能需要进一步调整自动映射。不过绝对有可能。