我正在尝试围绕现有的数据模型包装Hibernate,正如预期的那样,它有起伏不定。
我目前的关键点是其中一个实体表具有准时间模型;没有行被删除或更新;相反,“is_current”列设置为false(并且在更新时使用不同的主键创建新行,其中包含新字段。)
对于Hibernate相对较新我正在努力解决这个问题,甚至确定它是否可行。好吧,删除很简单,使用自定义@SQLDelete
注释,但这些更新似乎很棘手。从理论上讲,这似乎可能是一件非常简单的事情(在元代码中,@SQLUpdate(sql = @SQLDelete + "; " + @SQLInsert)
)但是有明显的复杂性(除了这个语法不存在的事实) ,部分原因是主键需要在两个语句之间无效并在第二个语句中更新,我确信还有其他数据一致性问题,我还没有考虑过。
有没有一种现实的方法来管理它,即模型更新为Hibernate中的delete + insert?
编辑:只是为了澄清,我知道我可以通过显式指定插入SQL,然后使用上面的代码片段(带有对SQL常量的合法引用)以暴力方式工作更新。但是,我真的不想这样做,因为我很满意SQL Hibernate选择默认为插入生成,如果类完全改变,手写这个就会非常脆弱。这是迫使这个通过的最后一个解决方案,但如果我必须手工编写SQL,它似乎有点破坏ORM映射器的重点...DOUBLE EDIT:即使以上情况也可能无法正常工作,因为我需要在SQL中指定两次主键绑定参数(不可能带问号),和我无法说服Hibernate给我一个来自SequenceGenerator的新的。所以看起来我需要一个程序化方法,而不是一个配置方法 - 除非我错过了一些特别相关的配置元素。
答案 0 :(得分:1)
您说没有更新行,但听起来您正在更新该行上的is_current列。我会使用Hibernate做同样的事情(更新行的isCurrent字段,然后创建一个新行),而不是尝试编写实际上是更新的自定义删除函数。
row1.setCurrent(false);
session.saveOrUpdate(row1);
row2 = new Row(row1); //Copy constructor; use a different primary key (or your default primary key for a new object)
row2.setCurrent(true);
row2.setFoo("bar"); //whatever data updates you are doing for the new row
session.saveOrUpdate(row2);
您可以将此过程包装在某些中间层/业务逻辑代码中,以确保不会更新其他字段。
答案 1 :(得分:1)
我们有一个与Hibernate一起使用的完全时态星型模式。但是,Hibernate永远不会知道审计或事实表,只知道表的视图。这允许我们像往常一样使用Hibernate,因此当Hibernate在db中的视图上发出插入,删除或更新时,“而不是”触发器会针对这些相应的任务触发。
所以在你的情况下创建一个视图(Hibernate不知道更好,完全透明)和触发器,以适当设置你的标志和其他任何东西。实际上我很惊讶我们如何以相对较小的痛苦逃脱这一点 - 而且我们的设计确实可以更好,因为使用Hibernate是事后补充/添加。
答案 2 :(得分:0)
进一步研究后,我相信没有一种简单的方法可以做到这一点。我试图尝试的一种方法是将原始表隐藏在可更新视图后面,这样Hibernate可以呈现出看起来很健全的东西,而视图上的触发器将简单的CRUD操作映射到基础表中所需的操作序列
但是,我怀疑这可能效果不好,因为我相信Hibernate在任何时候都会维护自己对数据库内容的概念;例如如果我删除一个实体,Hibernate的缓存会认为表中不再存在物理行(虽然它确实存在但is_current现在为false)。如果这种不匹配可能导致最坏情况下的数据一致性问题,或者批量优化效率低下,我不会感到惊讶。
无论如何现有的表格都很糟糕,所以在这种变化的背景下让它们更加健全是我要采取的方法。至少这个评估阶段使现有模型的一些缺陷更加清晰。