gpt4 book ai didi

java - 使用 LiquiBase 和 Spring 将大量值(使用 FK)插入数据库

转载 作者:IT老高 更新时间:2023-10-28 13:51:03 25 4
gpt4 key购买 nike

我正在尝试使用 Liquibase 将大量记录(当前位于 Excel 文件中)添加到我的数据库中(以便我知道如何为将来的数据库更改做这件事)

我的想法是使用 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>

或者还有其他方法吗?

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

导入数据
<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 文件:

实体.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 的 header 更改为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>

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

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

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

最佳答案

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

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

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

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

  2. 使用 Custom Refactoring Class您从 changelog.xml 中引用的内容如下:

    <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' 从类路径加载数据集并执行 DBUnit 'refresh' 操作,这将来自 docs :

This operation literally refreshes dataset contents into the database. This means that data of existing rows is updated and non-existing row get inserted. Any rows which exist in the database but not in dataset stay unaffected.

这样,您可以将引用数据保存在一个位置,并随着时间的推移添加到其中,这样信息就只有一个来源,并且不会分散到多个 Liquibase 变更集中。将您的 DBUnit 数据集保存在版本控制中将提供可追溯性,并且作为奖励,DBUnit 数据集可以跨数据库移植,并且可以管理诸如插入顺序之类的事情,以防止您违反外键。

关于java - 使用 LiquiBase 和 Spring 将大量值(使用 FK)插入数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12143994/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com