Liquibaseを使用して(現在Excelファイルにある)多くのレコードをDBに追加しようとしています(将来のDB変更のためにそれを行う方法を知っているため)
私のアイデアは、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ファイルで:
entity.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>
これは予想される動作ですか? LiquiBaseのバグ?それとも私が何か間違ったことをしているだけですか(最も可能性が高いです)?
または、大量のデータをインポートする他の方法はありますか?ただし、常にLiquiBaseやSpringを使用します。
EDIT2:私の問題は、正しい外部キーを使用して2番目のテーブルにデータを挿入できないことです。
Liquibaseはあなたが達成したいことのための理想的なツールではないと思います。 Liquibaseは、データベースのデータではなく、データベース構造の管理に適しています。
それでもLiquibaseを使用してデータを管理したい場合は、いくつかのオプションがあります( ここ を参照)-
挿入ステートメントをSQLとして記録し、次のようにchangelog.xmlから参照します。
_<sqlFile path="/path/to/file.sql"/>
_
次のように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 から実行されます。
この操作は、文字通りデータセットの内容をデータベースに更新します。これは、既存の行のデータが更新され、存在しない行が挿入されることを意味します。データベースには存在するがデータセットには存在しない行は影響を受けません。
このようにして、参照データを1つの場所に保持し、時間の経過とともに追加して、情報のソースが1つだけになり、複数のLiquibaseチェンジセットに分割されないようにすることができます。 DBUnitデータセットをバージョン管理で維持すると、トレース機能が提供されます。また、ボーナスとして、DBUnitデータセットはデータベース間で移植可能であり、挿入順序などを管理して外部キー違反を防ぐことができます。
ターゲットデータベースによって異なります。 Sybaseまたは[〜#〜] mssql [〜#〜]サーバーを使用している場合は、 インストールされているclient + driverに付属するBCPツール 。これは、これらのデータベースに大量のデータを出し入れするための最速の方法です。
グーグルでこれらのリンクも見つけました...
Oracleには SQL * LOADER ツールがあります
MySQLには LOAD DATA INFILE コマンドがあります
私は、各データベースベンダーが、データの一括読み込みのための何らかの説明のツールを提供することを期待しています。