【问题标题】:grails 3 database migrationsgrails 3 数据库迁移
【发布时间】:2017-01-08 03:36:18
【问题描述】:

我将我的应用程序更新到了 grails 3.1.9,但我在使用数据库迁移插件时遇到了问题。

我的生产应用程序.yml 如下所示:

   production:
        dataSource:
                driverClassName: org.postgresql.Driver
                dialect: org.hibernate.dialect.PostgreSQLDialect
                dbCreate: none
                url: jdbc:postgresql://localhost:5432/something
                username: postgres
                password: postgres
                properties:

我的 build.gradle 看起来像这样:

buildscript {
 dependencies {
        classpath 'org.grails.plugins:database-migration:2.0.0.RC4'
    }
}

    dependencies {
        compile 'org.liquibase:liquibase-core:3.4.1'
        compile 'org.grails.plugins:database-migration:2.0.0.RC4'
    }

这是更新日志的开头:

databaseChangeLog = {

    changeSet(author: "michal (generated)", id: "1472650791344-1") {
        createTable(tableName: "appointment") {
            column(autoIncrement: "true", name: "id", type: "BIGINT") {
                constraints(primaryKey: "true", primaryKeyName: "appointmentPK")
            }

            column(name: "version", type: "BIGINT")

            column(name: "customer_id", type: "BIGINT")

            column(name: "duration", type: "BLOB(255)")

            column(name: "note", type: "CLOB")

            column(defaultValueComputed: "0", name: "personal_available", type: "BOOLEAN")

            column(defaultValueComputed: "0", name: "personal_booked", type: "BOOLEAN")

            column(name: "provider_id", type: "BIGINT")

            column(name: "start_time", type: "BLOB(255)")

            column(name: "url", type: "VARCHAR(255)")
        }
    }

当我在生产模式下运行我的应用时,我收到了这个错误。

SEVERE 8/31/16 3:41 PM: liquibase: changelog.groovy: changelog.groovy::1472650791344-1::michal (generated): Change Set changelog.groovy::1472650791344-1::michal (generated) failed.  Error: ERROR: relation "appointment" already exists [Failed SQL: CREATE TABLE public.appointment (id BIGSERIAL NOT NULL, version BIGINT, customer_id BIGINT, duration BYTEA, note TEXT, personal_available BOOLEAN DEFAULT 0, personal_booked BOOLEAN DEFAULT 0, provider_id BIGINT, start_time BYTEA, url VARCHAR(255), CONSTRAINT "appointmentPK" PRIMARY KEY (id))]
liquibase.exception.DatabaseException: ERROR: relation "appointment" already exists [Failed SQL: CREATE TABLE public.appointment (id BIGSERIAL NOT NULL, version BIGINT, customer_id BIGINT, duration BYTEA, note TEXT, personal_available BOOLEAN DEFAULT 0, personal_booked BOOLEAN DEFAULT 0, provider_id BIGINT, start_time BYTEA, url VARCHAR(255), CONSTRAINT "appointmentPK" PRIMARY KEY (id))]
    at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:316)

...

Caused by: org.postgresql.util.PSQLException: ERROR: relation "appointment" already exists

我会感激任何想法,为什么它不起作用。


谢谢格雷戈尔·佩特金。将 dbcreate 设置为 validate 确实帮助我修复了这个错误。

【问题讨论】:

  • 如果您将dbCreate 明确设置为validate 而不是none,是否有帮助?
  • @Gregor Petrin 嗨,它似乎有帮助。查看我的编辑。

标签: grails migration database-migration


【解决方案1】:

该表已经存在似乎很奇怪,但我昨晚在dev 环境中遇到了这样的事情,所以我知道它可能会发生。例如,即使您有dbCreate: none,也可能由于错误而执行了hbm2ddl 迁移工具。检查日志。

或者您的databasechangelog 表可能由于某种原因被意外清除。检查您的 databasechangelog 表中是否存在与该特定变更集对应的行。

您可以为此特定变更集做的一件事是向变更集添加tableExists 前置条件,如果表已存在,则使用onFail="MARK_RAN" 将变更集标记为EXECUTED。 Liquibase 的作者曾经写道,由于性能问题,应谨慎使用前置条件。因此,如果您发现自己为每个变更集创建了前提条件,您可能需要重新考虑。

关于这一点,如果您收到更多变更集的此错误,您可能需要使用dbm-changelog-sync (http://grails-plugins.github.io/grails-database-migration/1.4.0/ref/Maintenance%20Scripts/dbm-changelog-sync.html) 将所有变更集标记为“已执行”,本质上是告诉 Liquibase 在这些变更集中在随后重新启动时忽略它们服务器。

如果有一些你真正想要执行的变更集(而不是忽略)——例如,你最近做了一些更改——那么你可以使用上下文标记“to-be-ignored”变更集并然后将这些值作为context 参数运行dbm-changelog-sync 命令。

有关详细信息,请参阅以下链接。 * http://grails-plugins.github.io/grails-database-migration/1.4.0/ref/Maintenance%20Scripts/dbm-changelog-sync.html * http://www.liquibase.org/2014/11/contexts-vs-labels.html

【讨论】:

    【解决方案2】:

    问题是您的dbCreate 子句和一个非常不方便的行为更改导致无效的dbCreate 值被忽略。如果您不希望 Hibernate 弄乱您的数据库并干扰数据库迁移,请使用 dbCreate: validate

    插件可以为 Grails 应用程序贡献值,因此它们可以提供合理的默认值,并且它从头开始工作:首先一个接一个地出现插件,然后最后 application.yml 有机会覆盖他们设置的任何内容.为了便于开发和测试,插件也是独立的 Grails 应用程序,因此其中许多都将具有 dbCreate 集。

    发生的不方便的变化是,现在无效的dbCreate 选项将被忽略,然后覆盖最新的随机选择的插件留下的值,以便有机会为配置(该插件也可以使用create-drop,即使在开发环境中也可能非常不方便——事实上,较新的 Grails 版本将忽略插件中的dbCreate 设置,因为当前的行为非常危险)。

    所以现在当数据库迁移运行时,Hibernate 已经使用updatecreate-drop 设置来创建您的表,因此数据库迁移失败。将值配置为 validate 应该可以有效替代覆盖插件设置的任何内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-25
      • 2011-05-22
      • 2011-01-07
      • 2012-01-15
      • 2016-05-10
      • 2017-05-26
      • 1970-01-01
      相关资源
      最近更新 更多