NHibernate Definitive Cascade 应用指南

Posted

技术标签:

【中文标题】NHibernate Definitive Cascade 应用指南【英文标题】:NHibernate Definitive Cascade application guide 【发布时间】:2010-01-13 16:35:01 【问题描述】:

是否有任何 Internet 资源对 NHibernate 的所有级联设置有明确的指南,其中包括类结构、HBM 以及每个级联设置对与 NH 的所有关系的操作的含义的示例。

如果有以最正确的方式完成常见关联的示例,例如设置一个您永远不会最终级联删除状态的状态表,或者删除具有 CreatedBy 的对象,这将很有帮助用户属性永远不会以级联方式删除用户等。

【问题讨论】:

【参考方案1】:

以下内容改编自 Java Hibernate 参考 http://docs.jboss.org/hibernate/stable/core/manual/en-US/html/objectstate.html#objectstate-transitive 用于 NHiberate 3.0(即当前的 svn 主干)。

对于 NHibernate Session 的每个基本操作——包括 Persist()、Merge()、SaveOrUpdate()、Delete()、Lock()、Refresh()、Evict()、Replicate()——都有相应的级联风格。级联样式分别命名为persist、merge、save-update、delete、lock、refresh、evict、replication。 Save() 和 Update() 的级联样式是 save-update;对于 SaveAndUpdateCopy() 它是合并;对于 PersistOnFlush() 它是持久的。而remove是delete的别名。

如果您希望一个操作沿关联级联,您必须在映射文档中指出这一点。例如:

<one-to-one name="person" cascade="persist"/>

可以组合层叠样式:

<one-to-one name="person" cascade="persist,delete,lock"/>

您可以使用 cascade="all" 指定所有操作应沿关联级联。默认的 cascade="none" 指定不进行级联操作。

一种特殊的级联样式 delete-orphan 仅适用于一对多关联,并指示应将 Delete() 操作应用于从关联中删除的任何子对象。而 all-delete-orphan 和 all,delete-orphan 是一样的。

建议:

关联上启用级联通常没有意义。 Cascade 通常对 关联很有用。 如果子对象的生命周期受限于父对象的生命周期,则通过指定 cascade="all-delete-orphan" 使其成为生命周期对象。 否则,您可能根本不需要级联。但是,如果您认为您将经常在同一个事务中与父母和孩子一起工作,并且您想节省一些输入,请考虑使用 cascade="persist,merge,save-update"。

使用 cascade="all" 映射关联(单值关联或集合)将关联标记为父/子样式关系,其中父的保存/更新/删除导致保存/更新/删除孩子或孩子。不被父级引用的子级不会被自动删除,除非是用 cascade="delete-orphan" 映射的 关联。父子关系的级联操作的精确语义如下:

如果将父级传递给 Persist(),则所有子级都传递给 Persist() 如果将父级传递给 Merge(),则所有子级都将传递给 Merge() 如果将父级传递给 Save()、Update() 或 SaveOrUpdate(),则所有子级都传递给 SaveOrUpdate() 如果临时或分离的子代被持久父代引用,则将其传递给 SaveOrUpdate() 如果删除父级,则将所有子级传递给 Delete() 如果子项被持久父项取消引用,则不会发生任何特殊情况 - 应用程序应在必要时显式删除子项 - 除非 cascade="delete-orphan",在这种情况下,“孤立”子项将被删除。

【讨论】:

【参考方案2】:

已接受的答案使用 HBM 文件详细说明了这一点。此答案与按代码映射相同。它们几乎相同;只是映射到他们的 HBM 字符串。

文章表格Ayende很好解释:

无 - 不做任何级联,让用户自己处理。 save-update - 保存/更新对象时,检查关联并保存/更新任何需要它的对象(包括保存/更新多对多场景中的关联)。 delete - 删除对象时,删除关联中的所有对象。 delete-orphan - 当对象被删除时,删除关联中的所有对象。除此之外,当一个对象从关联中移除并且不与另一个对象关联(孤立)时,也将其删除。 全部 - 保存/更新/删除对象时,检查关联并保存/更新/删除找到的所有对象。 all-delete-orphan - 保存/更新/删除对象时,检查关联并保存/更新/删除找到的所有对象。除此之外,当一个对象从关联中移除并且不与另一个对象关联(孤立)时,也将其删除。

另外,this 问题解释了Cascade 的一些内部实现。

[Flags]
public enum Cascade

    None = 0,
    Persist = 2,
    Refresh = 4,
    Merge = 8,
    Remove = 16,
    Detach = 32,
    ReAttach = 64,
    DeleteOrphans = 128,
    All = 256,

private static IEnumerable<string> CascadeDefinitions(this Cascade source)

    if (source.Has(Cascade.All))
    
        yield return "all";
    
    if (source.Has(Cascade.Persist))
    
        yield return "save-update, persist";
    
    if (source.Has(Cascade.Refresh))
    
        yield return "refresh";
    
    if (source.Has(Cascade.Merge))
    
        yield return "merge";
    
    if (source.Has(Cascade.Remove))
    
        yield return "delete";
    
    if (source.Has(Cascade.Detach))
    
        yield return "evict";
    
    if (source.Has(Cascade.ReAttach))
    
        yield return "lock";
    
    if (source.Has(Cascade.DeleteOrphans))
    
        yield return "delete-orphan";
    

请注意Cascade.All 不包括Cascade.DeleteOrphans。在这种情况下,您可能需要使用 Cascade.All | Cascade.DeleteOrphans 将其包含在内。

或者,您可以使用Include扩展方法Cascade.All.Include(Cascade.DeleteOrphans)

结合Cascade,您可能还需要查看Inverse;它指定了关联的所有者。更多详情请参考this问题和this答案。

【讨论】:

【参考方案3】:

这可能是显而易见的建议,但我建议浏览 Ayende 的旧帖子。在他的网站上,NHibernate 和 cascade 的快速search 揭示了一些有趣的帖子。但是,对于您的需求,它们可能有点稀缺。

即使它本身不是互联网资源,我也推荐NHibernate in Action。它在第 3、4 和 6 章中深入讨论了级联。本书针对 NHibernate 1.2。不过,我确实相信本书的新版本将针对 NHibernate 3.0 版本。可能值得关注。

尽管我很想看到一份关于级联的权威指南,但我还没有看过。也许您可以在您自己的博客上总结一些讨论级联的博客文章。

【讨论】:

不幸的是,我开始相信情况确实如此,但是很高兴在 NHibernate in Action 中了解这一点。我有太多的博客要做,而时间太少了。 我绝对没有找到 Nhibernate 3 的官方文档,其中包含代码映射等。我认为这是 NHibernate 的缺点之一:太复杂以至于没有更新的文档【参考方案4】:

我不知道任何“权威”指南,但我所知道的最佳资源是 Ayende 的博客文章,他是 NHibernate 的权威专家之一:

NHibernate Cascades: the different between all, all-delete-orphans and save-update

对我来说,我实际上只使用cascade="none"cascade="all"all-delete-orphan 有时是一种选择。其他一切都是可疑的。例如,为什么我要隐式创建一个实例,因为它被引用了,而它的寿命比包含对象的寿命长?对我来说,只有两种情况:对象是依赖对象或独立对象。

【讨论】:

以上是关于NHibernate Definitive Cascade 应用指南的主要内容,如果未能解决你的问题,请参考以下文章

THE DEFINITIVE GUIDE TO DEBUGGING JAVASCRIPT

JenkinsJenkins权威指南英文版:jenkins-the-definitive-guide.pdf

The Definitive C++ Book Guide and List

Active FTP vs. Passive FTP, a Definitive Explanation

我正在学习如何从 Spark the Definitive Guide 一书中将 sqlite 连接到 spark

NHibernate之旅系列文章导航