【问题标题】:Liquibase not picking up seed data with Spring BootLiquibase 没有使用 Spring Boot 获取种子数据
【发布时间】:2015-05-11 22:09:14
【问题描述】:

我正在使用 Spring-Boot 1.2.1 和 Liquibase 创建 H2(测试)和 PostgreSQL(QA 和生产)数据库。我有几个表要在创建数据库时播种。但是,尽管尝试了 dataLoad 和 sqlFile,但没有插入任何内容。我的 sql 文件只是一堆插入语句,例如:

INSERT INTO state (Name, Code) VALUES('Alabama','AL');
INSERT INTO state (Name, Code) VALUES('Alaska','AK');

这是我相关的 changelog-master.xml:

    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.3.xsd"
    objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS">

...
<changeSet id="3" author="me">
        <createTable tableName="STATE">
            <column name="code" type="VARCHAR(10)">
                <constraints primaryKey="true"/>
            </column>
            <column name="name" type="VARCHAR(100)"/>
        </createTable>

         <sqlFile dbms="h2, PostgreSQL"
                 encoding="utf8"
                 endDelimiter="\nGO"
                 path="src/main/resources/db/changelog/data/states.sql"
                 relativeToChangelogFile="true"
                 splitStatements="true"
                 stripComments="true"/>
    </changeSet>

这是我的项目结构:

当我启动我的 spring-boot 应用程序时,我可以看到 State 表已创建,但其中有零行。我还尝试从变更集 3 中取出并使用它:

  <changeSet id="4" author="me">
            <loadData file="data/state.csv" tablename="STATE" schemaName="edentalmanager" relativeToChangelogFile="true">
            <column name="name" type="VARCHAR(100)"/>
            <column name="code" type="VARCHAR(10)"/>
            </loadData>
        </changeSet>

csv文件基本上是:

Alabama,AL
Alaska,AK
...

我在控制台日志中没有看到 Liquibase 正在尝试创建数据或将数据插入表中的任何消息。我也没有收到任何异常或错误消息。

更新: 如果我将 state.sql 复制为 /resources/data.sql 然后 spring-boot 会拿起文件并执行 sql 就好了。不幸的是,这意味着每次我启动时,它都会尝试再次插入这些值,从而导致启动异常(重复键违规)但是,与其依赖单个文件,我更希望 Liquibase 将它们作为变更集的一部分作为数据执行需要改变。

【问题讨论】:

  • 没有其他人有这个文件没有被 Liquibase 加载的问题吗?
  • 当您将应用程序打包到 JAR/WAR 时,path src/main/resources/db/changelog/data/states.sql 无法工作。理想情况下,如果 liquibase 可以从类路径读取文件但在文档中找不到它

标签: spring-boot liquibase


【解决方案1】:

我从 2.2.0-RELEASE 版本升级到 spring boot 2.4.1 时遇到了这个问题。 2.2.0-RELEASE 版本将 liquibase-core:jar:3.8.0 作为依赖项,它准确地采用了 relativeToChangelogFile="true"。但是2.4.1 版本有liquibase-core:jar:3.10.3 版本,它破坏了loadData 功能。

我正在加载的 csv 文件和 changelog.xml 文件在我的情况下位于同一类目录中 src/main/resources/liquibase/version2/changelog.xmlsrc/main/resources/liquibase/version2/xref_specialty_codes.csv

这是我的changelog.xml 的 sn-p,用于加载不适用于更高版本的 liquibase 的数据

<changeSet author="anon"
               id="xref_specialty_codes_load_data"
               objectQuotingStrategy="LEGACY">
        <loadData catalogName="adb"
                  schemaName="public"
                  encoding="UTF-8"
                  file="xref_specialty_codes.csv"
                  relativeToChangelogFile="true"
                  separator=","
                  tableName="xref_specialty_codes"
                  usePreparedStatements="true">
            <column name="id" type="NUMERIC"/>
            ...
            ....
        </loadData>
    </changeSet>

我使用以下布局加载了更改日志文件的层次结构,其中顶部位于 src/main/resources/liquibase/changelog.xml

<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
    <property name="now" value="now()" dbms="postgresql"/>
    <include file="src/main/resources/liquibase/version1/changelog.xml" />
    <include file="src/main/resources/liquibase/version2/changelog.xml" />
    ....
</databaseChangeLog>

【讨论】:

  • 我在将 Spring Boot 升级到 2.4.3 后遇到了同样的问题。你现在解决了吗?
  • 当时我降级到旧版本。使用最新的 spring 2.5.x 版本,我看不到这个问题。
【解决方案2】:

这是因为默认情况下,Hibernate 在初始化时会丢弃架构。所以首先 Liquibase 创建数据,完成后 Hibernate 删除表并根据您定义的 JPA 实体重新创建它们。

您可以通过查找日志记录来验证这一点:

2017-01-19 11:03:48.692  INFO 15161 --- [           main] org.hibernate.tool.hbm2ddl.SchemaExport  : HHH000227: Running hbm2ddl schema export

您可以通过设置此应用程序属性来告诉 Hibernate 不要对 DB 模式执行任何操作:

spring.jpa.hibernate.ddl-auto=none

【讨论】:

    【解决方案3】:

    我认为您的变更集 3 中有两个问题:

    1. path 属性的值指向不存在的资源。当您定义relativeToChangelogFile="true" 时,Liquibase 将寻找classpath:/db/changelog/src/main/resources/.../states.sql。正确的路径应该是path="../data/states.sql"
    2. 如果给定的路径不正确,Liquibase 应该抛出异常。如果你没有得到一个意味着 Liquibase 由于其他条件决定不执行该部分。这些条件之一可能是dbms 属性。您的变更集应该适用于 H2 数据库。由于type name 错误,它不应该与 PostgreSQL 数据库一起使用。请改用dbms="h2, postgresql"

    在这些更改之后,我得到了一个基于您的项目结构的填充表。

    【讨论】:

    • 我做了这两个更改,但仍然没有任何反应。如果找不到文件,我认为 Liquibase 会抛出异常,但什么也没有。我尝试在此目录位置以及 resources/ 中使用我的 states.sql 文件(并且我更改了路径)。我在嵌入式 Tomcat 中运行它,所以我想知道是否有办法告诉 Liquibase 只使用类路径?
    • 您真的需要dbms 属性吗?如果删除它会发生什么?
    • 相同的行为。奇怪的是,日志中没有任何异常、消息或输出。你知道如何打开 Liquibase 的调试吗?我试过“logging.level.org.springframework.boot.liquibase.:DEBUG”,但这似乎也不正确
    • 很奇怪...日志记录的属性是logging.level.liquibase。如果您在变更集中添加 2 个额外的插入,会发生什么情况:一个在 createTable 和 sqlFile 之间,第二个在 sqlFile 之后?您应该至少获得两条额外的日志消息(“新行插入...”)。
    • 您是否将 liquibase-core 作为依赖项添加到您的项目中?
    猜你喜欢
    • 1970-01-01
    • 2018-01-20
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 2020-06-21
    相关资源
    最近更新 更多