【问题标题】:NHibernate many-to-one relationship deleting parent onlyNHibernate 多对一关系仅删除父级
【发布时间】:2009-04-29 10:13:32
【问题描述】:

对象ProductSupplier 之间存在多对一关系。我需要能够在不删除属于它的Products 的情况下删除Supplier

这是类的简化版本:

public class Supplier {
    public virtual IList<Product> Products { get; protected set; }
}

public class Product {
    // Product belongs to a Category but Supplier is optional
    public virtual Supplier Supplier { get; set; }
    public virtual Category Category { get; set; }
}

我正在使用 FluentNHibernate,但这里是它产生的映射:

<bag name="Products" cascade="save-update" inverse="true">
      <key column="SupplierID" />
      <one-to-many class="Me.Product, Me, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bag>

<many-to-one name="Supplier" column="SupplierID" />

这会在 Products 表上创建一个外键,因此当我尝试对供应商执行直接删除时,我会收到外键约束错误。我尝试将级联更改为“全部”,希望它可能只会删除关系,但它删除了所有产品及其其他关联对象。

我现在可以看到解决此问题的唯一方法是迭代 Supplier 的 Products 集合并将 Supplier 属性设置为 null。有没有办法通过映射实现这种行为?

【问题讨论】:

  • 数据库是自动生成的,所以没有。
  • 此外,我会有没有关系的虚拟供应商ID 值

标签: nhibernate nhibernate-mapping many-to-one


【解决方案1】:

映射属性仅在实体实际加载时生效,并且在您不通过 HQL 进行查询时生效。例如,如果您指定 Cascade=ALL,如果您使用查询 "delete from Supplier where id=:id" 删除供应商,您可能会遇到相同的 FK 约束失败,因为 hql 不会触发(程序化)级联。

产品似乎是关系的拥有方,这很好。我认为你有两个选择:

  • 在供应商上编写一些方法来遍历所有产品并将产品的供应商设置为空,并在删除任何供应商之前使用此方法
  • 在删除供应商之前,请确保您的 DAO 将产品的供应商设置为 null

例子:

public int Delete(Supplier s) {
    return Session.CreateQuery("udpate Product set Supplier = null where Supplier = :supplier")
        .SetParameter("supplier", s)
        .ExecuteUpdate();
}

【讨论】:

  • 没想到在数据访问层做一个查询,太完美了!
  • 原来你不能在 HQL 中执行 UPDATE 或 DELETE 语句,唯一的方法是使用原始 SQL。在这种情况下,我可以忍受。
  • 你确定吗?我在我的代码中使用删除: svc.getEm().createQuery("delete from UserOperatorEJB").executeUpdate();还要检查此链接:java2s.com/Code/Java/Hibernate/HQLDeleteHQL.htmtwasink.net/blog/2005/04/… 太糟糕了,休眠文档站点已关闭。
  • 我使用的是 NHibernate(.NET 端口),而不是 Hibernate :o) JIRA 中有一个未解决的问题可以从 HIbernate 移植它,但我认为它不会很快发生。
  • 我的错,我认为 NHibernate 是一个关闭的端口。
【解决方案2】:

不要这样做。

您的模型中有一个隐含或明确的断言,即所有产品都有一个供应商。外键用于强制执行此条件。在保留产品的同时删除供应商违反了您的模型,并且可能会导致您的大部分代码(依赖于这一点始终为真)失败。

您可以做的一件事,您已经发现:对于每个具有此供应商的产品,您可以将产品的供应商设置为空。这不会违反你的条件,但相当于说“我们不知道这个产品的供应商是谁”,可能会导致代码失败。

你为什么要这样做?

【讨论】:

  • Product 上的 Supplier 属性是可选的,Product 由 Supplier 以外的其他对象拥有。你有什么建议?加入课程?
猜你喜欢
  • 2011-01-15
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 1970-01-01
  • 1970-01-01
  • 2014-10-15
  • 1970-01-01
相关资源
最近更新 更多