为基于Hibernate的应用程序实现数据历史/版本控制解决方案(带有扭曲)

时间:2009-12-22 10:14:46

标签: java mysql hibernate versioning datahistory

首先是基本事实:Java webapp,Spring,Hibernate,MySQL。

情况是我有一个复杂的对象模型,例如: 汽车。它的 由许多物体(发动机,轮胎......)组成,它们之间具有多对一和一对多的关系。

现在有很多车,不时有人检查汽车并创建一个报告的检查。报告指的是汽车的许多部件,显示其属性等。

到目前为止,系统尚未支持在车辆进入系统后更新汽车及其零件属性的能力。这意味着如果底盘颜色或轮胎数量发生变化,旧报告将反映出这种变化,这不是我们想要的。

嗯,现在已经请求了这个功能。汽车及其零件需要可修改,并且必须创建版本历史记录。旧报告需要参考旧版本的零件及其值。

我一直在看“Slowly changing dimensions”,似乎可以使用Type 6方法完成汽车及其零件的版本控制。

我遇到麻烦(可能是由于我有限的Hibernate经验)的事情(扭曲)是这样的:

如何使用Hibernate组合我的报告实例,以便他们参考汽车每个部分的正确版本?报告有一个日期,每个版本的汽车零件都有日期范围当它们是有效的,所以我想我可以用一些复杂的HQL / SQL做到这一点。 但使用Hibernate有没有更简单,更自动的方式?

3 个答案:

答案 0 :(得分:6)

您可以查看JBoss envers对对象进行版本控制。我不确定它是否适合您的用例,但请看一下。

答案 1 :(得分:1)

MySQL支持triggers。设置触发器,以便每当更改行时,触发器将行复制到“存档”表中,并附带时间戳。这样,所有以前的数据版本都会得到维护,报告可以针对这些版本运行。

答案 2 :(得分:1)

我已经使用了你建议的方法(类型6)和Hibernate,它对我来说很好。对报告的查询确实变得有点复杂但不是那么多,因为所有查询都需要相同的子句(例如'和:reportTime> = x.startTime和(:reportTime< x.endTime或x.endTime)一片空白)')。

我为支持这种方法的实体创建了一个接口和一个基类(对于父级不是时间的临时子类,只需要接口)(如startTime和endTime),以及使用DAO的基类通常需要一些功能的时间实体。我在这个基础DAO中提出的事情:

  1. 防止更改已经过startTime的实例(除了将endTime设置为将来的时间)
  2. 如果添加了新实例,则自动关闭(即填充endTime)前一个实例(例如oldInstance.endTime = newInstance.startTime)
  3. 添加标准子句以在查询HQL查询时选择当前实体。
  4. 如果由于某种原因在某个时刻发现了两个有效的实例/版本(我通过'startTime desc'命令我的查询并且只返回了第一个),则处理重复项。
  5. 我发现它非常混乱的唯一部分是使用针对数据库运行的普通SQL查询,其中在连接表或子选择中需要额外的子句。