我正在try 使用Liquibase将大量记录(当前位于Excel文件中)添加到我的数据库中(这样我就知道如何在future 的数据库更改中这样做)

我的 idea 是使用Java读取excel文件,然后从Spring初始化类中填充ChangeLogParameters,如下所示:

SpringLiquibase liqui = new SpringLiquibase();
liqui.setBeanName("liquibaseBean");
liqui.setDataSource(dataSource());
liqui.setChangeLog("classpath:changelog.xml");

HashMap<String, String> values = new HashMap<String, String>();
values.put("line1col1", ExcelValue1);
values.put("line1col2", ExcelValue2);
values.put("line1col3", ExcelValue3);
values.put("line2col1", ExcelValue4);
values.put("line2col2", ExcelValue5);
values.put("line2col3", ExcelValue6);
...
liqui.setChangeLogParameters(values);

这种方法的问题是,我的changelog.xml将非常奇怪(并且没有生产力)

<changeSet author="gcardoso" id="2012082707">
    <insert tableName="t_user">
        <column name="login" value="${ExcelValue1}"/>
        <column name="name" value="${ExcelValue2}}"/>
        <column name="password" value="${ExcelValue3}"/>
    </insert>
    <insert tableName="t_user">
        <column name="login" value="${ExcelValue4}"/>
        <column name="name" value="${ExcelValue5}}"/>
        <column name="password" value="${ExcelValue6}"/>
    </insert>
    ...
</changeSet>

有没有办法让我做这样的事:

HashMap<String, ArrayList<String>> values = new HashMap<String, ArrayList<String>>();
values.put("col1", Column1);
values.put("col2", Column2);
values.put("col3", Column3);
liqui.setChangeLogParameters(values);

<changeSet author="gcardoso" id="2012082707">
    <insert tableName="t_user">
        <column name="login" value="${Column1}"/>
        <column name="name" value="${Column2}}"/>
        <column name="password" value="${Column3}"/>
    </insert>
</changeSet>

或者还有别的办法吗?

EDIT :个 我当前的 Select 是将Excel转换为CSV文件,然后使用

<changeSet author="gcardoso" id="InitialImport2" runOnChange="true">

    <loadData tableName="T_ENTITY" file="com/exictos/dbUpdate/实体csv">
        <column header="SHORTNAME" name="SHORTNAME" />
        <column header="DESCRIPTION" name="DESCRIPTION" />
    </loadData>


    <loadData tableName="T_CLIENT" file="com/exictos/dbUpdate/client.csv">
        <column header="fdbhdf" name="ENTITYID" defaultValueComputed="(SELECT ID FROM T_ENTITY WHERE SHORTNAME = ENTITY_REFERENCE"/>
        <column header="DESCRIPTION" name="DESCRIPTION" />
    </loadData>


</changeSet>

使用这些CSV文件:

实体csv

SHORTNAME,DESCRIPTION
nome1,descricao1
nome2,descricao2

client.csv

DESCRIPTION,ENTITY_REFERENCE
descricaoCliente1,nome1
descricaoCliente2,nome2

但是我得到了这个错误:

liquibase.exception.DatabaseException: Error executing SQL INSERT INTO `T_CLIENT` (`DESCRIPTION`, `ENTITY_REFERENCE`) VALUES ('descricaoCliente1', 'nome1'): Unknown column 'ENTITY_REFERENCE' in 'field list'

如果我将client.csv的标题更改为Description,ENTITYID,我会收到以下错误:

liquibase.exception.DatabaseException: Error executing SQL INSERT INTO `T_CLIENT` (`DESCRIPTION`, `ENTITYID`) VALUES ('descricaoCliente1', 'nome1'): Incorrect integer value: 'nome1' for column 'entityid' at row 1

在任何一种情况下,defaultValueComputed的工作方式都与下面示例中的valueComputed不同

<changeSet author="gcardoso" id="InitialImport1">

    <insert tableName="T_ENTITY">
        <column name="SHORTNAME">nome1</column>
        <column name="DESCRIPTION">descricao1</column>
    </insert>

    <insert tableName="T_CLIENT">
        <column name="ENTITYID" valueComputed="(SELECT ID FROM T_ENTITY WHERE SHORTNAME = 'nome1')"/>
        <column name="DESCRIPTION">descricaoCliente</column>
    </insert>

</changeSet>

这是预期的行为吗?wine 鬼?或者只是我做错了什么(最有可能)?

或者有没有其他方法可以导入大量数据?但总是使用液化Enzyme 和/或弹簧.

EDIT2 :我的问题是,我无法用正确的外键将数据插入到第二个表中

推荐答案

我想说,Liquibase并不是你想要实现的理想工具.Liquibase非常适合管理数据库 struct ,而不是数据库的数据.

如果您仍然想使用Liquibase来管理数据,您有几个 Select (请参见here)-

  1. 将insert语句记录为SQL,并从changelog中引用它们.xml如下所示:

    <sqlFile path="/path/to/file.sql"/>

  2. 使用您从changelog.xml引用的Custom Refactoring Class,如下所示:

    <customChange class="com.example.YourJavaClass" csvFile="/path/to/file.csv"/>

    您的JavaClass将从CSV文件中读取记录,并将它们应用到数据库,实现此方法:

    void execute(Database database) throws CustomChangeException;

请记住,一旦通过Liquibase加载了这些数据,就不应该修改文件中的数据,因为这些更改不会被重新apply.如果要对其进行更改,则必须在后续的更改集中进行更改.因此,过一段时间后,你可能会得到许多不同的CSV文件/liquibase变更集,所有这些文件都在相同/相似的数据上运行(这取决于你将如何使用这些数据——一旦插入,它会发生变化吗?).

我建议使用DBUnit来管理参考数据.这是一个主要用于单元测试的工具,但它非常成熟,适合在生产中使用.您可以将信息存储在CSV或XML中.我建议使用Spring'InitializingBean'从类路径加载数据集,并执行DBUnit'refresh'操作,从docs开始:

此操作从字面上将数据集内容刷新到数据库中.这 表示更新现有行的数据,并获取不存在的行 已插入.存在于数据库中但不在数据集中的任何行都将保留 不受影响.

通过这种方式,您可以将引用数据保存在一个地方,并随着时间的推移添加到其中,这样就只有一个信息源,而不会在多个Liquibase变更集中拆分.将DBUnit数据集保持在版本控制中可以提供跟踪能力,另外,DBUnit数据集可以跨数据库移植,并可以管理插入顺序等内容,以防止外键冲突.

Database相关问答推荐

1-2400之间格式奇怪的时间数据

您如何使两个相关但独立的系统保持同步?

MongoDB是面向对象的吗?

将 .frm 和 .opt 文件导入 MySQL

类似 Hibernate 的 C++ 框架

Membase 和 Couchbase 有什么区别?

Boyce-Codd 范式的良好 KISS 描述是什么?

数据库设计—应该避免一对一的关系吗?

在 SQL SERVER 中监视 SQL 查询的进度

postgresql 在 where 子句中使用 json 子元素

如何在 MySQL 中强制执行唯一约束?

从 Java 创建 MySQL 数据库

如何在 Postgres 9.6+ 中生成长度为 N 的随机、唯一的字母数字 ID?

MySQL相对于其他数据库的缺点

什么时候用R,什么时候用SQL?

如何删除除了postgres中的少数数据库之外的所有数据库

Rails:'schema.rb' 中的版本号是否用于任何用途?

字符串列上的postgresql索引

使用 Django 的复合/复合主/唯一键

SqlParameterCollection only accepts non-null SqlParameter type objects, not String objects