Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>To be honest, <code>JdbcTemplate</code> isn't the best choice for this sort of task. You'll need to do some one-time processing of the <code>ResultSet</code> to create the insert SQL and there's not really any point you can do this using <code>JdbcTemplate</code> (as far as I know).</p> <p>Anyway, this is how I'd do the copy you want in pure JDBC (you can take the same principles and squeeze it into <code>JdbcTemplate</code> if you want to):</p> <pre><code>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 &gt;= 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); } </code></pre> <p>The important bit is what happens in the <code>createInsertSql</code> and <code>setParameters</code> methods, which both use the <code>ResultSetMetaData</code> to perform their operations. You'll need to play with these a bit depending on the database you're using but they'll look something like:</p> <pre><code>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 &lt;= resultSetMetaData.getColumnCount(); i++) { insertSql.append(resultSetMetaData.getColumnName(i)); values.append("?"); if (i &lt;= resultSetMetaData.getColumnCount()) { insertSql.append(", "); values.append(", "); } else { insertSql.append(")"); values.append(")"); } } return insertSql.toString() + values.toString(); } </code></pre> <p>And:</p> <pre><code>private void setParameters(PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException { for (int i = 1; i &lt;= resultSet.getMetaData().getColumnCount(); i++) { preparedStatement.setObject(i, resultSet.getObject(i)); } } </code></pre> <p>Note this only works if the source and destination databases have identically structured tables. If they vary you'll have to start defining mappings between the two, at which point you're better off just buying an ETL tool.</p> <p><strong>Following Comment</strong></p> <p>The insert/update thing is quite a lot harder. </p> <p>From the <code>DatabaseMetaData</code> you'd need to get the primary key and query both the source and destination tables making sure the query orders by the primary key columns. </p> <p>Then as you iterate over the source result set you'd need to check the destination result set to see if the primary key columns match or are greater in ordering, creating insert or update sql accordingingly. </p> <p>For example if you had simple integer keys in the source table 1, 2, 3, 4, 7 and in the destination table you had 1, 2, 4, 5, 6 then:</p> <ul> <li>1 = update</li> <li>2 = update</li> <li>3 because it's before 4 can safely be an insert</li> <li>4 = update </li> <li>7 you need to iterate the destination result set until you've gone past 6 before you can know for certain that 7 is an insert. </li> </ul> <p>Sorry if that's not that clear, it's hard to explain in static text.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload