Hibernate向XML数据库写入

3
我们目前有以下任务需要完成,但我很难找到我认为应该存在的东西。
通过Hibernate将数据模型存储在MySQL中。一切工作正常,产品已经发布。
计划未来版本时需要更改数据模型,我们还不知道如何更改以及更改的程度,但我们知道必须相应地更新客户数据库。
这很可能会在未来版本的未来版本中再次发生,这就带来了第一个问题:
1.是否可以通过将现有数据库内容转换为XML文件来解决此问题,基于它们创建的 Hibernate 版本,并更新其内容(例如XSLT),然后使用更新后的 Hibernate 版本重写数据库内容?
我可以看到以下优点:
我们只需为新版本编写一个 XSLT。
即使是自动化的,我们也可以轻松地将此应用于所有客户端。
我们可以通过链接对应的 XSLT 转换来轻松地将数据库内容从版本X转换为版本Y,即使在它们之间有多个版本。
然而,假设采用此方法,实际问题是我们不想编写生成相应XML文件的额外代码。理想情况下,我想使用将其内容存储在 XML 文件中并提供 JDBC 接口的数据库。这里有人知道如何以最小的努力实现吗?
我心中所设想的工作流程如下:
1.使用Hibernate 数据模型的版本X。创建两个数据库连接,一个连接MySQL 数据库,另一个连接 XML 数据库。从第一个数据读取一切内容,并将其转储到后者(这可能需要一些自定义代码)。
2.编写 XSLT,在 XML 数据库的 XML 文件上执行它。
3.使用Hibernate 数据模型的版本Y。创建两个数据库连接,一个连接 MySQL 数据库,另一个连接 XML 数据库。从 XML 中读出所有内容,并将其转储回 MySQL。
可行吗?是否有更好的方法来解决这个问题?在哪里可以找到支持 JDBC 的 XML 数据库?
3个回答

1

我认为XML数据库(如eXist)实现JDBC没有任何意义,因为JDBC直接基于处理SQL和关系模型。此外,我不确定XML的计划好处是什么; XSLT是XML内容的ok转换语言。但在这种情况下,您最多拥有关系数据的XML包装,而不是树形深度嵌套的文本数据。

因此,您最好只编写Java代码逐行进行更改。这是一种相当常见的做法。

当然,您可以使用XML或JSON作为中间存储/缓冲格式,即处理导入和导出。但是,在中间处理过程中,并不一定从XSLT或临时数据库中受益。


我特别寻找一种良好扩展的方法。当连续发生几个版本后,您如何处理此问题?链式使用XSLT非常容易,但是不同Java程序使用相同库的不同版本...我不认为那会很顺畅? - Frank
通常情况下,新的转换只是我见过的情况下的附加类 -- 或者甚至只是一个包含各种switch语句的巨大文件。虽然不太优雅,但根据更改量的不同还是可以实现的。从那个角度来看,我可以理解为什么一组XSLT会看起来是一个不错的选择。 - StaxMan

1
一个简单的解决方案可以是执行 mysqldump --xml ( http://dev.mysql.com/doc/refman/5.1/en/mysqldump.html#option_mysqldump_xml ),它会生成如下数据:
<mysqldump xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<database name="world">
  <table_data name="City">
    <row>
      <field name="ID">1</field>
      <field name="Name">Kabul</field>
      <field name="CountryCode">AFG</field>
      <field name="District">Kabol</field>
      <field name="Population">1780000</field>
    </row>

然后,您可以使用“LOAD XML INFILE” http://dev.mysql.com/doc/refman/5.5/en/load-xml.html 将数据转换并再次逐个表加载。

作为替代方案,我听说一些同事在使用数据库重构工具Liquibase时取得了不错的结果。这使您能够使用重构命令以描述性方式脚本化数据库迁移,如http://www.liquibase.org/manual/refactoring_commands中所列出的。

例如:

  <databaseChangeLog>
  <changeSet id="1" author="greyfairer>  
  <addLookupTable
        existingTableName="address" existingColumnName="state"
        newTableName="state" newColumnName="abbreviation"
        constraintName="fk_address_state"
    />

Liquibase还在专用的changeset表中跟踪所有已应用的变更集。因此,如果您在产品的第2版中应用了changesets 2a和2b,以及第3版的3a和3b,然后从第1版升级,则Liquibase可以检测到例如,它们全部需要应用,仅需要3a和3b用于第2版,因为2a和2b已经在changeset表中。

诚然,这些解决方案不反映您的领域模型,但有时在进行此类迁移时,使用数据库术语比使用领域术语更容易。


谢谢。这基本上就是我想要的。虽然还不完全符合,但肯定值得进一步追求。 - Frank

0

更好的方法是不使用Hibernate,我个人认为。

我们曾经使用nHibernate和SqlServer解决了这个问题,所以你的解决方案可能会有所不同,但我相信相关工具可以应用来实现相同的目标。

要从R1升级到R1.1,我们将使用nHibernate映射文件将新模式生成到一个空的“build”数据库中(例如db1.1)。然后,我们将复制当前版本(db1.0)并使用数据库模式工具(我们使用DbGhost)将db1.0升级到db1.1。

DbGhost(和其他类似的工具)将自动添加非空添加和新表,并为每组批量更改提供自定义SQL的注入点。

它运行得很完美,在我们的多开发者、多环境中也很好用。真正的好处是,对于最终发布,DbGhost调用可以更改为生成一个单一的升级脚本,总结所有的更改。

希望这能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接