正直なところ、JdbcTemplate
この種のタスクには最適な選択ではありません。挿入SQLを作成するには、の1回限りの処理を行う必要がありますResultSet
が、これを使用してこれを実行できるポイントは実際にはありませんJdbcTemplate
(私が知る限り)。
とにかく、これは純粋なJDBCで必要なコピーを実行する方法です(必要に応じて、同じ原則を採用して圧縮することができJdbcTemplate
ます)。
Connection sourceConnection = null;
Connection destinationConnection = null;
PreparedStatement selectStatement = null;
PreparedStatement insertStatement = null;
ResultSet resultSet = null;
try
{
sourceConnection = ...
destinationConnection = ...
selectStatement = sourceConnection.prepareStatement("SELECT * FROM table");
resultSet = selectStatement.executeQuery();
insertStatement = destinationConnection.prepareStatement(createInsertSql(resultSet.getMetaData()));
int batchSize = 0;
while (resultSet.next())
{
setParameters(insertStatement, resultSet);
insertStatement.addBatch();
batchSize++;
if (batchSize >= BATCH_EXECUTE_SIZE)
{
insertStatement.executeBatch();
batchSize = 0;
}
}
insertStatement.executeBatch();
}
finally
{
JdbcUtils.closeResultSet(resultSet);
JdbcUtils.closeStatement(insertStatement);
JdbcUtils.closeStatement(selectStatement);
JdbcUtils.closeConnection(destinationConnection);
JdbcUtils.closeConnection(sourceConnection);
}
重要な点は、createInsertSql
とsetParameters
メソッドで何が起こるかです。これらは両方とも、を使用しResultSetMetaData
て操作を実行します。使用しているデータベースに応じて、これらを少し試す必要がありますが、次のようになります。
private String createInsertSql(ResultSetMetaData resultSetMetaData) throws SQLException
{
StringBuffer insertSql = new StringBuffer("INSERT INTO ");
StringBuffer values = new StringBuffer(" VALUES (");
insertSql.append(resultSetMetaData.getTableName());
for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++)
{
insertSql.append(resultSetMetaData.getColumnName(i));
values.append("?");
if (i <= resultSetMetaData.getColumnCount())
{
insertSql.append(", ");
values.append(", ");
}
else
{
insertSql.append(")");
values.append(")");
}
}
return insertSql.toString() + values.toString();
}
と:
private void setParameters(PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException
{
for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++)
{
preparedStatement.setObject(i, resultSet.getObject(i));
}
}
これは、ソースデータベースと宛先データベースに同じ構造のテーブルがある場合にのみ機能することに注意してください。それらが異なる場合は、2つの間のマッピングの定義を開始する必要があります。その時点で、ETLツールを購入する方がよいでしょう。
次のコメント
挿入/更新のことはかなり難しいです。
からDatabaseMetaData
主キーを取得し、ソーステーブルと宛先テーブルの両方にクエリを実行して、クエリが主キー列で順序付けられていることを確認する必要があります。
次に、ソース結果セットを反復処理するときに、宛先結果セットをチェックして、主キー列が順序に一致するか、それよりも大きいかどうかを確認し、それに応じて挿入または更新sqlを作成する必要があります。
たとえば、ソーステーブル1、2、3、4、7に単純な整数キーがあり、宛先テーブルに1、2、4、5、6がある場合、次のようになります。
- 1=更新
- 2=更新
- 34より前なので安全にインサートになります
- 4=更新
- 7 7が挿入であることを確実に知る前に、6を超えるまで、宛先の結果セットを繰り返す必要があります。
それがそれほど明確でない場合は申し訳ありませんが、静的なテキストで説明するのは難しいです。