2012-05-04 39 views
5

Tôi cần trích xuất dữ liệu từ một số bảng ngẫu nhiên từ cơ sở dữ liệu của mình và chèn vào các bảng tương tự trong cơ sở dữ liệu khác.Trích xuất dữ liệu bằng cách sử dụng spring jdbctemplate để tải trong cơ sở dữ liệu khác

Tôi không rõ ràng làm thế nào tôi có thể viết một phương pháp chung có thể xử lý tất cả các bảng.

this.jdbcTemplate.query("select * from TableName", new RowMapper() { 
     @Override 
     public Object mapRow(ResultSet resultSet, int i) throws SQLException { 
      while(resultSet.next()){ 
//    Fetch data in a generic object for later updating in a different schema 
      } 
      return null; //To change body of implemented methods use File | Settings | File Templates. 
     } 
    }); 
+0

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? –

+0

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

Trả lời

1

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 createInsertSqlsetParameters, 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.

+0

Cảm ơn, điều này hoạt động hoàn hảo nếu tôi cần chèn các bản ghi vào bảng đích. Tôi cũng cần phải giữ một kiểm tra, nếu hồ sơ với cùng một khóa chính đã tồn tại trong bảng đích, tôi cần phải cập nhật thay vì chèn. – vikknp

+0

Xem giải thích về cách chèn hoặc cập nhật trong phần có tiêu đề ** Nhận xét sau ** ở trên. –

0

Gọi

this.jdbcTemplate.setDateSource(sourceDB) 

trước khi dữ liệu đọc

this.jdbcTemplate.setDateSource(targetDB) 

trước bằng văn bản.

Đăng ký nhiều DataSource vào mùa xuân của bạn và sử dụng một cái gì đó như thế này

@Autowired 
@Qualifier("writeDataSource") 
public void setDataSource(DataSource writeDataSource) { 
    this.jdbcTemplate = new JdbcTemplate(writeDataSource); 
} 
+0

Làm thế nào để giúp sao chép dữ liệu giữa hai cơ sở dữ liệu (khác với bạn rõ ràng là cần hai kết nối)? –

+0

Chính xác tôi biết cách tôi sẽ cấu hình nhiều nguồn dữ liệu bằng cách sử dụng mùa xuân. Nhưng làm thế nào để trích xuất dữ liệu theo cách tổng quát khi các bảng mà từ đó tôi muốn tìm nạp dữ liệu là khác nhau. – vikknp

Các vấn đề liên quan