首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用LiquiBase和Spring将许多值(使用FK)插入数据库

使用LiquiBase和Spring将许多值(使用FK)插入数据库
EN

Stack Overflow用户
提问于 2012-08-27 22:28:20
回答 2查看 24.9K关注 0票数 21

我正在尝试使用Liquibase将许多记录(当前位于Excel文件中)添加到我的数据库中(以便我知道如何在将来的数据库更改中执行此操作)

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

代码语言:javascript
复制
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会非常奇怪(并且没有效率)

代码语言:javascript
复制
<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>

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

代码语言:javascript
复制
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>

还有没有别的办法?

编辑:我当前的选择是将Excel转换为CSV文件并使用

代码语言:javascript
复制
<changeSet author="gcardoso" id="InitialImport2" runOnChange="true">

    <loadData tableName="T_ENTITY" file="com/exictos/dbUpdate/entity.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文件:

entity.csv

代码语言:javascript
复制
SHORTNAME,DESCRIPTION
nome1,descricao1
nome2,descricao2

client.csv

代码语言:javascript
复制
DESCRIPTION,ENTITY_REFERENCE
descricaoCliente1,nome1
descricaoCliente2,nome2

但是我得到了这个错误:

代码语言:javascript
复制
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,我会收到以下错误:

代码语言:javascript
复制
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不同

代码语言:javascript
复制
<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>

这是预期的行为吗?LiquiBase的Bug?或者仅仅是我做错了什么(最有可能的)?

或者,有没有其他方法可以导入大量数据?但是总是使用LiquiBase和/或Spring。

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-31 15:42:01

我想说Liquibase不是你想要实现的理想工具。Liquibase非常适合于管理数据库结构,而不是数据库的数据。

如果你仍然想使用Liquibase来管理数据,你有几个选择(参见here) -

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

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

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

YourJavaClass将从CSV文件中读取记录,并将它们应用于数据库,实现以下方法:

void execute(Database database) throws CustomChangeException;

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

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

此操作从字面上将数据集内容刷新到数据库。这意味着更新现有行的数据,并插入不存在的行。存在于数据库中但不在数据集中的任何行都不受影响。

这样,您可以将引用数据保存在一个位置,并随着时间的推移添加到其中,以便只有一个信息源,而不会在多个Liquibase变更集之间拆分。将您的DBUnit数据集保持在版本控制中将提供跟踪能力,并且DBUnit数据集可以跨数据库移植,并且可以管理插入顺序等内容,以防止违反外键。

票数 11
EN

Stack Overflow用户

发布于 2012-08-31 00:47:58

这取决于您的目标数据库。如果您使用的是SybaseMSSQL,那么您可以使用随已安装的client+driver一起提供的BCP tool。这是将大量数据移入/移出这些数据库的最快方法。

我在谷歌上也找到了这些链接……

甲骨文提供了SQL*LOADER工具

MySQL具有LOAD DATA INFILE命令

我希望每个数据库供应商都能提供某种描述的工具来批量加载数据。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12143994

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档