Thành thật mà nói, JdbcTemplate
không phải là lựa chọn tốt nhất cho loại công việc. Bạn sẽ cần phải thực hiện một số xử lý một lần của ResultSet
để tạo SQL chèn và không thực sự có bất kỳ điểm nào bạn có thể thực hiện việc này bằng cách sử dụng JdbcTemplate
(theo như tôi biết).
Dù sao, đây là cách tôi muốn làm bản sao bạn muốn trong tinh khiết JDBC (bạn có thể mang cùng một nguyên tắc và ép nó vào JdbcTemplate
nếu bạn muốn):
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);
}
Các bit quan trọng là những gì xảy ra trong các phương pháp createInsertSql
và setParameters
, cả hai đều sử dụng ResultSetMetaData
để thực hiện các thao tác của chúng. Bạn sẽ cần phải chơi với những một chút tùy thuộc vào cơ sở dữ liệu bạn đang sử dụng nhưng họ sẽ giống như thế:
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();
}
Và:
private void setParameters(PreparedStatement preparedStatement, ResultSet resultSet) throws SQLException
{
for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++)
{
preparedStatement.setObject(i, resultSet.getObject(i));
}
}
Chú giải này chỉ hoạt động nếu nguồn và cơ sở dữ liệu đích có bảng có cấu trúc giống nhau. Nếu chúng thay đổi, bạn sẽ phải bắt đầu xác định ánh xạ giữa hai điểm, tại thời điểm đó bạn tốt hơn chỉ cần mua một công cụ ETL.
Sau Comment
Các chèn/cập nhật điều là khá nhiều khó khăn hơn.
Từ DatabaseMetaData
bạn cần lấy khóa chính và truy vấn cả bảng nguồn và đích để đảm bảo các lệnh truy vấn theo các cột khóa chính. Sau đó, khi bạn lặp lại tập hợp kết quả nguồn, bạn cần kiểm tra tập hợp kết quả đích để xem các cột khóa chính có khớp hay lớn hơn theo thứ tự, tạo chèn hoặc cập nhật sql theo đúng.
Ví dụ, nếu bạn có các phím số nguyên đơn giản trong bảng nguồn 1, 2, 3, 4, 7 và trong bảng đích bạn có 1, 2, 4, 5, 6 thì:
- 1 = cập nhật
- 2 = cập nhật
- 3 vì nó trước 4 một cách an toàn có thể là một chèn
- 4 = cập nhật
- 7 bạn cần phải lặp kết quả thiết lập điểm đến cho đến khi bạn đã đi qua 6 trước khi bạn có thể biết chắc chắn rằng 7 là một chèn.
Xin lỗi nếu điều đó không rõ ràng, thật khó để giải thích bằng văn bản tĩnh.
Vui lòng xác định ý bạn là gì bởi 'các bảng tương tự' - chúng có cùng cấu trúc và khác biệt duy nhất là cơ sở dữ liệu chúng có trong hoặc cấu trúc khác nhau không? –
Cấu trúc giống nhau. Ví dụ tôi có các bảng A, B, C trong DB1, tất cả đều có cấu trúc khác nhau và tôi cần lưu trữ các bảng này vào DB2 có các bảng A, B và C. – vikknp