Per essere onesti, JdbcTemplate
non è la scelta migliore per questo tipo di compito. È necessario eseguire una singola elaborazione di ResultSet
per creare l'SQL di inserimento e non c'è alcun punto in cui è possibile farlo utilizzando JdbcTemplate
(per quanto ne so).
In ogni caso, questo è come mi piacerebbe fare la copia che si desidera in puro JDBC (si può prendere gli stessi principi e spremere in JdbcTemplate
se si vuole):
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);
}
Il bit importante è quello che avviene nei metodi createInsertSql
e setParameters
, che utilizzano entrambi lo ResultSetMetaData
per eseguire le loro operazioni. Avrete bisogno di giocare con questi un po 'a seconda del database che si sta utilizzando, ma ti guarda qualcosa di simile:
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();
}
E:
private void setParameters(PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException
{
for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++)
{
preparedStatement.setObject(i, resultSet.getObject(i));
}
}
notare che questo funziona solo se l'origine e la i database di destinazione hanno tabelle strutturate in modo identico. Se variano, dovrai iniziare a definire i mapping tra i due, a quel punto starai meglio acquistando uno strumento ETL.
seguente commento
L'inserimento/aggiornamento cosa è abbastanza molto più difficile.
Da DatabaseMetaData
è necessario ottenere la chiave primaria e interrogare sia le tabelle di origine che di destinazione assicurandosi che gli ordini di query siano eseguiti dalle colonne della chiave primaria.
Quindi, mentre si esegue l'iterazione sul set di risultati di origine, è necessario controllare il set di risultati di destinazione per verificare se le colonne della chiave primaria corrispondono o sono più grandi nell'ordinare, creando in modo inserto o aggiornamento sql in modo coerente.
Ad esempio se si ha semplici chiavi intere nella tabella sorgente 1, 2, 3, 4, 7 e nella tabella di destinazione si aveva 1, 2, 4, 5, 6 allora:
- 1 = aggiornare
- 2 = aggiornamento
- 3 perché è prima di 4 può tranquillamente essere un inserto
- 4 = aggiornamento
- 7 è necessario scorrere il set di risultati di destinazione prima che siano trascorse oltre 6 prima di poter sapere per certo che 7 è un inserto.
Scusate se non è chiaro, è difficile da spiegare nel testo statico.
Si prega di definire cosa si intende per "tabelle simili" - hanno la stessa struttura e l'unica differenza è il database in cui si trovano o la struttura è diversa? –
Stessa struttura. Ad esempio, ho tabelle A, B, C in DB1 che hanno tutte una struttura diversa, e ho bisogno di archiviare queste tabelle in DB2 che ha le tabelle A, B e C. – vikknp