【问题标题】:Creating HSQL create table query from class从类创建 HSQL 创建表查询
【发布时间】:2012-08-26 19:19:01
【问题描述】:

我有一个经常使用的项目,目前正在更新中。有几个地方可以安装这个项目,并且将来不确定在哪里使用哪个版本以及将来可能会更新到哪个版本。不过现在它们都一样。

我的问题源于这样一个事实:hibernate 实体类可能会有很多变化,并且必须很容易更新到新版本,没有任何麻烦,并且不会丢失数据库内容。只需替换 WAR 并启动,它应该会自行迁移。

据我所知,Hibernate 不会更改表,除非 hibernate.hbm2ddl.auto=create,但实际上会丢弃所有数据?

所以现在当 Spring 上下文完全加载时,它会执行一个 bean,该 bean 将通过从 versionX 到 versionY 的所有更改将数据库迁移到当前版本(它之前的版本保存在数据库中),并手动更改表格。

做一些硬编码的 ALTER TABLE 来添加一些列并不麻烦,但是当涉及到添加完整的新表时,不得不写所有这些感觉很愚蠢......

所以我的问题是这样的

  • 有什么办法可以将实体类和方言发送到 Hibernate 在某处编码,然后取回用于创建表的有效 SQL 查询?

  • 更好的是,以某种方式创建一个 SQL 字符串以向表中添加列,方言安全?

我希望这不是一个愚蠢的问题,而且我没有错过 Hibernate 的一些明显的东西......

【问题讨论】:

    标签: java spring hibernate hsqldb


    【解决方案1】:

    也许您应该尝试不同的方法。不要在运行时更新时生成架构,而是“手动”制作一个(尽管可以基于休眠生成的脚本)。

    在数据库中存储一个版本号,并为每个下一个版本创建一个更新脚本。您现在唯一需要做的就是确定数据库当前的版本,然后依次运行必要的更新脚本以将其更新到当前版本。

    为了使其更加健壮,您可以进行单元/集成测试,运行所有可能的数据库更新并检查结果数据库的完整性。

    我将这种方法用于我构建的应用程序,它可以完美运行。此模式的另一个实现示例是 Android。他们的 API 中有升级方法

    http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onUpgrade(android.database.sqlite.SQLiteDatabase, int, int)

    【讨论】:

    • 我想我会将此作为接受的答案。遗憾的是,我觉得给予赏金很奇怪,因为这并不是我问题的真正答案;如果我的问题确实被认为是不可能的,这是我计划依靠的解决方案。但我想这是最符合我自己的不引入额外依赖等的想法的一个。谢谢
    • 说真的,你应该好好看看 Liquibase,尤其是它的 hibernate support...
    • 我做到了;尽管我在阅读文档时对此有所保留。可能只是我阅读得不够透彻,也没有弄清楚如何将它与我的环境很好地结合起来。如果情况发生变化,可能会以修改后的接受度回来。
    【解决方案2】:

    我认为您无法完全自动化此操作。 Hibernate 有 hbm2ddl 工具(可作为 ant 任务或 maven 插件使用)从您的 hibernate 配置中生成所需的 DDL 语句以创建一个空数据库,但我不知道有任何工具可以在两者之间进行自动“差异”版本。在任何情况下,您最好手动仔细地进行 diff,因为只有您足够了解您的对象模型,才能为现有实体的新属性等选择正确的默认值。

    确定差异后,您可以使用liquibase 之类的工具来管理它们并在应用程序启动时处理将更新实际应用到数据库。

    【讨论】:

    • 好的,我认为这是更好的答案。我仍然保留将 liquibase 本身作为依赖项或适合我的 Spring+Hibernate+Annotations,但它在创建硬编码 SQL 查询方面做得很好,我可以将其用于我自己的自定义解决方案。谢谢。
    • 让 Hibernate 自己进行自动更新在简单的情况下效果很好,例如添加新的可为空的列,但它无法应对更复杂的迁移,例如重命名或删除列、更改类型等。想象一下这样一种情况,您要添加一个新列,其值需要根据现有列中的值计算(而不是仅具有适用于所有现有行的静态默认值)。
    • 啊,误解了这个问题,以为这只是从无到有创建一个工作模式。不过,Liquibase 并不是持续模式迁移管理的唯一选择。此外,您使用 XML 而不是 SQL 编写模式迁移也有点奇怪。主页上有一个很好的比较图表,用于另一种选择,flyway:code.google.com/p/flyway
    【解决方案3】:

    你试过了吗

    hibernate.hbm2ddl.auto=update
    

    它保留了所有数据库中的数据,并仅附加您在实体中更改的列和表。

    【讨论】:

      【解决方案4】:

      不要使用 Hibernate 的 ddl。如果您想迁移,它会丢弃您的数据。我建议你看看 Liquibase。 Liquibase 是一个数据库版本控制。它使用变更集工作。每个变更集都可以手动创建,或者您可以让 Liquibase 读取您的 Hibernate 配置并生成一个变更集。

      Liquibase 可以通过 Spring 启动,因此它应该适合您的项目;-)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-08-25
        • 1970-01-01
        • 1970-01-01
        • 2021-08-02
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        相关资源
        最近更新 更多