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="all" 映射关联(单值关联或集合)将关联标记为父/子样式关系,其中父的保存/更新/删除导致保存/更新/删除孩子或孩子。不被父级引用的子级不会被自动删除,除非是用 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