5

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

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

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

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

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

所以我的问题是

  • 有没有办法将实体类和方言发送到某个地方的 Hibernate 代码,并取回用于创建表的有效 SQL 查询?

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

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

4

4 回答 4

4

have you tried

hibernate.hbm2ddl.auto=update

it retains all the database with the data and append only columns and tables you have changed in entity.

于 2012-09-04T08:56:18.190 回答
2

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

一旦你计算出你的差异,你就可以使用像liquibase这样的工具来管理它们,并在应用程序启动时处理将更新实际应用到数据库。

于 2012-09-04T08:34:14.773 回答
2

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

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

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

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

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

于 2012-09-04T08:12:45.200 回答
2

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

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

于 2012-09-04T09:09:44.897 回答