使用未映射的列映射复合键
Posted
技术标签:
【中文标题】使用未映射的列映射复合键【英文标题】:Map composite key with unmapped column 【发布时间】:2011-12-13 16:32:04 【问题描述】:如果复合键的一部分未映射到我的实体中,我该如何映射它?
例子:
我有一个表 ITEMDELIVERY
包含列:
ITEMDELIVERY_ID
(PK)
DELIVERY_DATE
(PK)
我有一个表 ITEMDELIVERYDETAIL
包含列:
ITEMDELIVERYDETAIL_ID
(PK)
ITEMDELIVERY_ID
(FK)
PARTITIONDATE
(PK、FK)
如您所见,两个表中都有一个复合键,ITEMDELIVERYDETAIL
有一个指向ITEMDELIVERY
的“复合”外键。
在我的域模型ItemDeliveryDetail
中不存在可以映射到列PARTITIONDATE
的属性PartitionDate(请参阅here 和here 了解原因)。
但是现在,我如何映射ITEMDELIVERYDETAIL
中的复合键?
我尝试了以下方法,但不起作用:
mapping.CompositeId().KeyProperty(x => x.Id, "ITEMDELIVERYDETAIL_ID")
.KeyProperty(x => x.ItemDelivery.DeliveryDate,
"PARTITIONDATE");
我收到以下错误:
NHibernate.PropertyNotFoundException:在“REM.Domain.NHibernate.ItemDeliveryDetail”类中找不到属性“DeliveryDate”的getter
更新:
我想我找到了解决办法:
-
从
ItemDeliveryDetail
的映射中删除对ItemDelivery
的引用:mapping.References(x => x.ItemDelivery);.Columns("ITEMDELIVERY_ID", "PARTITIONDATE");
将复合键的声明改为:
mapping.CompositeId().KeyProperty(x => x.Id, "ITEMDELIVERYDETAIL_ID")
.KeyReference(x => x.ItemDelivery, "ITEMDELIVERY_ID",
"PARTITIONDATE");
这具有保存ItemDeliveryDetail
不能级联保存ItemDelivery
的副作用。需要提前保存。
但是,我想知道一件事:这会创建一个包含三列的 PK 吗?如果是这样,如何避免它并且只为需要的两列创建一个PK?
【问题讨论】:
【参考方案1】:看起来您有一个遗留数据库,并且永远不会使用 SchemaExport 生成它,因此 NH 认为它有 3 个或 1 个 PK 列并不重要。
在查看您的问题Composite key with sequence 之后,如果您的 ID 是唯一的,那么最好
mapping.Id(x => x.Id).GeneratedBy.SequenceIdentity("SQ_TRANSFORM_ITEMDEL_IDDID");
mapping.Reference(x => x.ItemDelivery).Columns("ITEMDELIVERY_ID", "PARTITIONDATE");
即使在数据库中,PK 跨越两列
更新:您的发票示例中的棘手问题。在联接中有第二列(作为查询优化器应添加到联接的位置)有一个技巧
HasManyToMany(u => u.ItemDeliveryDetails)
.Table("INVOICEITEM_IDD")
.ChildWhere("PARTITIONDATE = nhGeneratedAliasForINVOICEITEM_IDD.PARTITIONDATE");
【讨论】:
您对遗留数据库的假设是正确的。但是,将用于持久性规范测试的测试数据库应该通过模式导出来创建,以确保干净可靠的测试环境。 我有相同的场景,一个遗留数据库和映射的单元测试。但是我不使用 SchemaExport,因为它可能会掩盖映射错误。我将生产数据库的架构导出到一个 sqlscript 中,我在创建 sessionfactory 后立即执行。 好点。不过,我需要正确映射还有另一个原因:有些表有一个指向ITEMDELIVERYDETAIL
的外键。为确保生成的连接尽可能快,此外键还需要使用两列。如果我使用您的答案,这将不起作用,因为 ITEMDELIVERYDETAIL
仅使用一个 ID 进行映射...
如果只加入索引 (pk) 的一列,您确定在 oracle 中性能会下降那么多吗?我想不出一种方法来模拟映射中的 db 模式而不会遇到很多麻烦
是的。这就是我们在创建该数据库时引入该列和分区的全部目的。这是一个相当大的表,有 3000 万个条目……只是一些数字:单行没有分区日期的连接需要 11 秒。与分区日期的连接是即时的。以上是关于使用未映射的列映射复合键的主要内容,如果未能解决你的问题,请参考以下文章
如何进行 Hibernate XML 映射,一对多使用 1 PK 映射到另一个具有复合键的实体